From cfb9e6b5b0e53834df6a96f15d2815b350469fac Mon Sep 17 00:00:00 2001 From: Alexander Chadin Date: Tue, 5 Jul 2016 10:47:58 +0300 Subject: [PATCH] Add support for watcher osclient and watcher related types This patch set registers Watcher as Service for Rally and adds Watcher Goal and Strategy Types with related unit tests. Also it adds *.DS_Store type to gitignore and python-watcherclient to the requirements.txt to support Watcher in future. Change-Id: I0ed4154bdb497d76b768c0eace74940f8811a8e8 --- .gitignore | 3 ++ rally/consts.py | 3 ++ rally/osclients.py | 19 +++++++++++ rally/plugins/openstack/cleanup/resources.py | 21 ++++++++++++ requirements.txt | 1 + tests/ci/osresources.py | 20 +++++++++++ tests/unit/fakes.py | 33 +++++++++++++++++++ .../openstack/cleanup/test_resources.py | 27 +++++++++++++++ tests/unit/test_osclients.py | 25 ++++++++++++++ 9 files changed, 152 insertions(+) diff --git a/.gitignore b/.gitignore index d311e9b9c5..3a8cb664d4 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,6 @@ doc/source/_build/ .idea .pydevproject *.swp + +# Mac Desktop Service Store +*.DS_Store diff --git a/rally/consts.py b/rally/consts.py index 3b15251d00..dab791f259 100644 --- a/rally/consts.py +++ b/rally/consts.py @@ -113,6 +113,7 @@ class _Service(utils.ImmutableMixin, utils.EnumMixin): IRONIC = "ironic" GNOCCHI = "gnocchi" MAGNUM = "magnum" + WATCHER = "watcher" class _ServiceType(utils.ImmutableMixin, utils.EnumMixin): @@ -141,6 +142,7 @@ class _ServiceType(utils.ImmutableMixin, utils.EnumMixin): BARE_METAL = "baremetal" METRIC = "metric" CONTAINER_INFRA = "container-infra" + INFRA_OPTIM = "infra-optim" def __init__(self): self.__names = { @@ -167,6 +169,7 @@ class _ServiceType(utils.ImmutableMixin, utils.EnumMixin): self.BARE_METAL: _Service.IRONIC, self.METRIC: _Service.GNOCCHI, self.CONTAINER_INFRA: _Service.MAGNUM, + self.INFRA_OPTIM: _Service.WATCHER, } def __getitem__(self, service_type): diff --git a/rally/osclients.py b/rally/osclients.py index 233bdb75c9..10b9dc519b 100644 --- a/rally/osclients.py +++ b/rally/osclients.py @@ -744,6 +744,25 @@ class Magnum(OSClient): return magnum.Client(session=session, interface=endpoint_type[0]) +@configure("watcher", default_version="1", default_service_type="infra-optim", + supported_versions=["1"]) +class Watcher(OSClient): + def create_client(self, version=None, service_type=None): + """Return watcher client.""" + from watcherclient import client as watcher_client + kc = self.keystone() + watcher_api_url = self._get_endpoint( + self.choose_service_type(service_type)) + client = watcher_client.Client( + self.choose_version(version), + watcher_api_url, + token=kc.auth_token, + timeout=CONF.openstack_client_http_timeout, + insecure=self.credential.insecure, + ca_file=self.credential.cacert) + return client + + class Clients(object): """This class simplify and unify work with OpenStack python clients.""" diff --git a/rally/plugins/openstack/cleanup/resources.py b/rally/plugins/openstack/cleanup/resources.py index 5161370a90..37fca765f0 100644 --- a/rally/plugins/openstack/cleanup/resources.py +++ b/rally/plugins/openstack/cleanup/resources.py @@ -720,6 +720,27 @@ class FuelEnvironment(base.ResourceManager): futils.FuelScenario)] +# WATCHER + +@base.resource("watcher", "audit_template", order=1500, + admin_required=True, tenant_resource=True) +class WatcherTemplate(SynchronizedDeletion, base.ResourceManager): + + def id(self): + return self.raw_resource.uuid + + def is_deleted(self): + from watcherclient.common.apiclient import exceptions + try: + self._manager().get(self.id()) + return False + except exceptions.NotFound: + return True + + def list(self): + return self._manager().list(limit=0) + + # KEYSTONE _keystone_order = get_order(9000) diff --git a/requirements.txt b/requirements.txt index 2c35c73e64..997fe78b2b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -32,6 +32,7 @@ python-saharaclient>=0.13.0 # Apache-2.0 python-troveclient>=2.2.0 # Apache-2.0 python-zaqarclient>=1.0.0 # Apache-2.0 python-swiftclient>=2.2.0 # Apache-2.0 +python-watcherclient>=0.23.0 # Apache-2.0 python-subunit>=0.0.18 # Apache-2.0/BSD requests>=2.10.0 # Apache-2.0 SQLAlchemy<1.1.0,>=1.0.10 # MIT diff --git a/tests/ci/osresources.py b/tests/ci/osresources.py index 898ae8bf5c..14c6be74ae 100755 --- a/tests/ci/osresources.py +++ b/tests/ci/osresources.py @@ -208,6 +208,26 @@ class Cinder(ResourceManager): search_opts={"all_tenants": True}) +class Watcher(ResourceManager): + + REQUIRED_SERVICE = consts.Service.WATCHER + + def list_audits(self): + return self.client.audit.list() + + def list_audit_templates(self): + return self.client.audit_template.list() + + def list_goals(self): + return self.client.goal.list() + + def list_action_plans(self): + return self.client.action_plan.list() + + def list_actions(self): + return self.client.action.list() + + class CloudResources(object): """List and compare cloud resources. diff --git a/tests/unit/fakes.py b/tests/unit/fakes.py index c273e900b8..8e6949f83c 100644 --- a/tests/unit/fakes.py +++ b/tests/unit/fakes.py @@ -127,6 +127,14 @@ class FakeImage(FakeResource): self.update = mock.MagicMock() +class FakeStrategy(FakeResource): + pass + + +class FakeGoal(FakeResource): + pass + + class FakeMurano(FakeResource): pass @@ -425,6 +433,18 @@ class FakeImageManager(FakeManager): self.resources_order.remove(resource) +class FakeStrategyManager(FakeManager): + + def create(self): + return FakeStrategy(self) + + +class FakeGoalManager(FakeManager): + + def create(self): + return FakeGoal(self) + + class FakePackageManager(FakeManager): def create(self, package_descr, package_arch, package_class=FakeMurano): @@ -1493,6 +1513,13 @@ class FakeMagnumClient(object): pass +class FakeWatcherClient(object): + + def __init__(self): + self.strategy = FakeStrategyManager() + self.goal = FakeGoalManager() + + class FakeClients(object): def __init__(self, credential_=None): @@ -1513,6 +1540,7 @@ class FakeClients(object): self._monasca = None self._ec2 = None self._senlin = None + self._watcher = None self._credential = credential_ or objects.Credential( "http://fake.example.org:5000/v2.0/", "fake_username", @@ -1607,6 +1635,11 @@ class FakeClients(object): self._senlin = FakeSenlinClient() return self._senlin + def watcher(self): + if not self._watcher: + self._watcher = FakeWatcherClient() + return self._watcher + class FakeRunner(object): diff --git a/tests/unit/plugins/openstack/cleanup/test_resources.py b/tests/unit/plugins/openstack/cleanup/test_resources.py index 15d15c494a..ad509ae98f 100644 --- a/tests/unit/plugins/openstack/cleanup/test_resources.py +++ b/tests/unit/plugins/openstack/cleanup/test_resources.py @@ -18,6 +18,7 @@ import ddt import mock from neutronclient.common import exceptions as neutron_exceptions from novaclient import exceptions as nova_exc +from watcherclient.common.apiclient import exceptions as watcher_exceptions from rally.common import utils from rally.plugins.openstack.cleanup import resources @@ -753,3 +754,29 @@ class FuelEnvironmentTestCase(test.TestCase): fres = resources.FuelEnvironment() self.assertEqual(envs[:-1], fres.list()) + + +class WatcherTemplateTestCase(test.TestCase): + + def test_id(self): + watcher = resources.WatcherTemplate() + watcher.raw_resource = mock.MagicMock(uuid=100) + self.assertEqual(100, watcher.id()) + + @mock.patch("%s.WatcherTemplate._manager" % BASE) + def test_is_deleted(self, mock__manager): + mock__manager.return_value.get.return_value = None + watcher = resources.WatcherTemplate() + watcher.id = mock.Mock() + self.assertFalse(watcher.is_deleted()) + mock__manager.side_effect = [watcher_exceptions.NotFound()] + self.assertTrue(watcher.is_deleted()) + + def test_list(self): + watcher = resources.WatcherTemplate() + watcher._manager = mock.MagicMock() + + watcher.list() + + self.assertEqual("audit_template", watcher._resource) + watcher._manager().list.assert_called_once_with(limit=0) diff --git a/tests/unit/test_osclients.py b/tests/unit/test_osclients.py index 16ba3ff1ca..88cce985a2 100644 --- a/tests/unit/test_osclients.py +++ b/tests/unit/test_osclients.py @@ -856,3 +856,28 @@ class OSClientsTestCase(test.TestCase): session=self.fake_keystone.session) self.assertEqual(fake_magnum, self.clients.cache["magnum"]) + + def test_watcher(self): + fake_watcher = fakes.FakeWatcherClient() + mock_watcher = mock.MagicMock() + mock_watcher.client.Client.return_value = fake_watcher + self.assertNotIn("watcher", self.clients.cache) + with mock.patch.dict("sys.modules", {"watcherclient": mock_watcher}): + client = self.clients.watcher() + + self.assertEqual(fake_watcher, client) + + self.service_catalog.url_for.assert_called_once_with( + service_type="infra-optim", + endpoint_type=consts.EndpointType.PUBLIC, + region_name=self.credential.region_name) + + mock_watcher.client.Client.assert_called_once_with( + "1", + self.service_catalog.url_for.return_value, + token=self.fake_keystone.auth_token, + ca_file=None, + insecure=False, + timeout=180.0) + + self.assertEqual(fake_watcher, self.clients.cache["watcher"])