Add volume zone to availability zone profile
-- Add volume_zone option to zone profile for amphora driver Closes-Bug: #2087794 Change-Id: I12e2118df5e31ec62e71b8650fcefe4dd9234751 Signed-off-by: Evgeniy Bykov <chypakabre@gmail.com>
This commit is contained in:

committed by
Tom Weininger

parent
fd071d3391
commit
0640ba5837
@@ -3,6 +3,6 @@
|
||||
{
|
||||
"name": "some_az",
|
||||
"provider_name": "amphora",
|
||||
"availability_zone_data": "{\"compute_zone\": \"az1\"}"
|
||||
"availability_zone_data": "{\"compute_zone\": \"az1\", \"volume_zone\": \"az1\"}"
|
||||
}
|
||||
}
|
||||
|
@@ -4,6 +4,6 @@
|
||||
"id": "5712097e-0092-45dc-bff0-ab68b61ad51a",
|
||||
"name": "some_az",
|
||||
"provider_name": "amphora",
|
||||
"availability_zone_data": "{\"compute_zone\": \"az1\"}"
|
||||
"availability_zone_data": "{\"compute_zone\": \"az1\", \"volume_zone\": \"az1\"}"
|
||||
}
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@
|
||||
"id": "5712097e-0092-45dc-bff0-ab68b61ad51a",
|
||||
"name": "some_az",
|
||||
"provider_name": "amphora",
|
||||
"availability_zone_data": "{\"compute_zone\": \"az1\"}"
|
||||
"availability_zone_data": "{\"compute_zone\": \"az1\", \"volume_zone\": \"az2\"}"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@@ -4,6 +4,6 @@
|
||||
"id": "5712097e-0092-45dc-bff0-ab68b61ad51a",
|
||||
"name": "some_az",
|
||||
"provider_name": "amphora",
|
||||
"availability_zone_data": "{\"compute_zone\": \"az1\"}"
|
||||
"availability_zone_data": "{\"compute_zone\": \"az1\", \"volume_zone\": \"az1\"}"
|
||||
}
|
||||
}
|
||||
|
@@ -3,6 +3,6 @@
|
||||
{
|
||||
"name": "other_az",
|
||||
"provider_name": "amphora",
|
||||
"availability_zone_data": "{\"compute_zone\": \"az2\"}"
|
||||
"availability_zone_data": "{\"compute_zone\": \"az2\", \"volume_zone\": \"az2\"}"
|
||||
}
|
||||
}
|
||||
|
@@ -4,6 +4,6 @@
|
||||
"id": "5712097e-0092-45dc-bff0-ab68b61ad51a",
|
||||
"name": "other_az",
|
||||
"provider_name": "amphora",
|
||||
"availability_zone_data": "{\"compute_zone\": \"az2\"}"
|
||||
"availability_zone_data": "{\"compute_zone\": \"az2\", \"volume_zone\": \"az2\"}"
|
||||
}
|
||||
}
|
||||
|
@@ -3,6 +3,10 @@
|
||||
{
|
||||
"name": "compute_zone",
|
||||
"description": "The compute availability zone."
|
||||
},
|
||||
{
|
||||
"name": "volume_zone",
|
||||
"description": "The volume availability zone."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@@ -1770,6 +1770,7 @@ description. For example:
|
||||
.. code-block:: python
|
||||
|
||||
{"compute_zone": "The compute availability zone to use for this loadbalancer.",
|
||||
"volume_zone": "The volume availability zone to use for this loadbalancer.",
|
||||
"management_network": "The management network ID for the loadbalancer.",
|
||||
"valid_vip_networks": "List of network IDs that are allowed for VIP use. This overrides/replaces the list of allowed networks configured in `octavia.conf`."}
|
||||
|
||||
|
@@ -39,6 +39,10 @@ SUPPORTED_AVAILABILITY_ZONE_SCHEMA = {
|
||||
"type": "string",
|
||||
"description": "The compute availability zone."
|
||||
},
|
||||
consts.VOLUME_ZONE: {
|
||||
"type": "string",
|
||||
"description": "The volume availability zone."
|
||||
},
|
||||
consts.MANAGEMENT_NETWORK: {
|
||||
"type": "string",
|
||||
"description": "The management network ID for the amphora."
|
||||
|
@@ -582,6 +582,18 @@ class AmphoraProviderDriver(driver_base.ProviderDriver):
|
||||
# when the octavia-lib supports it.
|
||||
compute_driver.validate_availability_zone(compute_zone)
|
||||
|
||||
volume_zone = availability_zone_dict.get(consts.VOLUME_ZONE, None)
|
||||
if volume_zone:
|
||||
volume_driver = stevedore_driver.DriverManager(
|
||||
namespace='octavia.volume.drivers',
|
||||
name=CONF.controller_worker.volume_driver,
|
||||
invoke_on_load=True
|
||||
).driver
|
||||
|
||||
# TODO(johnsom) Fix this to raise a NotFound error
|
||||
# when the octavia-lib supports it.
|
||||
volume_driver.validate_availability_zone(volume_zone)
|
||||
|
||||
check_nets = availability_zone_dict.get(
|
||||
consts.VALID_VIP_NETWORKS, [])
|
||||
management_net = availability_zone_dict.get(
|
||||
|
@@ -259,6 +259,8 @@ class NoopManager:
|
||||
self.__class__.__name__)
|
||||
|
||||
return {"compute_zone": "The compute availability zone to use for "
|
||||
"this loadbalancer.",
|
||||
"volume_zone": "The volume availability zone to use for "
|
||||
"this loadbalancer."}
|
||||
|
||||
def validate_availability_zone(self, availability_zone_metadata):
|
||||
|
@@ -332,6 +332,7 @@ CODE = 'code'
|
||||
COMPUTE_ID = 'compute_id'
|
||||
COMPUTE_OBJ = 'compute_obj'
|
||||
COMPUTE_ZONE = 'compute_zone'
|
||||
VOLUME_ZONE = 'volume_zone'
|
||||
CONN_MAX_RETRIES = 'conn_max_retries'
|
||||
CONN_RETRY_INTERVAL = 'conn_retry_interval'
|
||||
CREATED_AT = 'created_at'
|
||||
|
@@ -42,7 +42,7 @@ class ComputeBase(metaclass=abc.ABCMeta):
|
||||
well or a string
|
||||
:param server_group_id: Optional server group id(uuid) which is used
|
||||
for anti_affinity feature
|
||||
:param availability_zone: Name of the compute availability zone.
|
||||
:param availability_zone: Availability zone data dict
|
||||
|
||||
:raises ComputeBuildException: if compute failed to build amphora
|
||||
:returns: UUID of amphora
|
||||
|
@@ -90,8 +90,7 @@ class VirtualMachineManager(compute_base.ComputeBase):
|
||||
well or a string
|
||||
:param server_group_id: Optional server group id(uuid) which is used
|
||||
for anti_affinity feature
|
||||
:param availability_zone: Name of the compute availability zone.
|
||||
|
||||
:param availability_zone: Availability zone data dict
|
||||
:raises ComputeBuildException: if nova failed to build virtual machine
|
||||
:returns: UUID of amphora
|
||||
|
||||
@@ -109,7 +108,12 @@ class VirtualMachineManager(compute_base.ComputeBase):
|
||||
|
||||
server_group = None if server_group_id is None else {
|
||||
"group": server_group_id}
|
||||
az_name = availability_zone or CONF.nova.availability_zone
|
||||
|
||||
if availability_zone:
|
||||
az_name = availability_zone.get(constants.COMPUTE_ZONE,
|
||||
CONF.nova.availability_zone)
|
||||
else:
|
||||
az_name = CONF.nova.availability_zone
|
||||
|
||||
image_id = self.image_driver.get_image_id_by_tag(
|
||||
image_tag, image_owner)
|
||||
@@ -127,7 +131,7 @@ class VirtualMachineManager(compute_base.ComputeBase):
|
||||
LOG.debug('Creating volume for amphora from image %s',
|
||||
image_id)
|
||||
volume_id = self.volume_driver.create_volume_from_image(
|
||||
image_id)
|
||||
image_id, availability_zone)
|
||||
LOG.debug('Created boot volume %s for amphora', volume_id)
|
||||
# If use volume based, does not require image ID anymore
|
||||
image_id = None
|
||||
|
@@ -107,13 +107,9 @@ class ComputeCreate(BaseComputeTask):
|
||||
amp_image_tag = CONF.controller_worker.amp_image_tag
|
||||
|
||||
if availability_zone:
|
||||
amp_availability_zone = availability_zone.get(
|
||||
constants.COMPUTE_ZONE)
|
||||
amp_network = availability_zone.get(constants.MANAGEMENT_NETWORK)
|
||||
if amp_network:
|
||||
network_ids = [amp_network]
|
||||
else:
|
||||
amp_availability_zone = None
|
||||
try:
|
||||
if CONF.haproxy_amphora.build_rate_limit != -1:
|
||||
self.rate_limit.add_to_build_request_queue(
|
||||
@@ -146,7 +142,7 @@ class ComputeCreate(BaseComputeTask):
|
||||
config_drive_files=config_drive_files,
|
||||
user_data=user_data,
|
||||
server_group_id=server_group_id,
|
||||
availability_zone=amp_availability_zone)
|
||||
availability_zone=availability_zone)
|
||||
|
||||
LOG.info("Server created with id: %s for amphora id: %s",
|
||||
compute_id, amphora_id)
|
||||
|
@@ -186,9 +186,14 @@ class TestAvailabilityZoneCapabilities(base.BaseAPITest):
|
||||
provider='bogus'), status=400)
|
||||
|
||||
def test_noop_provider(self):
|
||||
ref_capabilities = [{'description': 'The compute availability zone to '
|
||||
'use for this loadbalancer.',
|
||||
'name': constants.COMPUTE_ZONE}]
|
||||
ref_capabilities = [
|
||||
{'description': 'The compute availability zone to '
|
||||
'use for this loadbalancer.',
|
||||
'name': constants.COMPUTE_ZONE},
|
||||
{'description': 'The volume availability zone to '
|
||||
'use for this loadbalancer.',
|
||||
'name': constants.VOLUME_ZONE},
|
||||
]
|
||||
|
||||
result = self.get(
|
||||
self.AVAILABILITY_ZONE_CAPABILITIES_PATH.format(
|
||||
@@ -220,9 +225,14 @@ class TestAvailabilityZoneCapabilities(base.BaseAPITest):
|
||||
provider='noop_driver'), status=501)
|
||||
|
||||
def test_authorized(self):
|
||||
ref_capabilities = [{'description': 'The compute availability zone to '
|
||||
'use for this loadbalancer.',
|
||||
'name': constants.COMPUTE_ZONE}]
|
||||
ref_capabilities = [
|
||||
{'description': 'The compute availability zone to '
|
||||
'use for this loadbalancer.',
|
||||
'name': constants.COMPUTE_ZONE},
|
||||
{'description': 'The volume availability zone to '
|
||||
'use for this loadbalancer.',
|
||||
'name': constants.VOLUME_ZONE},
|
||||
]
|
||||
self.conf = self.useFixture(oslo_fixture.Config(cfg.CONF))
|
||||
auth_strategy = self.conf.conf.api_settings.get('auth_strategy')
|
||||
self.conf.config(group='api_settings', auth_strategy=constants.TESTING)
|
||||
|
@@ -853,6 +853,16 @@ class TestAmphoraDriver(base.TestRpc):
|
||||
m_driver.validate_availability_zone.return_value = None
|
||||
ref_dict = {consts.COMPUTE_ZONE: 'my_compute_zone'}
|
||||
self.amp_driver.validate_availability_zone(ref_dict)
|
||||
m_driver.validate_availability_zone.assert_called_once_with(
|
||||
'my_compute_zone')
|
||||
|
||||
# Test volume zone
|
||||
with mock.patch('stevedore.driver.DriverManager.driver') as m_driver:
|
||||
m_driver.validate_availability_zone.return_value = None
|
||||
ref_dict = {consts.VOLUME_ZONE: 'my_volume_zone'}
|
||||
self.amp_driver.validate_availability_zone(ref_dict)
|
||||
m_driver.validate_availability_zone.assert_called_once_with(
|
||||
'my_volume_zone')
|
||||
|
||||
with mock.patch('octavia.common.utils.get_network_driver') as m_driver:
|
||||
# Test vip networks
|
||||
|
@@ -145,7 +145,9 @@ class TestNoopProviderDriver(base.TestCase):
|
||||
"to use for this load balancer."}
|
||||
self.ref_availability_zone_metadata = {
|
||||
"compute_zone": "The compute availability zone to use for this "
|
||||
"loadbalancer."}
|
||||
"loadbalancer.",
|
||||
"volume_zone": "The volume availability zone to use for this "
|
||||
"loadbalancer."}
|
||||
|
||||
def test_create_vip_port(self):
|
||||
vip_dict, additional_vip_dicts = self.driver.create_vip_port(
|
||||
|
@@ -144,7 +144,7 @@ class TestNovaClient(base.TestCase):
|
||||
config_drive_files='Files Blah')
|
||||
|
||||
self.assertEqual(self.amphora.compute_id, amphora_id)
|
||||
mock_driver.create_volume_from_image.assert_called_with(1)
|
||||
mock_driver.create_volume_from_image.assert_called_with(1, None)
|
||||
self.manager.manager.create.assert_called_with(
|
||||
name="amphora_name",
|
||||
nics=[{'net-id': 1}, {'port-id': 2}],
|
||||
@@ -161,7 +161,9 @@ class TestNovaClient(base.TestCase):
|
||||
)
|
||||
|
||||
def test_build_with_availability_zone(self):
|
||||
FAKE_AZ = "my_availability_zone"
|
||||
FAKE_AZ_NAME = "my_availability_zone"
|
||||
self.conf.config(group="nova", availability_zone=FAKE_AZ_NAME)
|
||||
FAKE_AZ = {constants.COMPUTE_ZONE: FAKE_AZ_NAME}
|
||||
|
||||
amphora_id = self.manager.build(amphora_flavor=1, image_tag='malt',
|
||||
key_name=1,
|
||||
@@ -185,10 +187,50 @@ class TestNovaClient(base.TestCase):
|
||||
userdata='Blah',
|
||||
config_drive=True,
|
||||
scheduler_hints=None,
|
||||
availability_zone=FAKE_AZ,
|
||||
availability_zone=FAKE_AZ_NAME,
|
||||
block_device_mapping={}
|
||||
)
|
||||
|
||||
@mock.patch('stevedore.driver.DriverManager.driver')
|
||||
def test_build_with_availability_zone_and_volume(self, mock_driver):
|
||||
FAKE_AZ_NAME = "my_availability_zone"
|
||||
self.conf.config(group="controller_worker",
|
||||
volume_driver='volume_cinder_driver')
|
||||
self.conf.config(group="nova", availability_zone=FAKE_AZ_NAME)
|
||||
self.conf.config(group="cinder", availability_zone=FAKE_AZ_NAME)
|
||||
FAKE_AZ = {constants.COMPUTE_ZONE: FAKE_AZ_NAME,
|
||||
constants.VOLUME_ZONE: FAKE_AZ_NAME}
|
||||
|
||||
self.manager.volume_driver = mock_driver
|
||||
mock_driver.create_volume_from_image.return_value = 1
|
||||
|
||||
amphora_id = self.manager.build(amphora_flavor=1, image_tag='pilsner',
|
||||
key_name=1,
|
||||
sec_groups=1,
|
||||
network_ids=[1],
|
||||
port_ids=[2],
|
||||
user_data='Blah',
|
||||
config_drive_files='Files Blah',
|
||||
availability_zone=FAKE_AZ)
|
||||
|
||||
self.assertEqual(self.amphora.compute_id, amphora_id)
|
||||
|
||||
self.manager.manager.create.assert_called_with(
|
||||
name="amphora_name",
|
||||
nics=[{'net-id': 1}, {'port-id': 2}],
|
||||
image=None,
|
||||
flavor=1,
|
||||
key_name=1,
|
||||
security_groups=1,
|
||||
files='Files Blah',
|
||||
userdata='Blah',
|
||||
config_drive=True,
|
||||
scheduler_hints=None,
|
||||
availability_zone=FAKE_AZ_NAME,
|
||||
block_device_mapping={'vda': '1:::true'}
|
||||
)
|
||||
mock_driver.create_volume_from_image.assert_called_with(1, FAKE_AZ)
|
||||
|
||||
def test_build_with_availability_zone_config(self):
|
||||
FAKE_AZ = "my_availability_zone"
|
||||
self.conf.config(group="nova", availability_zone=FAKE_AZ)
|
||||
|
@@ -269,7 +269,7 @@ class TestComputeTasks(base.TestCase):
|
||||
'/etc/rsyslog.d/10-rsyslog.conf': 'FAKE CFG'},
|
||||
user_data='user_data_conf',
|
||||
server_group_id=SERVER_GRPOUP_ID,
|
||||
availability_zone=compute_zone)
|
||||
availability_zone=az_dict)
|
||||
|
||||
# Make sure it returns the expected compute_id
|
||||
self.assertEqual(COMPUTE_ID, compute_id)
|
||||
|
@@ -13,10 +13,10 @@
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from octavia.common import constants
|
||||
import octavia.tests.unit.base as base
|
||||
from octavia.volume.drivers.noop_driver import driver
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
@@ -33,7 +33,16 @@ class TestNoopVolumeDriver(base.TestCase):
|
||||
|
||||
def test_create_volume_from_image(self):
|
||||
self.driver.create_volume_from_image(self.image_id)
|
||||
self.assertEqual((self.image_id, 'create_volume_from_image'),
|
||||
self.assertEqual((self.image_id, None, 'create_volume_from_image'),
|
||||
self.driver.driver.volumeconfig[(
|
||||
self.image_id
|
||||
)])
|
||||
|
||||
def test_create_volume_from_image_with_availability_zone(self):
|
||||
az_name = "some_az"
|
||||
az_data = {constants.VOLUME_ZONE: az_name}
|
||||
self.driver.create_volume_from_image(self.image_id, az_data)
|
||||
self.assertEqual((self.image_id, az_data, 'create_volume_from_image'),
|
||||
self.driver.driver.volumeconfig[(
|
||||
self.image_id
|
||||
)])
|
||||
|
@@ -16,6 +16,7 @@ from oslo_config import cfg
|
||||
from oslo_config import fixture as oslo_fixture
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from octavia.common import constants
|
||||
from octavia.common import exceptions
|
||||
import octavia.tests.unit.base as base
|
||||
import octavia.volume.drivers.cinder_driver as cinder_common
|
||||
@@ -42,6 +43,7 @@ class TestCinderClient(base.TestCase):
|
||||
|
||||
self.manager.manager.get.return_value.status = 'available'
|
||||
self.manager.manager.create.return_value = self.cinder_response
|
||||
self.manager.availability_zone_manager = mock.MagicMock()
|
||||
self.image_id = fake_uuid2
|
||||
self.volume_id = fake_uuid3
|
||||
|
||||
@@ -58,6 +60,36 @@ class TestCinderClient(base.TestCase):
|
||||
availability_zone=None,
|
||||
imageRef=self.image_id)
|
||||
|
||||
def test_create_volume_from_image_with_availability_zone(self):
|
||||
self.conf.config(group="controller_worker",
|
||||
volume_driver='volume_cinder_driver')
|
||||
self.conf.config(group="cinder", volume_create_retry_interval=0)
|
||||
self.conf.config(group="cinder", availability_zone="no_zone")
|
||||
|
||||
az_name = "some_zone"
|
||||
az_data = {constants.VOLUME_ZONE: az_name}
|
||||
|
||||
self.manager.create_volume_from_image(self.image_id, az_data)
|
||||
self.manager.manager.create.assert_called_with(
|
||||
size=16,
|
||||
volume_type=None,
|
||||
availability_zone=az_name,
|
||||
imageRef=self.image_id)
|
||||
|
||||
def test_create_volume_from_image_with_availability_zone_from_conf(self):
|
||||
az_name = "some_az"
|
||||
self.conf.config(group="controller_worker",
|
||||
volume_driver='volume_cinder_driver')
|
||||
self.conf.config(group="cinder", volume_create_retry_interval=0)
|
||||
self.conf.config(group="cinder", availability_zone=az_name)
|
||||
|
||||
self.manager.create_volume_from_image(self.image_id)
|
||||
self.manager.manager.create.assert_called_with(
|
||||
size=16,
|
||||
volume_type=None,
|
||||
availability_zone=az_name,
|
||||
imageRef=self.image_id)
|
||||
|
||||
def test_create_volume_from_image_error(self):
|
||||
self.conf.config(group="controller_worker",
|
||||
volume_driver='volume_cinder_driver')
|
||||
@@ -97,3 +129,18 @@ class TestCinderClient(base.TestCase):
|
||||
self.assertRaises(exceptions.VolumeGetException,
|
||||
self.manager.get_image_from_volume,
|
||||
self.volume_id)
|
||||
|
||||
def test_validate_availability_zone(self):
|
||||
az_name = "some_az"
|
||||
mock_az = mock.Mock()
|
||||
mock_az.zoneName = az_name
|
||||
self.manager.availability_zone_manager.list.return_value = [mock_az]
|
||||
self.manager.validate_availability_zone(az_name)
|
||||
self.manager.availability_zone_manager.list.assert_called_with(
|
||||
detailed=False)
|
||||
|
||||
def test_validate_availability_zone_with_exception(self):
|
||||
self.manager.availability_zone_manager.list.return_value = []
|
||||
self.assertRaises(exceptions.InvalidSubresource,
|
||||
self.manager.validate_availability_zone,
|
||||
"bogus")
|
||||
|
@@ -43,20 +43,29 @@ class VolumeManager(volume_base.VolumeBase):
|
||||
cacert=CONF.cinder.ca_certificates_file
|
||||
)
|
||||
self.manager = self._cinder_client.volumes
|
||||
self.availability_zone_manager = self._cinder_client.availability_zones
|
||||
|
||||
@retry(reraise=True,
|
||||
stop=stop_after_attempt(CONF.cinder.volume_create_max_retries))
|
||||
def create_volume_from_image(self, image_id):
|
||||
def create_volume_from_image(self, image_id, availability_zone=None):
|
||||
"""Create cinder volume
|
||||
|
||||
:param image_id: ID of amphora image
|
||||
:param availability_zone: Availability zone data dict
|
||||
|
||||
:return volume id
|
||||
"""
|
||||
|
||||
if availability_zone:
|
||||
az_name = availability_zone.get(
|
||||
constants.VOLUME_ZONE, CONF.cinder.availability_zone)
|
||||
else:
|
||||
az_name = CONF.cinder.availability_zone
|
||||
|
||||
volume = self.manager.create(
|
||||
size=CONF.cinder.volume_size,
|
||||
volume_type=CONF.cinder.volume_type,
|
||||
availability_zone=CONF.cinder.availability_zone,
|
||||
availability_zone=az_name,
|
||||
imageRef=image_id)
|
||||
resource_status = self.manager.get(volume.id).status
|
||||
|
||||
@@ -121,3 +130,24 @@ class VolumeManager(volume_base.VolumeBase):
|
||||
LOG.error("Volume %s has no image metadata", volume_id)
|
||||
image_id = None
|
||||
return image_id
|
||||
|
||||
def validate_availability_zone(self, availability_zone):
|
||||
"""Validates that an availability zone exists in cinder.
|
||||
|
||||
:param availability_zone: Name of the availability zone to lookup.
|
||||
:raises: NotFound
|
||||
:returns: None
|
||||
"""
|
||||
try:
|
||||
volume_zones = [
|
||||
a.zoneName for a in self.availability_zone_manager.list(
|
||||
detailed=False)]
|
||||
if availability_zone not in volume_zones:
|
||||
LOG.info('Availability zone %s was not found in cinder. %s',
|
||||
availability_zone, volume_zones)
|
||||
raise exceptions.InvalidSubresource(
|
||||
resource='Cinder availability zone', id=availability_zone)
|
||||
except Exception as e:
|
||||
LOG.exception('Cinder reports a failure getting listing '
|
||||
'availability zones: %s', str(e))
|
||||
raise
|
||||
|
@@ -23,10 +23,12 @@ class NoopManager:
|
||||
super().__init__()
|
||||
self.volumeconfig = {}
|
||||
|
||||
def create_volume_from_image(self, image_id):
|
||||
LOG.debug("Volume %s no-op, image id %s",
|
||||
self.__class__.__name__, image_id)
|
||||
self.volumeconfig[image_id] = (image_id, 'create_volume_from_image')
|
||||
def create_volume_from_image(self, image_id, availability_zone=None):
|
||||
LOG.debug("Volume %s no-op, image id %s, availability zone %s",
|
||||
self.__class__.__name__, image_id, availability_zone)
|
||||
self.volumeconfig[image_id] = (image_id,
|
||||
availability_zone,
|
||||
'create_volume_from_image')
|
||||
volume_id = uuidutils.generate_uuid()
|
||||
return volume_id
|
||||
|
||||
@@ -42,14 +44,21 @@ class NoopManager:
|
||||
image_id = uuidutils.generate_uuid()
|
||||
return image_id
|
||||
|
||||
def validate_availability_zone(self, availability_zone):
|
||||
LOG.debug("Volume %s no-op, validate_availability_zone name %s",
|
||||
self.__class__.__name__, availability_zone)
|
||||
self.volumeconfig[availability_zone] = (
|
||||
availability_zone, 'validate_availability_zone')
|
||||
|
||||
|
||||
class NoopVolumeDriver(driver_base.VolumeBase):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.driver = NoopManager()
|
||||
|
||||
def create_volume_from_image(self, image_id):
|
||||
volume_id = self.driver.create_volume_from_image(image_id)
|
||||
def create_volume_from_image(self, image_id, availability_zone=None):
|
||||
volume_id = self.driver.create_volume_from_image(
|
||||
image_id, availability_zone)
|
||||
return volume_id
|
||||
|
||||
def delete_volume(self, volume_id):
|
||||
@@ -58,3 +67,6 @@ class NoopVolumeDriver(driver_base.VolumeBase):
|
||||
def get_image_from_volume(self, volume_id):
|
||||
image_id = self.driver.get_image_from_volume(volume_id)
|
||||
return image_id
|
||||
|
||||
def validate_availability_zone(self, availability_zone):
|
||||
self.driver.validate_availability_zone(availability_zone)
|
||||
|
@@ -18,10 +18,11 @@ import abc
|
||||
class VolumeBase(metaclass=abc.ABCMeta):
|
||||
|
||||
@abc.abstractmethod
|
||||
def create_volume_from_image(self, image_id):
|
||||
def create_volume_from_image(self, image_id, availability_zone=None):
|
||||
"""Create volume for instance
|
||||
|
||||
:param image_id: ID of amphora image
|
||||
:param availability_zone: Availability zone data dict
|
||||
|
||||
:return volume id
|
||||
"""
|
||||
@@ -41,3 +42,13 @@ class VolumeBase(metaclass=abc.ABCMeta):
|
||||
|
||||
:return image id
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def validate_availability_zone(self, availability_zone):
|
||||
"""Validates that a volume availability zone exists.
|
||||
|
||||
:param availability_zone: Name of the availability zone to lookup.
|
||||
:returns: None
|
||||
:raises: NotFound
|
||||
:raises: NotImplementedError
|
||||
"""
|
||||
|
@@ -0,0 +1,6 @@
|
||||
---
|
||||
|
||||
features:
|
||||
- |
|
||||
Added volume zone to availability zone profile for amphorae backend for
|
||||
creating loadbalancer with specific volume availability zone
|
Reference in New Issue
Block a user