ScaleIo Driver: refactor config options
The configuration of the ScaleIO Driver is a bit confusing. This patch simplifies and deprecates some options that are infrequently used but cause confusion. Change-Id: If982799d4263c6b7ec8753f63e695ce0a0d16285
This commit is contained in:
parent
c1a7e41808
commit
b12b865ac5
@ -73,8 +73,9 @@ class TestCreateVolume(scaleio.TestScaleIODriver):
|
||||
|
||||
def test_no_domain(self):
|
||||
"""No protection domain name or ID provided."""
|
||||
self.driver.protection_domain_name = None
|
||||
self.driver.protection_domain_id = None
|
||||
self.driver.configuration.sio_protection_domain_name = None
|
||||
self.driver.configuration.sio_protection_domain_id = None
|
||||
self.driver.storage_pools = None
|
||||
self.volume.host = "host@backend"
|
||||
self.assertRaises(exception.VolumeBackendAPIException,
|
||||
self.test_create_volume)
|
||||
|
@ -118,8 +118,18 @@ class ScaleIOManageableCase(scaleio.TestScaleIODriver):
|
||||
self.HTTPS_MOCK_RESPONSES = {
|
||||
self.RESPONSE_MODE.Valid: {
|
||||
'instances/StoragePool::test_pool/relationships/Volume':
|
||||
scaleio_objects
|
||||
scaleio_objects,
|
||||
'types/Pool/instances/getByName::{},{}'.format(
|
||||
"test_domain",
|
||||
"test_pool"
|
||||
): '"{}"'.format("test_pool").encode('ascii', 'ignore'),
|
||||
'types/Domain/instances/getByName::' +
|
||||
"test_domain": '"{}"'.format("test_domain").encode(
|
||||
'ascii',
|
||||
'ignore'
|
||||
),
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
with mock.patch('cinder.volume.utils.paginate_entries_list') as mpage:
|
||||
|
@ -75,6 +75,17 @@ class TestMisc(scaleio.TestScaleIODriver):
|
||||
self.new_volume['provider_id']):
|
||||
self.volume['provider_id'],
|
||||
'version': '"{}"'.format('2.0.1'),
|
||||
'instances/StoragePool::{}'.format(
|
||||
"test_pool"
|
||||
): {
|
||||
'name': 'test_pool',
|
||||
'protectionDomainId': 'test_domain',
|
||||
},
|
||||
'instances/ProtectionDomain::{}'.format(
|
||||
"test_domain"
|
||||
): {
|
||||
'name': 'test_domain',
|
||||
},
|
||||
},
|
||||
self.RESPONSE_MODE.BadStatus: {
|
||||
'types/Domain/instances/getByName::' +
|
||||
@ -104,30 +115,43 @@ class TestMisc(scaleio.TestScaleIODriver):
|
||||
self.driver.check_for_setup_error()
|
||||
|
||||
def test_both_storage_pool(self):
|
||||
"""Both storage name and ID provided."""
|
||||
self.driver.storage_pool_id = "test_pool_id"
|
||||
self.driver.storage_pool_name = "test_pool_name"
|
||||
"""Both storage name and ID provided.
|
||||
|
||||
INVALID
|
||||
"""
|
||||
self.driver.configuration.sio_storage_pool_id = "test_pool_id"
|
||||
self.driver.configuration.sio_storage_pool_name = "test_pool_name"
|
||||
self.assertRaises(exception.InvalidInput,
|
||||
self.driver.check_for_setup_error)
|
||||
|
||||
def test_no_storage_pool(self):
|
||||
"""No storage name or ID provided."""
|
||||
self.driver.storage_pool_name = None
|
||||
self.driver.storage_pool_id = None
|
||||
self.assertRaises(exception.InvalidInput,
|
||||
self.driver.check_for_setup_error)
|
||||
"""No storage name or ID provided.
|
||||
|
||||
VALID as storage_pools are defined
|
||||
"""
|
||||
self.driver.configuration.sio_storage_pool_name = None
|
||||
self.driver.configuration.sio_storage_pool_id = None
|
||||
self.driver.check_for_setup_error()
|
||||
|
||||
def test_both_domain(self):
|
||||
self.driver.protection_domain_name = "test_domain_name"
|
||||
self.driver.protection_domain_id = "test_domain_id"
|
||||
"""Both domain and ID are provided
|
||||
|
||||
INVALID
|
||||
"""
|
||||
self.driver.configuration.sio_protection_domain_name = (
|
||||
"test_domain_name")
|
||||
self.driver.configuration.sio_protection_domain_id = (
|
||||
"test_domain_id")
|
||||
self.assertRaises(exception.InvalidInput,
|
||||
self.driver.check_for_setup_error)
|
||||
|
||||
def test_no_storage_pools(self):
|
||||
"""No storage pools."""
|
||||
"""No storage pools.
|
||||
|
||||
VALID as domain and storage pool names are provided
|
||||
"""
|
||||
self.driver.storage_pools = None
|
||||
self.assertRaises(exception.InvalidInput,
|
||||
self.driver.check_for_setup_error)
|
||||
self.driver.check_for_setup_error()
|
||||
|
||||
def test_volume_size_round_true(self):
|
||||
self.driver._check_volume_size(1)
|
||||
@ -185,6 +209,9 @@ class TestMisc(scaleio.TestScaleIODriver):
|
||||
self.new_volume['provider_id']):
|
||||
self.volume['provider_id'],
|
||||
'version': '"{}"'.format('2.0.1'),
|
||||
'instances/StoragePool::{}'.format(
|
||||
self.STORAGE_POOL_NAME
|
||||
): '"{}"'.format(self.STORAGE_POOL_ID),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,16 +66,28 @@ scaleio_opts = [
|
||||
cfg.BoolOpt('sio_unmap_volume_before_deletion',
|
||||
default=False,
|
||||
help='Unmap volume before deletion.'),
|
||||
cfg.StrOpt('sio_protection_domain_id',
|
||||
help='Protection Domain ID.'),
|
||||
cfg.StrOpt('sio_protection_domain_name',
|
||||
help='Protection Domain name.'),
|
||||
cfg.StrOpt('sio_storage_pools',
|
||||
help='Storage Pools.'),
|
||||
cfg.StrOpt('sio_protection_domain_id',
|
||||
deprecated_for_removal=True,
|
||||
deprecated_reason="Replaced by sio_storage_pools option",
|
||||
deprecated_since="Pike",
|
||||
help='DEPRECATED: Protection Domain ID.'),
|
||||
cfg.StrOpt('sio_protection_domain_name',
|
||||
deprecated_for_removal=True,
|
||||
deprecated_reason="Replaced by sio_storage_pools option",
|
||||
deprecated_since="Pike",
|
||||
help='DEPRECATED: Protection Domain name.'),
|
||||
cfg.StrOpt('sio_storage_pool_name',
|
||||
help='Storage Pool name.'),
|
||||
deprecated_for_removal=True,
|
||||
deprecated_reason="Replaced by sio_storage_pools option",
|
||||
deprecated_since="Pike",
|
||||
help='DEPRECATED: Storage Pool name.'),
|
||||
cfg.StrOpt('sio_storage_pool_id',
|
||||
help='Storage Pool ID.'),
|
||||
deprecated_for_removal=True,
|
||||
deprecated_reason="Replaced by sio_storage_pools option",
|
||||
deprecated_since="Pike",
|
||||
help='DEPRECATED: Storage Pool ID.'),
|
||||
cfg.StrOpt('sio_server_api_version',
|
||||
help='ScaleIO API version.'),
|
||||
cfg.FloatOpt('sio_max_over_subscription_ratio',
|
||||
@ -156,30 +168,23 @@ class ScaleIODriver(driver.VolumeDriver):
|
||||
'user': self.server_username,
|
||||
'verify_cert': self.verify_server_certificate})
|
||||
|
||||
# starting in Pike, prefer the sio_storage_pools option
|
||||
self.storage_pools = None
|
||||
if self.configuration.sio_storage_pools:
|
||||
self.storage_pools = [
|
||||
e.strip() for e in
|
||||
self.configuration.sio_storage_pools.split(',')]
|
||||
LOG.info("Storage pools names: %(pools)s.",
|
||||
{'pools': self.storage_pools})
|
||||
|
||||
self.storage_pool_name = self.configuration.sio_storage_pool_name
|
||||
self.storage_pool_id = self.configuration.sio_storage_pool_id
|
||||
if self.storage_pool_name is None and self.storage_pool_id is None:
|
||||
LOG.warning("No storage pool name or id was found.")
|
||||
else:
|
||||
LOG.info("Storage pools names: %(pools)s, "
|
||||
"storage pool name: %(pool)s, pool id: %(pool_id)s.",
|
||||
{'pools': self.storage_pools,
|
||||
'pool': self.storage_pool_name,
|
||||
'pool_id': self.storage_pool_id})
|
||||
LOG.info("Storage pool name: %(pool)s, pool id: %(pool_id)s.",
|
||||
{'pool': self.configuration.sio_storage_pool_name,
|
||||
'pool_id': self.configuration.sio_storage_pool_id})
|
||||
|
||||
self.protection_domain_name = (
|
||||
self.configuration.sio_protection_domain_name)
|
||||
LOG.info("Protection domain name: %(domain_name)s.",
|
||||
{'domain_name': self.protection_domain_name})
|
||||
self.protection_domain_id = self.configuration.sio_protection_domain_id
|
||||
LOG.info("Protection domain id: %(domain_id)s.",
|
||||
{'domain_id': self.protection_domain_id})
|
||||
LOG.info("Protection domain name: %(domain)s, "
|
||||
"domain id: %(domain_id)s.",
|
||||
{'domain': self.configuration.sio_protection_domain_name,
|
||||
'domain_id': self.configuration.sio_protection_domain_id})
|
||||
|
||||
self.provisioning_type = (
|
||||
'thin' if self.configuration.san_thin_provision else 'thick')
|
||||
@ -204,51 +209,51 @@ class ScaleIODriver(driver.VolumeDriver):
|
||||
'bandwidthLimit': None,
|
||||
}
|
||||
|
||||
def check_for_setup_error(self):
|
||||
if (not self.protection_domain_name and
|
||||
not self.protection_domain_id):
|
||||
LOG.warning("No protection domain name or id "
|
||||
"was specified in configuration.")
|
||||
# simple cache for domain and sp ids
|
||||
self.cache_pd = {}
|
||||
self.cache_sp = {}
|
||||
|
||||
if self.protection_domain_name and self.protection_domain_id:
|
||||
def check_for_setup_error(self):
|
||||
# make sure both domain name and id are not specified
|
||||
if (self.configuration.sio_protection_domain_name
|
||||
and self.configuration.sio_protection_domain_id):
|
||||
msg = _("Cannot specify both protection domain name "
|
||||
"and protection domain id.")
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
if not self.server_ip:
|
||||
msg = _("REST server IP must by specified.")
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
if not self.server_username:
|
||||
msg = _("REST server username must by specified.")
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
if not self.server_password:
|
||||
msg = _("REST server password must by specified.")
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
if not self.verify_server_certificate:
|
||||
LOG.warning("Verify certificate is not set, using default of "
|
||||
"False.")
|
||||
|
||||
if self.verify_server_certificate and not self.server_certificate_path:
|
||||
msg = _("Path to REST server's certificate must be specified.")
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
if self.storage_pool_name and self.storage_pool_id:
|
||||
# make sure both storage pool and id are not specified
|
||||
if (self.configuration.sio_storage_pool_name
|
||||
and self.configuration.sio_storage_pool_id):
|
||||
msg = _("Cannot specify both storage pool name and storage "
|
||||
"pool id.")
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
if not self.storage_pool_name and not self.storage_pool_id:
|
||||
msg = _("Must specify storage pool name or id.")
|
||||
# make sure the REST gateway is specified
|
||||
if not self.server_ip:
|
||||
msg = _("REST server IP must be specified.")
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
if not self.storage_pools:
|
||||
msg = (_("Must specify storage pools. Option: "
|
||||
"sio_storage_pools."))
|
||||
# make sure we got a username
|
||||
if not self.server_username:
|
||||
msg = _("REST server username must be specified.")
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
# make sure we got a password
|
||||
if not self.server_password:
|
||||
msg = _("REST server password must be specified.")
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
# validate certificate settings
|
||||
if self.verify_server_certificate and not self.server_certificate_path:
|
||||
msg = _("Path to REST server's certificate must be specified.")
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
# log warning if not using certificates
|
||||
if not self.verify_server_certificate:
|
||||
LOG.warning("Verify certificate is not set, using default of "
|
||||
"False.")
|
||||
|
||||
# validate oversubscription ration
|
||||
if (self.configuration.max_over_subscription_ratio is not None and
|
||||
(self.configuration.max_over_subscription_ratio -
|
||||
SIO_MAX_OVERSUBSCRIPTION_RATIO > 1)):
|
||||
@ -258,6 +263,7 @@ class ScaleIODriver(driver.VolumeDriver):
|
||||
'ratio': self.configuration.max_over_subscription_ratio})
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
# validate that version of ScaleIO is supported
|
||||
server_api_version = self._get_server_api_version(fromcache=False)
|
||||
if not self._version_greater_than_or_equal(
|
||||
server_api_version, "2.0.0"):
|
||||
@ -266,6 +272,48 @@ class ScaleIODriver(driver.VolumeDriver):
|
||||
"deprecated and will be removed in a future version"))
|
||||
versionutils.report_deprecated_feature(LOG, msg)
|
||||
|
||||
# we have enough information now to validate pools
|
||||
self.storage_pools = self._build_storage_pool_list()
|
||||
if not self.storage_pools:
|
||||
msg = (_("Must specify storage pools. Option: "
|
||||
"sio_storage_pools."))
|
||||
raise exception.InvalidInput(reason=msg)
|
||||
|
||||
def _build_storage_pool_list(self):
|
||||
"""Build storage pool list
|
||||
|
||||
This method determines the list of storage pools that
|
||||
are requested, by concatenating a few config settings
|
||||
"""
|
||||
# start with the list of pools supplied in the configuration
|
||||
pools = self.storage_pools
|
||||
# append the domain:pool specified individually
|
||||
if (self.configuration.sio_storage_pool_name is not None and
|
||||
self.configuration.sio_protection_domain_name is not None):
|
||||
extra_pool = "{}:{}".format(
|
||||
self.configuration.sio_storage_pool_name,
|
||||
self.configuration.sio_protection_domain_name)
|
||||
LOG.info("Ensuring %s is in the list of configured pools.",
|
||||
extra_pool)
|
||||
if pools is None:
|
||||
pools = []
|
||||
if extra_pool not in pools:
|
||||
pools.append(extra_pool)
|
||||
# if specified, account for the storage_pool_id
|
||||
if self.configuration.sio_storage_pool_id is not None:
|
||||
# the user specified a storage pool id
|
||||
# get the domain and pool names from SIO
|
||||
extra_pool = self._get_storage_pool_name(
|
||||
self.configuration.sio_storage_pool_id)
|
||||
LOG.info("Ensuring %s is in the list of configured pools.",
|
||||
extra_pool)
|
||||
if pools is None:
|
||||
pools = []
|
||||
if extra_pool not in pools:
|
||||
pools.append(extra_pool)
|
||||
|
||||
return pools
|
||||
|
||||
def _get_queryable_statistics(self, sio_type, sio_id):
|
||||
if self.statisticProperties is None:
|
||||
self.statisticProperties = [
|
||||
@ -301,8 +349,7 @@ class ScaleIODriver(driver.VolumeDriver):
|
||||
|
||||
def _find_storage_pool_id_from_storage_type(self, storage_type):
|
||||
# Default to what was configured in configuration file if not defined.
|
||||
return storage_type.get(STORAGE_POOL_ID,
|
||||
self.storage_pool_id)
|
||||
return storage_type.get(STORAGE_POOL_ID)
|
||||
|
||||
def _find_storage_pool_name_from_storage_type(self, storage_type):
|
||||
pool_name = storage_type.get(STORAGE_POOL_NAME)
|
||||
@ -317,8 +364,7 @@ class ScaleIODriver(driver.VolumeDriver):
|
||||
|
||||
def _find_protection_domain_id_from_storage_type(self, storage_type):
|
||||
# Default to what was configured in configuration file if not defined.
|
||||
return storage_type.get(PROTECTION_DOMAIN_ID,
|
||||
self.protection_domain_id)
|
||||
return storage_type.get(PROTECTION_DOMAIN_ID)
|
||||
|
||||
def _find_protection_domain_name_from_storage_type(self, storage_type):
|
||||
domain_name = storage_type.get(PROTECTION_DOMAIN_NAME)
|
||||
@ -465,82 +511,12 @@ class ScaleIODriver(driver.VolumeDriver):
|
||||
'domain_id': protection_domain_id,
|
||||
'domain_name': protection_domain_name})
|
||||
|
||||
if storage_pool_name:
|
||||
self.storage_pool_name = storage_pool_name
|
||||
self.storage_pool_id = None
|
||||
if storage_pool_id:
|
||||
self.storage_pool_id = storage_pool_id
|
||||
self.storage_pool_name = None
|
||||
if protection_domain_name:
|
||||
self.protection_domain_name = protection_domain_name
|
||||
self.protection_domain_id = None
|
||||
if protection_domain_id:
|
||||
self.protection_domain_id = protection_domain_id
|
||||
self.protection_domain_name = None
|
||||
|
||||
domain_id = self.protection_domain_id
|
||||
if not domain_id:
|
||||
if not self.protection_domain_name:
|
||||
msg = _("Must specify protection domain name or"
|
||||
" protection domain id.")
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
|
||||
domain_name = self.protection_domain_name
|
||||
encoded_domain_name = urllib.parse.quote(domain_name, '')
|
||||
req_vars = {'server_ip': self.server_ip,
|
||||
'server_port': self.server_port,
|
||||
'encoded_domain_name': encoded_domain_name}
|
||||
request = ("https://%(server_ip)s:%(server_port)s"
|
||||
"/api/types/Domain/instances/getByName::"
|
||||
"%(encoded_domain_name)s") % req_vars
|
||||
LOG.info("ScaleIO get domain id by name request: %s.",
|
||||
request)
|
||||
|
||||
r, domain_id = self._execute_scaleio_get_request(request)
|
||||
|
||||
if not domain_id:
|
||||
msg = (_("Domain with name %s wasn't found.")
|
||||
% self.protection_domain_name)
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
if r.status_code != http_client.OK and "errorCode" in domain_id:
|
||||
msg = (_("Error getting domain id from name %(name)s: %(id)s.")
|
||||
% {'name': self.protection_domain_name,
|
||||
'id': domain_id['message']})
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
|
||||
domain_id = self._get_protection_domain_id(protection_domain_name)
|
||||
LOG.info("Domain id is %s.", domain_id)
|
||||
pool_name = self.storage_pool_name
|
||||
pool_id = self.storage_pool_id
|
||||
if pool_name:
|
||||
encoded_domain_name = urllib.parse.quote(pool_name, '')
|
||||
req_vars = {'server_ip': self.server_ip,
|
||||
'server_port': self.server_port,
|
||||
'domain_id': domain_id,
|
||||
'encoded_domain_name': encoded_domain_name}
|
||||
request = ("https://%(server_ip)s:%(server_port)s"
|
||||
"/api/types/Pool/instances/getByName::"
|
||||
"%(domain_id)s,%(encoded_domain_name)s") % req_vars
|
||||
LOG.info("ScaleIO get pool id by name request: %s.", request)
|
||||
r, pool_id = self._execute_scaleio_get_request(request)
|
||||
|
||||
if not pool_id:
|
||||
msg = (_("Pool with name %(pool_name)s wasn't found in "
|
||||
"domain %(domain_id)s.")
|
||||
% {'pool_name': pool_name,
|
||||
'domain_id': domain_id})
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
if r.status_code != http_client.OK and "errorCode" in pool_id:
|
||||
msg = (_("Error getting pool id from name %(pool_name)s: "
|
||||
"%(err_msg)s.")
|
||||
% {'pool_name': pool_name,
|
||||
'err_msg': pool_id['message']})
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
|
||||
pool_id = self._get_storage_pool_id(protection_domain_name,
|
||||
storage_pool_name)
|
||||
LOG.info("Pool id is %s.", pool_id)
|
||||
|
||||
if provisioning_type == 'thin':
|
||||
provisioning = "ThinProvisioned"
|
||||
# Default volume type is thick.
|
||||
@ -946,8 +922,6 @@ class ScaleIODriver(driver.VolumeDriver):
|
||||
stats['thin_provisioning_support'] = True
|
||||
pools = []
|
||||
|
||||
verify_cert = self._get_verify_cert()
|
||||
|
||||
free_capacity = 0
|
||||
total_capacity = 0
|
||||
provisioned_capacity = 0
|
||||
@ -956,63 +930,10 @@ class ScaleIODriver(driver.VolumeDriver):
|
||||
splitted_name = sp_name.split(':')
|
||||
domain_name = splitted_name[0]
|
||||
pool_name = splitted_name[1]
|
||||
LOG.debug("domain name is %(domain)s, pool name is %(pool)s.",
|
||||
{'domain': domain_name,
|
||||
'pool': pool_name})
|
||||
# Get domain id from name.
|
||||
encoded_domain_name = urllib.parse.quote(domain_name, '')
|
||||
req_vars = {'server_ip': self.server_ip,
|
||||
'server_port': self.server_port,
|
||||
'encoded_domain_name': encoded_domain_name}
|
||||
request = ("https://%(server_ip)s:%(server_port)s"
|
||||
"/api/types/Domain/instances/getByName::"
|
||||
"%(encoded_domain_name)s") % req_vars
|
||||
LOG.info("ScaleIO get domain id by name request: %s.",
|
||||
request)
|
||||
LOG.info("username: %(username)s, verify_cert: %(verify)s.",
|
||||
{'username': self.server_username,
|
||||
'verify': verify_cert})
|
||||
r, domain_id = self._execute_scaleio_get_request(request)
|
||||
if not domain_id:
|
||||
msg = (_("Domain with name %s wasn't found.")
|
||||
% self.protection_domain_name)
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
if r.status_code != http_client.OK and "errorCode" in domain_id:
|
||||
msg = (_("Error getting domain id from name %(name)s: "
|
||||
"%(err)s.")
|
||||
% {'name': self.protection_domain_name,
|
||||
'err': domain_id['message']})
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
LOG.info("Domain id is %s.", domain_id)
|
||||
|
||||
# Get pool id from name.
|
||||
encoded_pool_name = urllib.parse.quote(pool_name, '')
|
||||
req_vars = {'server_ip': self.server_ip,
|
||||
'server_port': self.server_port,
|
||||
'domain_id': domain_id,
|
||||
'encoded_pool_name': encoded_pool_name}
|
||||
request = ("https://%(server_ip)s:%(server_port)s"
|
||||
"/api/types/Pool/instances/getByName::"
|
||||
"%(domain_id)s,%(encoded_pool_name)s") % req_vars
|
||||
LOG.info("ScaleIO get pool id by name request: %s.", request)
|
||||
r, pool_id = self._execute_scaleio_get_request(request)
|
||||
if not pool_id:
|
||||
msg = (_("Pool with name %(pool)s wasn't found in domain "
|
||||
"%(domain)s.")
|
||||
% {'pool': pool_name,
|
||||
'domain': domain_id})
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
if r.status_code != http_client.OK and "errorCode" in pool_id:
|
||||
msg = (_("Error getting pool id from name %(pool)s: "
|
||||
"%(err)s.")
|
||||
% {'pool': pool_name,
|
||||
'err': pool_id['message']})
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
pool_id = self._get_storage_pool_id(domain_name, pool_name)
|
||||
LOG.info("Pool id is %s.", pool_id)
|
||||
|
||||
req_vars = {'server_ip': self.server_ip,
|
||||
'server_port': self.server_port}
|
||||
request = ("https://%(server_ip)s:%(server_port)s"
|
||||
@ -1054,7 +975,7 @@ class ScaleIODriver(driver.VolumeDriver):
|
||||
LOG.info("Free capacity of pool %(pool)s is: %(free)s, "
|
||||
"total capacity: %(total)s, "
|
||||
"provisioned capacity: %(prov)s",
|
||||
{'pool': pool_name,
|
||||
{'pool': sp_name,
|
||||
'free': free_capacity_gb,
|
||||
'total': total_capacity_gb,
|
||||
'prov': provisioned_capacity})
|
||||
@ -1253,18 +1174,18 @@ class ScaleIODriver(driver.VolumeDriver):
|
||||
self._manage_existing_check_legal_response(r, existing_ref)
|
||||
return response
|
||||
|
||||
def _get_protection_domain_id(self):
|
||||
""""Get the id of the configured protection domain"""
|
||||
def _get_protection_domain_id(self, domain_name):
|
||||
""""Get the id of the protection domain"""
|
||||
|
||||
if self.protection_domain_id:
|
||||
return self.protection_domain_id
|
||||
|
||||
if not self.protection_domain_name:
|
||||
msg = _("Must specify protection domain name or"
|
||||
" protection domain id.")
|
||||
if not domain_name:
|
||||
msg = (_("Error getting domain id from None name."))
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
|
||||
domain_name = self.protection_domain_name
|
||||
# do we already have the id?
|
||||
if domain_name in self.cache_pd:
|
||||
return self.cache_pd[domain_name]
|
||||
|
||||
encoded_domain_name = urllib.parse.quote(domain_name, '')
|
||||
req_vars = {'server_ip': self.server_ip,
|
||||
'server_port': self.server_port,
|
||||
@ -1272,39 +1193,93 @@ class ScaleIODriver(driver.VolumeDriver):
|
||||
request = ("https://%(server_ip)s:%(server_port)s"
|
||||
"/api/types/Domain/instances/getByName::"
|
||||
"%(encoded_domain_name)s") % req_vars
|
||||
LOG.debug("ScaleIO get domain id by name request: %s.", request)
|
||||
|
||||
r, domain_id = self._execute_scaleio_get_request(request)
|
||||
|
||||
if not domain_id:
|
||||
msg = (_("Domain with name %s wasn't found.")
|
||||
% self.protection_domain_name)
|
||||
% domain_name)
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
if r.status_code != http_client.OK and "errorCode" in domain_id:
|
||||
msg = (_("Error getting domain id from name %(name)s: %(id)s.")
|
||||
% {'name': self.protection_domain_name,
|
||||
% {'name': domain_name,
|
||||
'id': domain_id['message']})
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
|
||||
LOG.info("Domain id is %s.", domain_id)
|
||||
|
||||
# add it to our cache
|
||||
self.cache_pd[domain_name] = domain_id
|
||||
return domain_id
|
||||
|
||||
def _get_storage_pool_id(self):
|
||||
"""Get the id of the configured storage pool"""
|
||||
def _get_storage_pool_name(self, pool_id):
|
||||
"""Get the protection domain:storage pool name
|
||||
|
||||
if self.storage_pool_id:
|
||||
return self.storage_pool_id
|
||||
From a storage pool id, get the domain name and
|
||||
storage pool names
|
||||
"""
|
||||
req_vars = {'server_ip': self.server_ip,
|
||||
'server_port': self.server_port,
|
||||
'pool_id': pool_id}
|
||||
request = ("https://%(server_ip)s:%(server_port)s"
|
||||
"/api/instances/StoragePool::%(pool_id)s") % req_vars
|
||||
r, response = self._execute_scaleio_get_request(request)
|
||||
|
||||
if not self.protection_domain_name:
|
||||
msg = _("Must specify storage pool name or"
|
||||
" storage pool id.")
|
||||
if r.status_code != http_client.OK:
|
||||
msg = (_("Error getting pool name from id %(pool_id)s: "
|
||||
"%(err_msg)s.")
|
||||
% {'pool_id': pool_id})
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
|
||||
domain_id = self._get_protection_domain_id()
|
||||
pool_name = self.storage_pool_name
|
||||
pool_name = response['name']
|
||||
domain_id = response['protectionDomainId']
|
||||
domain_name = self._get_protection_domain_name(domain_id)
|
||||
|
||||
pool_name = "{}:{}".format(domain_name, pool_name)
|
||||
|
||||
return pool_name
|
||||
|
||||
def _get_protection_domain_name(self, domain_id):
|
||||
"""Get the protection domain name
|
||||
|
||||
From a protection domain id, get the domain name
|
||||
"""
|
||||
req_vars = {'server_ip': self.server_ip,
|
||||
'server_port': self.server_port,
|
||||
'domain_id': domain_id}
|
||||
request = ("https://%(server_ip)s:%(server_port)s"
|
||||
"/api/instances/ProtectionDomain::%(domain_id)s") % req_vars
|
||||
r, response = self._execute_scaleio_get_request(request)
|
||||
|
||||
if r.status_code != http_client.OK:
|
||||
msg = (_("Error getting domain name from id %(domain_id)s: "
|
||||
"%(err_msg)s.")
|
||||
% {'domain_id': domain_id,
|
||||
'err_msg': response})
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
|
||||
domain_name = response['name']
|
||||
|
||||
return domain_name
|
||||
|
||||
def _get_storage_pool_id(self, domain_name, pool_name):
|
||||
"""Get the id of the configured storage pool"""
|
||||
if not domain_name or not pool_name:
|
||||
msg = (_("Unable to query the storage pool id for "
|
||||
"Pool %(pool_name)s and Domain %(domain_name)s.")
|
||||
% {'pool_name': pool_name,
|
||||
'domain_name': domain_name})
|
||||
LOG.error(msg)
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
|
||||
fullname = "{}:{}".format(domain_name, pool_name)
|
||||
if fullname in self.cache_sp:
|
||||
|
||||
return self.cache_sp[fullname]
|
||||
|
||||
domain_id = self._get_protection_domain_id(domain_name)
|
||||
encoded_pool_name = urllib.parse.quote(pool_name, '')
|
||||
req_vars = {'server_ip': self.server_ip,
|
||||
'server_port': self.server_port,
|
||||
@ -1333,29 +1308,38 @@ class ScaleIODriver(driver.VolumeDriver):
|
||||
|
||||
LOG.info("Pool id is %s.", pool_id)
|
||||
|
||||
# add it to ou cache
|
||||
self.cache_sp[fullname] = pool_id
|
||||
return pool_id
|
||||
|
||||
def _get_all_scaleio_volumes(self):
|
||||
"""Gets list of all SIO volumes in PD and SP"""
|
||||
|
||||
sp_id = self._get_storage_pool_id()
|
||||
all_volumes = []
|
||||
# check for every storage pool configured
|
||||
for sp_name in self.storage_pools:
|
||||
splitted_name = sp_name.split(':')
|
||||
domain_name = splitted_name[0]
|
||||
pool_name = splitted_name[1]
|
||||
|
||||
req_vars = {'server_ip': self.server_ip,
|
||||
'server_port': self.server_port,
|
||||
'storage_pool_id': sp_id}
|
||||
request = ("https://%(server_ip)s:%(server_port)s"
|
||||
"/api/instances/StoragePool::%(storage_pool_id)s"
|
||||
"/relationships/Volume") % req_vars
|
||||
LOG.info("ScaleIO get volumes in SP: %s.",
|
||||
request)
|
||||
r, volumes = self._execute_scaleio_get_request(request)
|
||||
sp_id = self._get_storage_pool_id(domain_name, pool_name)
|
||||
|
||||
if r.status_code != http_client.OK:
|
||||
msg = (_("Error calling api "
|
||||
"status code: %d") % r.status_code)
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
req_vars = {'server_ip': self.server_ip,
|
||||
'server_port': self.server_port,
|
||||
'storage_pool_id': sp_id}
|
||||
request = ("https://%(server_ip)s:%(server_port)s"
|
||||
"/api/instances/StoragePool::%(storage_pool_id)s"
|
||||
"/relationships/Volume") % req_vars
|
||||
r, volumes = self._execute_scaleio_get_request(request)
|
||||
|
||||
return volumes
|
||||
if r.status_code != http_client.OK:
|
||||
msg = (_("Error calling api "
|
||||
"status code: %d") % r.status_code)
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
|
||||
all_volumes.extend(volumes)
|
||||
|
||||
return all_volumes
|
||||
|
||||
def get_manageable_volumes(self, cinder_volumes, marker, limit, offset,
|
||||
sort_keys, sort_dirs):
|
||||
|
@ -0,0 +1,22 @@
|
||||
---
|
||||
deprecations:
|
||||
- |
|
||||
The ScaleIO Driver has deprecated several options specified
|
||||
in ``cinder.conf``:
|
||||
* ``sio_protection_domain_id``
|
||||
* ``sio_protection_domain_name``,
|
||||
* ``sio_storage_pool_id``
|
||||
* ``sio_storage_pool_name``.
|
||||
Users of the ScaleIO Driver should now utilize the
|
||||
``sio_storage_pools`` options to provide a list of
|
||||
protection_domain:storage_pool pairs.
|
||||
- |
|
||||
The ScaleIO Driver has deprecated the ability to specify the
|
||||
protection domain, as ``sio:pd_name``, and storage pool,
|
||||
as ``sio:sp_name``, extra specs in volume types.
|
||||
The supported way to specify a specific protection domain and
|
||||
storage pool in a volume type is to define a ``pool_name``
|
||||
extra spec and set the value to the appropriate
|
||||
``protection_domain_name:storage_pool_name``.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user