diff --git a/rally-jobs/rally-magnum.yaml b/rally-jobs/rally-magnum.yaml new file mode 100644 index 00000000..77315e1c --- /dev/null +++ b/rally-jobs/rally-magnum.yaml @@ -0,0 +1,49 @@ +--- + MagnumBaymodels.list_baymodels: + - + runner: + type: "constant" + times: 40 + concurrency: 20 + context: + users: + tenants: 1 + users_per_tenant: 1 + baymodels: + image_id: "fedora-atomic-latest" + flavor_id: "m1.small" + master_flavor_id: "m1.small" + external_network_id: "public" + dns_nameserver: "8.8.8.8" + docker_volume_size: 5 + coe: "kubernetes" + network_driver: "flannel" + docker_storage_driver: "devicemapper" + master_lb_enabled: False + sla: + failure_rate: + max: 0 + + - + runner: + type: "constant" + times: 40 + concurrency: 20 + context: + users: + tenants: 1 + users_per_tenant: 1 + baymodels: + image_id: "fedora-atomic-latest" + flavor_id: "m1.small" + master_flavor_id: "m1.small" + external_network_id: "public" + dns_nameserver: "8.8.8.8" + docker_volume_size: 5 + coe: "swarm" + network_driver: "docker" + docker_storage_driver: "devicemapper" + master_lb_enabled: False + sla: + failure_rate: + max: 0 diff --git a/rally/plugins/openstack/cleanup/resources.py b/rally/plugins/openstack/cleanup/resources.py index fb43c33d..4234806a 100644 --- a/rally/plugins/openstack/cleanup/resources.py +++ b/rally/plugins/openstack/cleanup/resources.py @@ -66,6 +66,27 @@ class QuotaMixin(SynchronizedDeletion): return [self.tenant_uuid] if self.tenant_uuid else [] +# MAGNUM + +@base.resource("magnum", "baymodels", order=80, tenant_resource=True) +class MagnumBaymodel(base.ResourceManager): + + def id(self): + """Returns id of resource.""" + return self.raw_resource.uuid + + def list(self): + result = [] + marker = None + while True: + baymodels = self._manager().list(marker=marker) + if not baymodels: + break + result.extend(baymodels) + marker = baymodels[-1].uuid + return result + + # HEAT @base.resource("heat", "stacks", order=100, tenant_resource=True) diff --git a/rally/plugins/openstack/context/magnum/__init__.py b/rally/plugins/openstack/context/magnum/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/rally/plugins/openstack/scenarios/magnum/__init__.py b/rally/plugins/openstack/scenarios/magnum/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/rally/plugins/openstack/scenarios/magnum/utils.py b/rally/plugins/openstack/scenarios/magnum/utils.py new file mode 100644 index 00000000..d2f22ae9 --- /dev/null +++ b/rally/plugins/openstack/scenarios/magnum/utils.py @@ -0,0 +1,50 @@ +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from rally.plugins.openstack import scenario +from rally.task import atomic + + +class MagnumScenario(scenario.OpenStackScenario): + """Base class for Magnum scenarios with basic atomic actions.""" + + @atomic.action_timer("magnum.list_baymodels") + def _list_baymodels(self, **kwargs): + """Return list of baymodels. + + :param limit: (Optional) The maximum number of results to return + per request, if: + + 1) limit > 0, the maximum number of baymodels to return. + 2) limit param is NOT specified (None), the number of items + returned respect the maximum imposed by the Magnum API + (see Magnum's api.max_limit option). + :param kwargs: Optional additional arguments for baymodels listing + + :returns: baymodels list + """ + + return self.clients("magnum").baymodels.list(**kwargs) + + @atomic.action_timer("magnum.create_baymodel") + def _create_baymodel(self, **kwargs): + """Create a baymodel + + :param kwargs: optional additional arguments for baymodel creation + :returns: magnum baymodel + """ + + kwargs["name"] = self.generate_random_name() + + return self.clients("magnum").baymodels.create(**kwargs) diff --git a/tests/ci/osresources.py b/tests/ci/osresources.py index 73c5be92..a0981758 100755 --- a/tests/ci/osresources.py +++ b/tests/ci/osresources.py @@ -92,6 +92,14 @@ class Keystone(ResourceManager): return self.client.roles.list() +class Magnum(ResourceManager): + + REQUIRED_SERVICE = consts.Service.MAGNUM + + def list_baymodels(self): + return self.client.baymodels.list() + + class Nova(ResourceManager): REQUIRED_SERVICE = consts.Service.NOVA diff --git a/tests/unit/fakes.py b/tests/unit/fakes.py index 0735bc23..4c195b6c 100644 --- a/tests/unit/fakes.py +++ b/tests/unit/fakes.py @@ -322,6 +322,10 @@ class FakeObject(FakeResource): pass +class FakeBaymodel(FakeResource): + pass + + class FakeManager(object): def __init__(self): @@ -514,6 +518,23 @@ class FakeKeypairManager(FakeManager): self.resources_order.remove(resource) +class FakeBaymodelManager(FakeManager): + + def create(self, name): + baymodel = FakeBaymodel(self) + baymodel.name = name or baymodel.name + return self._cache(baymodel) + + def delete(self, resource): + if not isinstance(resource, six.string_types): + resource = resource.id + + cached = self.get(resource) + if cached is not None: + del self.cache[resource] + self.resources_order.remove(resource) + + class FakeStackManager(FakeManager): def create(self, name): @@ -1512,7 +1533,7 @@ class FakeSenlinClient(object): class FakeMagnumClient(object): def __init__(self): - pass + self.baymodels = FakeBaymodelManager() class FakeWatcherClient(object): diff --git a/tests/unit/plugins/openstack/cleanup/test_resources.py b/tests/unit/plugins/openstack/cleanup/test_resources.py index be8cd735..37014498 100644 --- a/tests/unit/plugins/openstack/cleanup/test_resources.py +++ b/tests/unit/plugins/openstack/cleanup/test_resources.py @@ -65,6 +65,27 @@ class QuotaMixinTestCase(test.TestCase): self.assertEqual([quota.tenant_uuid], quota.list()) +class MagnumBaymodelTestCase(test.TestCase): + + def test_id(self): + baymodel = resources.MagnumBaymodel() + baymodel.raw_resource = mock.MagicMock() + self.assertEqual(baymodel.raw_resource.uuid, baymodel.id()) + + def test_list(self): + baymodels = [mock.MagicMock(), mock.MagicMock(), mock.MagicMock(), + mock.MagicMock()] + baymodel = resources.MagnumBaymodel() + baymodel._manager = mock.MagicMock() + baymodel._manager.return_value.list.side_effect = ( + baymodels[:2], baymodels[2:4], []) + self.assertEqual(baymodels, baymodel.list()) + self.assertEqual( + [mock.call(marker=None), mock.call(marker=baymodels[1].uuid), + mock.call(marker=baymodels[3].uuid)], + baymodel._manager.return_value.list.call_args_list) + + class NovaServerTestCase(test.TestCase): def test_list(self): @@ -879,4 +900,4 @@ class WatcherActionPlanTestCase(test.TestCase): watcher.list() self.assertEqual("action_plan", watcher._resource) - watcher._manager().list.assert_called_once_with(limit=0) \ No newline at end of file + watcher._manager().list.assert_called_once_with(limit=0) diff --git a/tests/unit/plugins/openstack/context/magnum/__init__.py b/tests/unit/plugins/openstack/context/magnum/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/plugins/openstack/scenarios/magnum/__init__.py b/tests/unit/plugins/openstack/scenarios/magnum/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/plugins/openstack/scenarios/magnum/test_utils.py b/tests/unit/plugins/openstack/scenarios/magnum/test_utils.py new file mode 100644 index 00000000..747a1edd --- /dev/null +++ b/tests/unit/plugins/openstack/scenarios/magnum/test_utils.py @@ -0,0 +1,60 @@ +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import mock + +from rally.plugins.openstack.scenarios.magnum import utils +from tests.unit import test + + +class MagnumScenarioTestCase(test.ScenarioTestCase): + def setUp(self): + super(MagnumScenarioTestCase, self).setUp() + self.baymodel = mock.Mock() + self.scenario = utils.MagnumScenario(self.context) + + def test_list_baymodels(self): + scenario = utils.MagnumScenario(self.context) + fake_baymodel_list = [self.baymodel] + + self.clients("magnum").baymodels.list.return_value = fake_baymodel_list + return_baymodels_list = scenario._list_baymodels() + self.assertEqual(fake_baymodel_list, return_baymodels_list) + + self.clients("magnum").baymodels.list.assert_called_once_with() + self._test_atomic_action_timer(scenario.atomic_actions(), + "magnum.list_baymodels") + + def test_create_baymodel(self): + self.scenario.generate_random_name = mock.Mock( + return_value="generated_name") + fake_baymodel = self.baymodel + self.clients("magnum").baymodels.create.return_value = fake_baymodel + + return_baymodel = self.scenario._create_baymodel( + image="test_image", + keypair="test_key", + external_network="public", + dns_nameserver="8.8.8.8", + flavor="m1.large", + docker_volume_size=50, + network_driver="docker", + coe="swarm") + + self.assertEqual(fake_baymodel, return_baymodel) + args, kwargs = self.clients("magnum").baymodels.create.call_args + self.assertEqual("generated_name", kwargs["name"]) + + self._test_atomic_action_timer(self.scenario.atomic_actions(), + "magnum.create_baymodel")