diff --git a/magnum/common/clients.py b/magnum/common/clients.py index d56b6344d1..6d3443ae77 100644 --- a/magnum/common/clients.py +++ b/magnum/common/clients.py @@ -104,12 +104,19 @@ neutron_client_opts = [ 'Type of endpoint in Identity service catalog to use ' 'for communication with the OpenStack service.'))] +cinder_client_opts = [ + cfg.StrOpt('region_name', + help=_('Region in Identity service catalog to use for ' + 'communication with the OpenStack service.'))] + + cfg.CONF.register_opts(magnum_client_opts, group='magnum_client') cfg.CONF.register_opts(heat_client_opts, group='heat_client') cfg.CONF.register_opts(glance_client_opts, group='glance_client') cfg.CONF.register_opts(barbican_client_opts, group='barbican_client') cfg.CONF.register_opts(nova_client_opts, group='nova_client') cfg.CONF.register_opts(neutron_client_opts, group='neutron_client') +cfg.CONF.register_opts(cinder_client_opts, group='cinder_client') class OpenStackClients(object): @@ -134,6 +141,10 @@ class OpenStackClients(object): endpoint_type=endpoint_type, region_name=region_name) + def cinder_region_name(self): + cinder_region_name = self._get_client_option('cinder', 'region_name') + return self.keystone().get_validate_region_name(cinder_region_name) + @property def auth_url(self): return self.keystone().auth_url diff --git a/magnum/common/exception.py b/magnum/common/exception.py index c890a87aeb..caca30f5fa 100644 --- a/magnum/common/exception.py +++ b/magnum/common/exception.py @@ -564,3 +564,7 @@ class TrusteeDeleteFailed(MagnumException): class QuotaAlreadyExists(Conflict): message = _("Quota for project %(project_id)s already exists " "for resource %(resource)s.") + + +class RegionsListFailed(MagnumException): + message = _("Failed to list regions.") diff --git a/magnum/common/keystone.py b/magnum/common/keystone.py index ee40cca48a..f555880ff9 100644 --- a/magnum/common/keystone.py +++ b/magnum/common/keystone.py @@ -196,3 +196,28 @@ class KeystoneClientV3(object): except Exception: LOG.exception(_LE('Failed to delete trustee')) raise exception.TrusteeDeleteFailed(trustee_id=trustee_id) + + def get_validate_region_name(self, region_name): + if region_name is None: + message = _("region_name needs to be configured in magnum.conf") + raise exception.InvalidParameterValue(message) + """matches the region of a public endpoint for the Keystone + service.""" + try: + regions = self.client.regions.list() + except kc_exception.NotFound: + pass + except Exception: + LOG.exception(_LE('Failed to list regions')) + raise exception.RegionsListFailed() + region_list = [] + for region in regions: + region_list.append(region.id) + if region_name not in region_list: + raise exception.InvalidParameterValue(_( + 'region_name %(region_name)s is invalid, ' + 'expecting a region_name in %(region_name_list)s.') % { + 'region_name': region_name, + 'region_name_list': '/'.join( + region_list + ['unspecified'])}) + return region_name diff --git a/magnum/tests/unit/common/test_keystone.py b/magnum/tests/unit/common/test_keystone.py index 069c91ced7..3d9aa665da 100644 --- a/magnum/tests/unit/common/test_keystone.py +++ b/magnum/tests/unit/common/test_keystone.py @@ -139,3 +139,30 @@ class KeystoneClientTest(base.BaseTestCase): trustor_user='123456', project='654321', trustee_user='888888', role_names=['role3'], impersonation=True) + + def test_get_validate_region_name(self, mock_ks): + key = 'region_name' + val = 'RegionOne' + cfg.CONF.set_override(key, val, 'cinder_client') + mock_region = mock.MagicMock() + mock_region.id = 'RegionOne' + mock_ks.return_value.regions.list.return_value = [mock_region] + ks_client = keystone.KeystoneClientV3(self.ctx) + region_name = ks_client.get_validate_region_name(val) + self.assertEqual('RegionOne', region_name) + + def test_get_validate_region_name_not_found(self, mock_ks): + key = 'region_name' + val = 'region123' + cfg.CONF.set_override(key, val, 'cinder_client') + ks_client = keystone.KeystoneClientV3(self.ctx) + self.assertRaises(exception.InvalidParameterValue, + ks_client.get_validate_region_name, val) + + def test_get_validate_region_name_is_None(self, mock_ks): + key = 'region_name' + val = None + cfg.CONF.set_override(key, val, 'cinder_client') + ks_client = keystone.KeystoneClientV3(self.ctx) + self.assertRaises(exception.InvalidParameterValue, + ks_client.get_validate_region_name, val)