Adds allow_availability_zone_fallback option to Cinder
This change adds allow_availability_zone_fallback, which allows Cinder to fall back to an already configured availability zone if the requested availability zone is unavailable. Change-Id: Id6b43fc3243b4de82241cfab34ff10953b537874 DocImpact: cinder Closes-Bug: #1489575
This commit is contained in:
parent
6dba657a29
commit
b85d2812a8
|
@ -140,6 +140,12 @@ global_opts = [
|
|||
help='Default availability zone for new volumes. If not set, '
|
||||
'the storage_availability_zone option value is used as '
|
||||
'the default for new volumes.'),
|
||||
cfg.BoolOpt('allow_availability_zone_fallback',
|
||||
default=False,
|
||||
help='If the requested Cinder availability zone is '
|
||||
'unavailable, fall back to the value of '
|
||||
'default_availability_zone, then '
|
||||
'storage_availability_zone, instead of failing.'),
|
||||
cfg.StrOpt('default_volume_type',
|
||||
default=None,
|
||||
help='Default volume type to use'),
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
import mock
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from cinder import context
|
||||
from cinder import exception
|
||||
from cinder.openstack.common import imageutils
|
||||
|
@ -30,6 +32,8 @@ from cinder.tests.unit.volume.flows import fake_volume_api
|
|||
from cinder.volume.flows.api import create_volume
|
||||
from cinder.volume.flows.manager import create_volume as create_volume_manager
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
class CreateVolumeFlowTestCase(test.TestCase):
|
||||
|
||||
|
@ -178,6 +182,103 @@ class CreateVolumeFlowTestCase(test.TestCase):
|
|||
'cgsnapshot_id': None, }
|
||||
self.assertEqual(expected_result, result)
|
||||
|
||||
@mock.patch('cinder.volume.volume_types.is_encrypted')
|
||||
@mock.patch('cinder.volume.volume_types.get_volume_type_qos_specs')
|
||||
@mock.patch('cinder.volume.flows.api.create_volume.'
|
||||
'ExtractVolumeRequestTask.'
|
||||
'_get_volume_type_id')
|
||||
def test_extract_availability_zone_without_fallback(
|
||||
self,
|
||||
fake_get_type_id,
|
||||
fake_get_qos,
|
||||
fake_is_encrypted):
|
||||
fake_image_service = fake_image.FakeImageService()
|
||||
image_id = 3
|
||||
image_meta = {}
|
||||
image_meta['id'] = image_id
|
||||
image_meta['status'] = 'active'
|
||||
image_meta['size'] = 1
|
||||
fake_image_service.create(self.ctxt, image_meta)
|
||||
fake_key_manager = mock_key_mgr.MockKeyManager()
|
||||
volume_type = 'type1'
|
||||
|
||||
task = create_volume.ExtractVolumeRequestTask(
|
||||
fake_image_service,
|
||||
{'nova'})
|
||||
|
||||
fake_is_encrypted.return_value = False
|
||||
fake_get_type_id.return_value = 1
|
||||
fake_get_qos.return_value = {'qos_specs': None}
|
||||
self.assertRaises(exception.InvalidInput,
|
||||
task.execute,
|
||||
self.ctxt,
|
||||
size=1,
|
||||
snapshot=None,
|
||||
image_id=image_id,
|
||||
source_volume=None,
|
||||
availability_zone='notnova',
|
||||
volume_type=volume_type,
|
||||
metadata=None,
|
||||
key_manager=fake_key_manager,
|
||||
source_replica=None,
|
||||
consistencygroup=None,
|
||||
cgsnapshot=None)
|
||||
|
||||
@mock.patch('cinder.volume.volume_types.is_encrypted')
|
||||
@mock.patch('cinder.volume.volume_types.get_volume_type_qos_specs')
|
||||
@mock.patch('cinder.volume.flows.api.create_volume.'
|
||||
'ExtractVolumeRequestTask.'
|
||||
'_get_volume_type_id')
|
||||
def test_extract_availability_zone_with_fallback(
|
||||
self,
|
||||
fake_get_type_id,
|
||||
fake_get_qos,
|
||||
fake_is_encrypted):
|
||||
|
||||
self.override_config('allow_availability_zone_fallback', True)
|
||||
|
||||
fake_image_service = fake_image.FakeImageService()
|
||||
image_id = 4
|
||||
image_meta = {}
|
||||
image_meta['id'] = image_id
|
||||
image_meta['status'] = 'active'
|
||||
image_meta['size'] = 1
|
||||
fake_image_service.create(self.ctxt, image_meta)
|
||||
fake_key_manager = mock_key_mgr.MockKeyManager()
|
||||
volume_type = 'type1'
|
||||
|
||||
task = create_volume.ExtractVolumeRequestTask(
|
||||
fake_image_service,
|
||||
{'nova'})
|
||||
|
||||
fake_is_encrypted.return_value = False
|
||||
fake_get_type_id.return_value = 1
|
||||
fake_get_qos.return_value = {'qos_specs': None}
|
||||
result = task.execute(self.ctxt,
|
||||
size=1,
|
||||
snapshot=None,
|
||||
image_id=image_id,
|
||||
source_volume=None,
|
||||
availability_zone='does_not_exist',
|
||||
volume_type=volume_type,
|
||||
metadata=None,
|
||||
key_manager=fake_key_manager,
|
||||
source_replica=None,
|
||||
consistencygroup=None,
|
||||
cgsnapshot=None)
|
||||
expected_result = {'size': 1,
|
||||
'snapshot_id': None,
|
||||
'source_volid': None,
|
||||
'availability_zone': 'nova',
|
||||
'volume_type': volume_type,
|
||||
'volume_type_id': 1,
|
||||
'encryption_key_id': None,
|
||||
'qos_specs': None,
|
||||
'source_replicaid': None,
|
||||
'consistencygroup_id': None,
|
||||
'cgsnapshot_id': None, }
|
||||
self.assertEqual(expected_result, result)
|
||||
|
||||
|
||||
class CreateVolumeFlowManagerTestCase(test.TestCase):
|
||||
|
||||
|
|
|
@ -277,9 +277,20 @@ class ExtractVolumeRequestTask(flow_utils.CinderTask):
|
|||
availability_zone = CONF.storage_availability_zone
|
||||
|
||||
if availability_zone not in self.availability_zones:
|
||||
msg = _("Availability zone '%s' is invalid") % (availability_zone)
|
||||
LOG.warning(msg)
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
if CONF.allow_availability_zone_fallback:
|
||||
original_az = availability_zone
|
||||
availability_zone = (
|
||||
CONF.default_availability_zone or
|
||||
CONF.storage_availability_zone)
|
||||
LOG.warning(_LW("Availability zone '%(s_az)s' "
|
||||
"not found, falling back to "
|
||||
"'%(s_fallback_az)s'."),
|
||||
{'s_az': original_az,
|
||||
's_fallback_az': availability_zone})
|
||||
else:
|
||||
msg = _("Availability zone '%(s_az)s' is invalid.")
|
||||
msg = msg % {'s_az': availability_zone}
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
# If the configuration only allows cloning to the same availability
|
||||
# zone then we need to enforce that.
|
||||
|
|
Loading…
Reference in New Issue