From c01240c910a9a18376661ebdb3c2fe199dc030fb Mon Sep 17 00:00:00 2001 From: Sumant Murke Date: Mon, 28 Mar 2016 18:30:35 +0000 Subject: [PATCH] Adding gnocchi client and keystoneauth to rally Adding gnocchi client and verifying it by unit test case and also registering gnocchi service to rally. Replacing "default" configuration with None for project_domain_name and user_domain_name to make it compatible with keystoneauth1 v2.0 and v3. Also adding gnocchicclient and keystonauth1 to requirements.txt Change-Id: Ie9a30297590f4447e39ecd44297e6d216899ef89 --- rally/common/objects/credential.py | 4 +-- rally/consts.py | 3 ++ rally/deployment/engines/existing.py | 4 +-- rally/osclients.py | 37 ++++++++++++++++++++-- requirements.txt | 2 ++ tests/unit/common/objects/test_endpoint.py | 12 +++---- tests/unit/fakes.py | 23 ++++++++++++++ tests/unit/test_osclients.py | 18 +++++++++++ 8 files changed, 91 insertions(+), 12 deletions(-) diff --git a/rally/common/objects/credential.py b/rally/common/objects/credential.py index 16054f5f28..b6cd61a372 100644 --- a/rally/common/objects/credential.py +++ b/rally/common/objects/credential.py @@ -22,8 +22,8 @@ class Credential(object): permission=consts.EndpointPermission.USER, region_name=None, endpoint_type=consts.EndpointType.PUBLIC, domain_name=None, endpoint=None, - user_domain_name="Default", admin_domain_name="Default", - project_domain_name="Default", + user_domain_name=None, admin_domain_name="Default", + project_domain_name=None, https_insecure=False, https_cacert=None): self.auth_url = auth_url self.username = username diff --git a/rally/consts.py b/rally/consts.py index 78ce89ccca..27ab2e6c5a 100644 --- a/rally/consts.py +++ b/rally/consts.py @@ -109,6 +109,7 @@ class _Service(utils.ImmutableMixin, utils.EnumMixin): MISTRAL = "mistral" MURANO = "murano" IRONIC = "ironic" + GNOCCHI = "gnocchi" class _ServiceType(utils.ImmutableMixin, utils.EnumMixin): @@ -134,6 +135,7 @@ class _ServiceType(utils.ImmutableMixin, utils.EnumMixin): WORKFLOW_EXECUTION = "workflowv2" APPLICATION_CATALOG = "application-catalog" BARE_METAL = "baremetal" + METRIC = "metric" def __init__(self): self.__names = { @@ -157,6 +159,7 @@ class _ServiceType(utils.ImmutableMixin, utils.EnumMixin): self.WORKFLOW_EXECUTION: _Service.MISTRAL, self.APPLICATION_CATALOG: _Service.MURANO, self.BARE_METAL: _Service.IRONIC, + self.METRIC: _Service.GNOCCHI, } def __getitem__(self, service_type): diff --git a/rally/deployment/engines/existing.py b/rally/deployment/engines/existing.py index 3417c2007d..203cb716bf 100644 --- a/rally/deployment/engines/existing.py +++ b/rally/deployment/engines/existing.py @@ -130,9 +130,9 @@ class ExistingCloud(engine.Engine): consts.EndpointType.PUBLIC), endpoint=common.get("endpoint"), domain_name=user.get("domain_name"), - user_domain_name=user.get("user_domain_name", "Default"), + user_domain_name=user.get("user_domain_name", None), admin_domain_name=user.get("admin_domain_name", "Default"), - project_domain_name=user.get("project_domain_name", "Default"), + project_domain_name=user.get("project_domain_name", None), https_insecure=common.get("https_insecure", False), https_cacert=common.get("https_cacert") ) diff --git a/rally/osclients.py b/rally/osclients.py index 8c80e1b975..e4c522f97e 100644 --- a/rally/osclients.py +++ b/rally/osclients.py @@ -160,6 +160,21 @@ class OSClient(plugin.Plugin): auth=auth, verify=not self.credential.insecure, timeout=CONF.openstack_client_http_timeout) + def _get_keystoneauth_session(self): + from keystoneauth1 import loading + from keystoneauth1 import session + loader = loading.get_plugin_loader("password") + plugin = loader.load_from_options( + auth_url=self.credential.auth_url, + username=self.credential.username, + password=self.credential.password, + user_domain_name=self.credential.user_domain_name, + project_name=self.credential.tenant_name, + project_domain_name=self.credential.project_domain_name) + sess = session.Session(auth=plugin, verify=( + not self.credential.insecure)) + return sess + def _get_endpoint(self, service_type=None): kc = self.keystone() api_url = kc.service_catalog.url_for( @@ -188,9 +203,11 @@ class OSClient(plugin.Plugin): kw.update({ domain_name_key: self.credential.domain_name}) kw.update({ - user_domain_name_key: self.credential.user_domain_name}) + user_domain_name_key: + self.credential.user_domain_name or "Default"}) kw.update({ - project_domain_name_key: self.credential.project_domain_name}) + project_domain_name_key: + self.credential.project_domain_name or "Default"}) return kw @@ -456,6 +473,22 @@ class Ceilometer(OSClient): return client +@configure("gnocchi", default_service_type="metric", default_version="1", + supported_versions=["1"]) +class Gnocchi(OSClient): + + def create_client(self, version=None, service_type=None): + """Return gnocchi client.""" + # NOTE(sumantmurke): gnocchiclient requires keystoneauth1 for + # authenticating and creating a session. + from gnocchiclient import client as gnocchi + service_type = self.choose_service_type(service_type) + sess = self._get_keystoneauth_session() + gclient = gnocchi.Client(version=self.choose_version( + version), session=sess, service_type=service_type) + return gclient + + @configure("ironic", default_version="1", default_service_type="baremetal", supported_versions=["1"]) class Ironic(OSClient): diff --git a/requirements.txt b/requirements.txt index 50165389c0..5d535b9090 100644 --- a/requirements.txt +++ b/requirements.txt @@ -21,8 +21,10 @@ pbr>=1.6 # Apache-2.0 PrettyTable<0.8,>=0.7 # BSD PyYAML>=3.1.0 # MIT python-designateclient>=1.5.0 # Apache-2.0 +gnocchiclient>=2.2.0 # Apache-2.0 python-glanceclient>=2.0.0 # Apache-2.0 python-keystoneclient!=1.8.0,!=2.1.0,>=1.6.0 # Apache-2.0 +keystoneauth1>=2.1.0 # Apache-2.0 python-novaclient!=2.33.0,>=2.29.0 # Apache-2.0 python-neutronclient>=4.1.1 # Apache-2.0 python-cinderclient>=1.6.0 # Apache-2.0 diff --git a/tests/unit/common/objects/test_endpoint.py b/tests/unit/common/objects/test_endpoint.py index 83a14bd4f2..4e34f7f5ca 100644 --- a/tests/unit/common/objects/test_endpoint.py +++ b/tests/unit/common/objects/test_endpoint.py @@ -36,8 +36,8 @@ class EndpointTestCase(test.TestCase): "endpoint_type": consts.EndpointType.PUBLIC, "https_insecure": False, "https_cacert": None, - "project_domain_name": "Default", - "user_domain_name": "Default", + "project_domain_name": None, + "user_domain_name": None, "admin_domain_name": "Default"}) def test_to_dict_with_include_permission(self): @@ -57,8 +57,8 @@ class EndpointTestCase(test.TestCase): "endpoint_type": consts.EndpointType.PUBLIC, "https_insecure": False, "https_cacert": None, - "project_domain_name": "Default", - "user_domain_name": "Default", + "project_domain_name": None, + "user_domain_name": None, "admin_domain_name": "Default"}) def test_to_dict_with_kwarg_credential(self): @@ -78,6 +78,6 @@ class EndpointTestCase(test.TestCase): "endpoint_type": consts.EndpointType.PUBLIC, "https_insecure": False, "https_cacert": None, - "project_domain_name": "Default", - "user_domain_name": "Default", + "project_domain_name": None, + "user_domain_name": None, "admin_domain_name": "Default"}) diff --git a/tests/unit/fakes.py b/tests/unit/fakes.py index f234960b48..ae2537220f 100644 --- a/tests/unit/fakes.py +++ b/tests/unit/fakes.py @@ -207,6 +207,13 @@ class FakeSecurityGroupRule(FakeResource): setattr(self, key, value) +class FakeMetric(FakeResource): + def __init_(self, manager=None, **kwargs): + super(FakeMetric, self).__init__(manager) + self.metric = kwargs.get("metric_name") + self.optional_args = kwargs.get("optional_args", {}) + + class FakeAlarm(FakeResource): def __init__(self, manager=None, **kwargs): super(FakeAlarm, self).__init__(manager) @@ -714,6 +721,17 @@ class FakeRolesManager(FakeManager): pass +class FakeMetricManager(FakeManager): + + def create(self, **kwargs): + metric = FakeMetric(self, **kwargs) + return self._cache(metric) + + def get(self, metric_id): + metric = self.find(metric_id=metric_id) + return [metric] + + class FakeAlarmManager(FakeManager): def get(self, alarm_id): @@ -1036,6 +1054,11 @@ class FakeCeilometerClient(object): self.query_alarm_history = FakeQueryManager() +class FakeGnocchiClient(object): + def __init__(self): + self.metric = FakeMetricManager() + + class FakeMonascaClient(object): def __init__(self): diff --git a/tests/unit/test_osclients.py b/tests/unit/test_osclients.py index 111ded4427..9222b0f703 100644 --- a/tests/unit/test_osclients.py +++ b/tests/unit/test_osclients.py @@ -493,6 +493,24 @@ class OSClientsTestCase(test.TestCase): self.assertEqual(fake_ceilometer, self.clients.cache["ceilometer"]) + def test_gnocchi(self): + fake_gnocchi = fakes.FakeGnocchiClient() + mock_gnocchi = mock.MagicMock() + mock_gnocchi.client.Client.return_value = fake_gnocchi + mock_keystoneauth1 = mock.MagicMock() + self.assertNotIn("gnocchi", self.clients.cache) + with mock.patch.dict("sys.modules", + {"gnocchiclient": mock_gnocchi, + "keystoneauth1": mock_keystoneauth1}): + client = self.clients.gnocchi() + + self.assertEqual(fake_gnocchi, client) + kw = {"version": "1", + "session": mock_keystoneauth1.session.Session(), + "service_type": "metric"} + mock_gnocchi.client.Client.assert_called_once_with(**kw) + self.assertEqual(fake_gnocchi, self.clients.cache["gnocchi"]) + def test_monasca(self): fake_monasca = fakes.FakeMonascaClient() mock_monasca = mock.MagicMock()