From e8287dfda9159acffc434432a31b6c0b671aa83e Mon Sep 17 00:00:00 2001 From: Sam Morrison Date: Mon, 19 Sep 2016 11:41:22 +1000 Subject: [PATCH] Pass availability zone through to volume creation. New config option `enable_volume_az` (defaults to false) ensures that the instance and volume will be created in the same availability zone. Story: 2008313 Task: 41208 Change-Id: I62ea46991c7398fba4e5027d5170038624d5aec9 --- ...add-cinder-az-option-d4ff1968e6064ff2.yaml | 5 ++++ trove/common/cfg.py | 6 +++- trove/taskmanager/models.py | 28 ++++++++++++------- trove/tests/fakes/nova.py | 12 ++++---- .../unittests/taskmanager/test_models.py | 4 +-- 5 files changed, 35 insertions(+), 20 deletions(-) create mode 100644 releasenotes/notes/add-cinder-az-option-d4ff1968e6064ff2.yaml diff --git a/releasenotes/notes/add-cinder-az-option-d4ff1968e6064ff2.yaml b/releasenotes/notes/add-cinder-az-option-d4ff1968e6064ff2.yaml new file mode 100644 index 0000000000..4fff591fef --- /dev/null +++ b/releasenotes/notes/add-cinder-az-option-d4ff1968e6064ff2.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Added the ability to create the cinder volume in the same AZ as the nova + instance. Set ``enable_volume_az`` to True (defaults to False) diff --git a/trove/common/cfg.py b/trove/common/cfg.py index 27e196ad58..6109a3598e 100644 --- a/trove/common/cfg.py +++ b/trove/common/cfg.py @@ -507,7 +507,11 @@ common_opts = [ 'management.'), cfg.BoolOpt( 'online_volume_resize', default=True, - help='If online volume resize is supported.') + help='If online volume resize is supported.'), + cfg.BoolOpt( + 'enable_volume_az', default=False, + help='If true create the volume in the same availability-zone as the ' + 'instance'), ] diff --git a/trove/taskmanager/models.py b/trove/taskmanager/models.py index df62966715..6703e8a4c8 100755 --- a/trove/taskmanager/models.py +++ b/trove/taskmanager/models.py @@ -822,9 +822,11 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin): volume_type, scheduler_hints): LOG.debug("Begin _create_server_volume for id: %s", self.id) server = None - volume_info = self._build_volume_info(datastore_manager, - volume_size=volume_size, - volume_type=volume_type) + volume_info = self._build_volume_info( + datastore_manager, + volume_size=volume_size, + volume_type=volume_type, + availability_zone=availability_zone) block_device_mapping_v2 = volume_info['block_device'] try: server = self._create_server( @@ -846,7 +848,7 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin): return volume_info def _build_volume_info(self, datastore_manager, volume_size=None, - volume_type=None): + volume_type=None, availability_zone=None): volume_info = None volume_support = self.volume_support device_path = self.device_path @@ -855,7 +857,8 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin): if volume_support: try: volume_info = self._create_volume( - volume_size, volume_type, datastore_manager) + volume_size, volume_type, datastore_manager, + availability_zone) except Exception as e: log_fmt = "Failed to create volume for instance %s" exc_fmt = _("Failed to create volume for instance %s") @@ -890,14 +893,19 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin): full_message = "%s%s" % (exc_fmt % fmt_content, exc_message) raise TroveError(message=full_message) - def _create_volume(self, volume_size, volume_type, datastore_manager): + def _create_volume(self, volume_size, volume_type, datastore_manager, + availability_zone): LOG.debug("Begin _create_volume for id: %s", self.id) volume_client = create_cinder_client(self.context, self.region_name) volume_desc = ("datastore volume for %s" % self.id) - volume_ref = volume_client.volumes.create( - volume_size, name="trove-%s" % self.id, - description=volume_desc, - volume_type=volume_type) + volume_kwargs = { + 'size': volume_size, + 'name': "trove-%s" % self.id, + 'description': volume_desc, + 'volume_type': volume_type} + if CONF.enable_volume_az: + volume_kwargs['availability_zone'] = availability_zone + volume_ref = volume_client.volumes.create(**volume_kwargs) # Record the volume ID in case something goes wrong. self.update_db(volume_id=volume_ref.id) diff --git a/trove/tests/fakes/nova.py b/trove/tests/fakes/nova.py index cc896c5c55..a077914745 100644 --- a/trove/tests/fakes/nova.py +++ b/trove/tests/fakes/nova.py @@ -358,7 +358,7 @@ class FakeRdServers(object): class FakeVolume(object): def __init__(self, parent, owner, id, size, name, - description, volume_type): + description, volume_type, availability_zone): self.attachments = [] self.parent = parent self.owner = owner # This is a context. @@ -371,6 +371,7 @@ class FakeVolume(object): # point. self.device = "vdb" self.volume_type = volume_type + self.availability_zone = availability_zone def __repr__(self): msg = ("FakeVolume(id=%s, size=%s, name=%s, " @@ -379,10 +380,6 @@ class FakeVolume(object): self.description, self._current_status) return (msg % params) - @property - def availability_zone(self): - return "fake-availability-zone" - @property def created_at(self): return "2001-01-01-12:30:30" @@ -445,10 +442,11 @@ class FakeVolumes(object): else: raise nova_exceptions.NotFound(404, "Bad permissions") - def create(self, size, name=None, description=None, volume_type=None): + def create(self, size, name=None, description=None, volume_type=None, + availability_zone=None): id = "FAKE_VOL_%s" % uuid.uuid4() volume = FakeVolume(self, self.context, id, size, name, - description, volume_type) + description, volume_type, availability_zone) self.db[id] = volume if size == 9: volume.schedule_status("error", 2) diff --git a/trove/tests/unittests/taskmanager/test_models.py b/trove/tests/unittests/taskmanager/test_models.py index 1db929ded7..353f82f4b2 100644 --- a/trove/tests/unittests/taskmanager/test_models.py +++ b/trove/tests/unittests/taskmanager/test_models.py @@ -386,7 +386,7 @@ class FreshInstanceTasksTest(BaseFreshInstanceTasksTest): is_public=False ) mock_build_volume_info.assert_called_with( - 'mysql', volume_size=2, + 'mysql', availability_zone=None, volume_size=2, volume_type='volume_type' ) mock_guest_prepare.assert_called_with( @@ -457,7 +457,7 @@ class FreshInstanceTasksTest(BaseFreshInstanceTasksTest): ) mock_build_volume_info.assert_called_with( - 'mysql', volume_size=2, + 'mysql', availability_zone=None, volume_size=2, volume_type='volume_type' ) mock_guest_prepare.assert_called_with(