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
This commit is contained in:
Sam Morrison 2016-09-19 11:41:22 +10:00 committed by Lingxian Kong
parent 59a972b312
commit e8287dfda9
5 changed files with 35 additions and 20 deletions

View File

@ -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)

View File

@ -507,7 +507,11 @@ common_opts = [
'management.'), 'management.'),
cfg.BoolOpt( cfg.BoolOpt(
'online_volume_resize', default=True, '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'),
] ]

View File

@ -822,9 +822,11 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
volume_type, scheduler_hints): volume_type, scheduler_hints):
LOG.debug("Begin _create_server_volume for id: %s", self.id) LOG.debug("Begin _create_server_volume for id: %s", self.id)
server = None server = None
volume_info = self._build_volume_info(datastore_manager, volume_info = self._build_volume_info(
volume_size=volume_size, datastore_manager,
volume_type=volume_type) volume_size=volume_size,
volume_type=volume_type,
availability_zone=availability_zone)
block_device_mapping_v2 = volume_info['block_device'] block_device_mapping_v2 = volume_info['block_device']
try: try:
server = self._create_server( server = self._create_server(
@ -846,7 +848,7 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
return volume_info return volume_info
def _build_volume_info(self, datastore_manager, volume_size=None, def _build_volume_info(self, datastore_manager, volume_size=None,
volume_type=None): volume_type=None, availability_zone=None):
volume_info = None volume_info = None
volume_support = self.volume_support volume_support = self.volume_support
device_path = self.device_path device_path = self.device_path
@ -855,7 +857,8 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
if volume_support: if volume_support:
try: try:
volume_info = self._create_volume( volume_info = self._create_volume(
volume_size, volume_type, datastore_manager) volume_size, volume_type, datastore_manager,
availability_zone)
except Exception as e: except Exception as e:
log_fmt = "Failed to create volume for instance %s" log_fmt = "Failed to create volume for instance %s"
exc_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) full_message = "%s%s" % (exc_fmt % fmt_content, exc_message)
raise TroveError(message=full_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) LOG.debug("Begin _create_volume for id: %s", self.id)
volume_client = create_cinder_client(self.context, self.region_name) volume_client = create_cinder_client(self.context, self.region_name)
volume_desc = ("datastore volume for %s" % self.id) volume_desc = ("datastore volume for %s" % self.id)
volume_ref = volume_client.volumes.create( volume_kwargs = {
volume_size, name="trove-%s" % self.id, 'size': volume_size,
description=volume_desc, 'name': "trove-%s" % self.id,
volume_type=volume_type) '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. # Record the volume ID in case something goes wrong.
self.update_db(volume_id=volume_ref.id) self.update_db(volume_id=volume_ref.id)

View File

@ -358,7 +358,7 @@ class FakeRdServers(object):
class FakeVolume(object): class FakeVolume(object):
def __init__(self, parent, owner, id, size, name, def __init__(self, parent, owner, id, size, name,
description, volume_type): description, volume_type, availability_zone):
self.attachments = [] self.attachments = []
self.parent = parent self.parent = parent
self.owner = owner # This is a context. self.owner = owner # This is a context.
@ -371,6 +371,7 @@ class FakeVolume(object):
# point. # point.
self.device = "vdb" self.device = "vdb"
self.volume_type = volume_type self.volume_type = volume_type
self.availability_zone = availability_zone
def __repr__(self): def __repr__(self):
msg = ("FakeVolume(id=%s, size=%s, name=%s, " msg = ("FakeVolume(id=%s, size=%s, name=%s, "
@ -379,10 +380,6 @@ class FakeVolume(object):
self.description, self._current_status) self.description, self._current_status)
return (msg % params) return (msg % params)
@property
def availability_zone(self):
return "fake-availability-zone"
@property @property
def created_at(self): def created_at(self):
return "2001-01-01-12:30:30" return "2001-01-01-12:30:30"
@ -445,10 +442,11 @@ class FakeVolumes(object):
else: else:
raise nova_exceptions.NotFound(404, "Bad permissions") 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() id = "FAKE_VOL_%s" % uuid.uuid4()
volume = FakeVolume(self, self.context, id, size, name, volume = FakeVolume(self, self.context, id, size, name,
description, volume_type) description, volume_type, availability_zone)
self.db[id] = volume self.db[id] = volume
if size == 9: if size == 9:
volume.schedule_status("error", 2) volume.schedule_status("error", 2)

View File

@ -386,7 +386,7 @@ class FreshInstanceTasksTest(BaseFreshInstanceTasksTest):
is_public=False is_public=False
) )
mock_build_volume_info.assert_called_with( mock_build_volume_info.assert_called_with(
'mysql', volume_size=2, 'mysql', availability_zone=None, volume_size=2,
volume_type='volume_type' volume_type='volume_type'
) )
mock_guest_prepare.assert_called_with( mock_guest_prepare.assert_called_with(
@ -457,7 +457,7 @@ class FreshInstanceTasksTest(BaseFreshInstanceTasksTest):
) )
mock_build_volume_info.assert_called_with( mock_build_volume_info.assert_called_with(
'mysql', volume_size=2, 'mysql', availability_zone=None, volume_size=2,
volume_type='volume_type' volume_type='volume_type'
) )
mock_guest_prepare.assert_called_with( mock_guest_prepare.assert_called_with(