summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Freudberg <jeremyfreudberg@gmail.com>2019-01-07 20:36:05 -0500
committerJeremy Freudberg <jeremyfreudberg@gmail.com>2019-01-07 20:36:05 -0500
commit359b89de3ff105c78aec189650d2feabfbb07ae8 (patch)
tree235a76163571b0ae7fb42b9ac405591e38154497
parent0b8002a99d800412268dd9f5796f08aeacb9974c (diff)
Enhance boot from volume
Attached volumes already had support for explicit volume type, availability zone, and instance locality. Extend this capability to boot volumes. (For posterity's sake, a summary of why other options related to attached volumes were not in fact appropriate for boot volumes: - volumes_per_node: there can only be one boot volume - volumes_size: boot volume size given by flavor - volume_mount_prefix: boot volume handled differently) Change-Id: I009c0da4179c880fd87a7c1903c93825e8997a38 Story: 2004507 Task: 28229
Notes
Notes (review): Code-Review+2: Telles Mota Vidal Nóbrega <tenobreg@redhat.com> Code-Review+2: Luigi Toscano <ltoscano@redhat.com> Workflow+1: Luigi Toscano <ltoscano@redhat.com> Verified+2: Zuul Submitted-by: Zuul Submitted-at: Tue, 08 Jan 2019 15:40:52 +0000 Reviewed-on: https://review.openstack.org/629079 Project: openstack/sahara Branch: refs/heads/master
-rw-r--r--releasenotes/notes/enhance-bfv-12bac06c4438675f.yaml6
-rw-r--r--sahara/conductor/manager.py3
-rw-r--r--sahara/conductor/objects.py9
-rw-r--r--sahara/db/migration/alembic_migrations/versions/035_boot_from_volume_enhancements.py70
-rw-r--r--sahara/db/sqlalchemy/models.py9
-rw-r--r--sahara/service/heat/templates.py21
-rw-r--r--sahara/service/validations/node_group_template_schema.py9
-rw-r--r--sahara/tests/unit/conductor/manager/test_clusters.py3
-rw-r--r--sahara/tests/unit/conductor/manager/test_templates.py3
-rw-r--r--sahara/tests/unit/db/migration/test_migrations.py8
10 files changed, 137 insertions, 4 deletions
diff --git a/releasenotes/notes/enhance-bfv-12bac06c4438675f.yaml b/releasenotes/notes/enhance-bfv-12bac06c4438675f.yaml
new file mode 100644
index 0000000..0318b28
--- /dev/null
+++ b/releasenotes/notes/enhance-bfv-12bac06c4438675f.yaml
@@ -0,0 +1,6 @@
1---
2features:
3 - In Sahara APIv2, the type, availability zone, and locality of boot volumes
4 may be expressed explicitly through the `boot_volume_type`,
5 `boot_volume_availability_zone`, and `boot_volume_local_to_instance`
6 parameters.
diff --git a/sahara/conductor/manager.py b/sahara/conductor/manager.py
index c57b083..64f42f6 100644
--- a/sahara/conductor/manager.py
+++ b/sahara/conductor/manager.py
@@ -51,6 +51,9 @@ NODE_GROUP_DEFAULTS = {
51 "volume_mount_prefix": "/volumes/disk", 51 "volume_mount_prefix": "/volumes/disk",
52 "volume_type": None, 52 "volume_type": None,
53 "boot_from_volume": False, 53 "boot_from_volume": False,
54 "boot_volume_type": None,
55 "boot_volume_availability_zone": None,
56 "boot_volume_local_to_instance": False,
54 "floating_ip_pool": None, 57 "floating_ip_pool": None,
55 "security_groups": None, 58 "security_groups": None,
56 "auto_security_group": False, 59 "auto_security_group": False,
diff --git a/sahara/conductor/objects.py b/sahara/conductor/objects.py
index eba7ffb..989a0e8 100644
--- a/sahara/conductor/objects.py
+++ b/sahara/conductor/objects.py
@@ -112,6 +112,12 @@ class NodeGroup(object):
112 volume_type 112 volume_type
113 boot_from_volume - If set to True, the base image will be converted to a 113 boot_from_volume - If set to True, the base image will be converted to a
114 bootable volume. 114 bootable volume.
115 boot_volume_type
116 boot_volume_availability_zone - name of Cinder availability zone for
117 spawning bootable volume.
118 boot_volume_local_to_instance - indicates if boot volume and instance
119 should be c reated on the same physical
120 host.
115 floating_ip_pool - Floating IP Pool name used to assign Floating IPs to 121 floating_ip_pool - Floating IP Pool name used to assign Floating IPs to
116 instances in this Node Group 122 instances in this Node Group
117 security_groups - List of security groups for instances in this Node Group 123 security_groups - List of security groups for instances in this Node Group
@@ -234,6 +240,9 @@ class NodeGroupTemplate(object):
234 volume_mount_prefix 240 volume_mount_prefix
235 volume_type 241 volume_type
236 boot_from_volume 242 boot_from_volume
243 boot_volume_type
244 boot_volume_availability_zone
245 boot_volume_local_to_instance
237 floating_ip_pool 246 floating_ip_pool
238 security_groups 247 security_groups
239 auto_security_group 248 auto_security_group
diff --git a/sahara/db/migration/alembic_migrations/versions/035_boot_from_volume_enhancements.py b/sahara/db/migration/alembic_migrations/versions/035_boot_from_volume_enhancements.py
new file mode 100644
index 0000000..a6a8c57
--- /dev/null
+++ b/sahara/db/migration/alembic_migrations/versions/035_boot_from_volume_enhancements.py
@@ -0,0 +1,70 @@
1# Copyright 2019 OpenStack Foundation.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12# implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16"""boot from volume enhancements
17
18Revision ID: 035
19Revises: 034
20Create Date: 2019-01-07 19:55:54.025736
21
22"""
23
24# revision identifiers, used by Alembic.
25revision = '035'
26down_revision = '034'
27
28from alembic import op
29import sqlalchemy as sa
30
31
32def upgrade():
33 op.add_column('node_group_templates',
34 sa.Column('boot_volume_availability_zone',
35 sa.String(length=255),
36 nullable=True))
37 op.add_column('node_group_templates',
38 sa.Column('boot_volume_local_to_instance',
39 sa.Boolean(),
40 nullable=True))
41 op.add_column('node_group_templates',
42 sa.Column('boot_volume_type',
43 sa.String(length=255),
44 nullable=True))
45
46 op.add_column('node_groups',
47 sa.Column('boot_volume_availability_zone',
48 sa.String(length=255),
49 nullable=True))
50 op.add_column('node_groups',
51 sa.Column('boot_volume_local_to_instance',
52 sa.Boolean(),
53 nullable=True))
54 op.add_column('node_groups',
55 sa.Column('boot_volume_type',
56 sa.String(length=255),
57 nullable=True))
58
59 op.add_column('templates_relations',
60 sa.Column('boot_volume_availability_zone',
61 sa.String(length=255),
62 nullable=True))
63 op.add_column('templates_relations',
64 sa.Column('boot_volume_local_to_instance',
65 sa.Boolean(),
66 nullable=True))
67 op.add_column('templates_relations',
68 sa.Column('boot_volume_type',
69 sa.String(length=255),
70 nullable=True))
diff --git a/sahara/db/sqlalchemy/models.py b/sahara/db/sqlalchemy/models.py
index ad62e1b..acf204e 100644
--- a/sahara/db/sqlalchemy/models.py
+++ b/sahara/db/sqlalchemy/models.py
@@ -118,6 +118,9 @@ class NodeGroup(mb.SaharaBase):
118 volume_mount_prefix = sa.Column(sa.String(80)) 118 volume_mount_prefix = sa.Column(sa.String(80))
119 volume_type = sa.Column(sa.String(255)) 119 volume_type = sa.Column(sa.String(255))
120 boot_from_volume = sa.Column(sa.Boolean(), default=False, nullable=False) 120 boot_from_volume = sa.Column(sa.Boolean(), default=False, nullable=False)
121 boot_volume_type = sa.Column(sa.String(255))
122 boot_volume_availability_zone = sa.Column(sa.String(255))
123 boot_volume_local_to_instance = sa.Column(sa.Boolean())
121 count = sa.Column(sa.Integer, nullable=False) 124 count = sa.Column(sa.Integer, nullable=False)
122 use_autoconfig = sa.Column(sa.Boolean(), default=True) 125 use_autoconfig = sa.Column(sa.Boolean(), default=True)
123 126
@@ -230,6 +233,9 @@ class NodeGroupTemplate(mb.SaharaBase):
230 volume_mount_prefix = sa.Column(sa.String(80)) 233 volume_mount_prefix = sa.Column(sa.String(80))
231 volume_type = sa.Column(sa.String(255)) 234 volume_type = sa.Column(sa.String(255))
232 boot_from_volume = sa.Column(sa.Boolean(), default=False, nullable=False) 235 boot_from_volume = sa.Column(sa.Boolean(), default=False, nullable=False)
236 boot_volume_type = sa.Column(sa.String(255))
237 boot_volume_availability_zone = sa.Column(sa.String(255))
238 boot_volume_local_to_instance = sa.Column(sa.Boolean())
233 floating_ip_pool = sa.Column(sa.String(36)) 239 floating_ip_pool = sa.Column(sa.String(36))
234 security_groups = sa.Column(st.JsonListType()) 240 security_groups = sa.Column(st.JsonListType())
235 auto_security_group = sa.Column(sa.Boolean()) 241 auto_security_group = sa.Column(sa.Boolean())
@@ -264,6 +270,9 @@ class TemplatesRelation(mb.SaharaBase):
264 volume_mount_prefix = sa.Column(sa.String(80)) 270 volume_mount_prefix = sa.Column(sa.String(80))
265 volume_type = sa.Column(sa.String(255)) 271 volume_type = sa.Column(sa.String(255))
266 boot_from_volume = sa.Column(sa.Boolean(), default=False, nullable=False) 272 boot_from_volume = sa.Column(sa.Boolean(), default=False, nullable=False)
273 boot_volume_type = sa.Column(sa.String(255))
274 boot_volume_availability_zone = sa.Column(sa.String(255))
275 boot_volume_local_to_instance = sa.Column(sa.Boolean())
267 count = sa.Column(sa.Integer, nullable=False) 276 count = sa.Column(sa.Integer, nullable=False)
268 use_autoconfig = sa.Column(sa.Boolean(), default=True) 277 use_autoconfig = sa.Column(sa.Boolean(), default=True)
269 cluster_template_id = sa.Column(sa.String(36), 278 cluster_template_id = sa.Column(sa.String(36),
diff --git a/sahara/service/heat/templates.py b/sahara/service/heat/templates.py
index 7bbaacb..44c6759 100644
--- a/sahara/service/heat/templates.py
+++ b/sahara/service/heat/templates.py
@@ -544,13 +544,26 @@ class ClusterStack(object):
544 node_group_flavor = nova.get_flavor(id=node_group.flavor_id) 544 node_group_flavor = nova.get_flavor(id=node_group.flavor_id)
545 image_size = node_group_flavor.disk 545 image_size = node_group_flavor.disk
546 546
547 properties = {}
548 properties["size"] = image_size
549 properties["image"] = node_group.get_image_id()
550
551 if node_group.boot_volume_type:
552 properties["volume_type"] = node_group.boot_volume_type
553
554 if node_group.boot_volume_availability_zone:
555 properties["availability_zone"] = (
556 node_group.boot_volume_availability_zone
557 )
558
559 if node_group.boot_volume_local_to_instance:
560 properties["scheduler_hints"] = {
561 "local_to_instance": {"get_param": "instance"}}
562
547 return { 563 return {
548 "bootable_volume": { 564 "bootable_volume": {
549 "type": "OS::Cinder::Volume", 565 "type": "OS::Cinder::Volume",
550 "properties": { 566 "properties": properties
551 "size": image_size,
552 "image": node_group.get_image_id()
553 }
554 } 567 }
555 } 568 }
556 569
diff --git a/sahara/service/validations/node_group_template_schema.py b/sahara/service/validations/node_group_template_schema.py
index b8badfe..c0e3598 100644
--- a/sahara/service/validations/node_group_template_schema.py
+++ b/sahara/service/validations/node_group_template_schema.py
@@ -122,6 +122,15 @@ NODE_GROUP_TEMPLATE_SCHEMA_V2["required"].append("plugin_version")
122NODE_GROUP_TEMPLATE_SCHEMA_V2["properties"].update({ 122NODE_GROUP_TEMPLATE_SCHEMA_V2["properties"].update({
123 "boot_from_volume": { 123 "boot_from_volume": {
124 "type": "boolean", 124 "type": "boolean",
125 },
126 "boot_volume_type": {
127 "type": "string",
128 },
129 "boot_volume_availability_zone": {
130 "type": "string",
131 },
132 "boot_volume_local_to_instance": {
133 "type": "boolean",
125 }}) 134 }})
126 135
127 136
diff --git a/sahara/tests/unit/conductor/manager/test_clusters.py b/sahara/tests/unit/conductor/manager/test_clusters.py
index a8c908e..83b737e 100644
--- a/sahara/tests/unit/conductor/manager/test_clusters.py
+++ b/sahara/tests/unit/conductor/manager/test_clusters.py
@@ -133,6 +133,9 @@ class ClusterTest(test_base.ConductorManagerTestCase):
133 ng.pop("volume_type") 133 ng.pop("volume_type")
134 ng.pop("floating_ip_pool") 134 ng.pop("floating_ip_pool")
135 ng.pop("boot_from_volume") 135 ng.pop("boot_from_volume")
136 ng.pop("boot_volume_type")
137 ng.pop("boot_volume_availability_zone")
138 ng.pop("boot_volume_local_to_instance")
136 ng.pop("image_username") 139 ng.pop("image_username")
137 ng.pop("open_ports") 140 ng.pop("open_ports")
138 ng.pop("auto_security_group") 141 ng.pop("auto_security_group")
diff --git a/sahara/tests/unit/conductor/manager/test_templates.py b/sahara/tests/unit/conductor/manager/test_templates.py
index 09c1242..c776bd3 100644
--- a/sahara/tests/unit/conductor/manager/test_templates.py
+++ b/sahara/tests/unit/conductor/manager/test_templates.py
@@ -459,6 +459,9 @@ class ClusterTemplates(test_base.ConductorManagerTestCase):
459 ng.pop("auto_security_group") 459 ng.pop("auto_security_group")
460 ng.pop("is_proxy_gateway") 460 ng.pop("is_proxy_gateway")
461 ng.pop("boot_from_volume") 461 ng.pop("boot_from_volume")
462 ng.pop("boot_volume_type")
463 ng.pop("boot_volume_availability_zone")
464 ng.pop("boot_volume_local_to_instance")
462 ng.pop('volume_local_to_instance') 465 ng.pop('volume_local_to_instance')
463 466
464 self.assertEqual(SAMPLE_CLT["node_groups"], 467 self.assertEqual(SAMPLE_CLT["node_groups"],
diff --git a/sahara/tests/unit/db/migration/test_migrations.py b/sahara/tests/unit/db/migration/test_migrations.py
index 139d778..c9f5b1f 100644
--- a/sahara/tests/unit/db/migration/test_migrations.py
+++ b/sahara/tests/unit/db/migration/test_migrations.py
@@ -634,6 +634,14 @@ class SaharaMigrationsCheckers(object):
634 self.assertColumnExists(engine, 'templates_relations', 634 self.assertColumnExists(engine, 'templates_relations',
635 'boot_from_volume') 635 'boot_from_volume')
636 636
637 def _check_035(self, engine, data):
638 for col in ['boot_volume_type',
639 'boot_volume_availability_zone',
640 'boot_volume_local_to_instance']:
641 self.assertColumnExists(engine, 'node_groups', col)
642 self.assertColumnExists(engine, 'node_group_templates', col)
643 self.assertColumnExists(engine, 'templates_relations', col)
644
637 645
638class TestMigrationsMySQL(SaharaMigrationsCheckers, 646class TestMigrationsMySQL(SaharaMigrationsCheckers,
639 base.BaseWalkMigrationTestCase, 647 base.BaseWalkMigrationTestCase,