From 36d7a08960d96d437394e71e7dc073c7876de70c Mon Sep 17 00:00:00 2001 From: Endre Karlson Date: Tue, 24 Nov 2015 13:43:31 +0100 Subject: [PATCH] Add Designate API V2 support - part 1 This commit adds basic support for Rally > Designate V2 with the RecordSet and Zone resources. More functionality will be added later. Change-Id: I42456a404a8c8733103228f3b1e83215da9ae641 --- rally-jobs/rally-designate.yaml | 41 ++++++++++ .../openstack/scenarios/designate/basic.py | 74 ++++++++++++++++--- .../openstack/scenarios/designate/utils.py | 61 +++++++++++++++ .../designate/create-and-delete-zone.json | 25 +++++++ .../designate/create-and-delete-zone.yaml | 17 +++++ .../designate/create-and-list-zones.json | 25 +++++++ .../designate/create-and-list-zones.yaml | 17 +++++ .../scenarios/designate/list-recordsets.json | 20 +++++ .../scenarios/designate/list-recordsets.yaml | 13 ++++ .../tasks/scenarios/designate/list-zones.json | 17 +++++ .../tasks/scenarios/designate/list-zones.yaml | 11 +++ .../openstack/context/designate/__init__.py | 0 .../scenarios/designate/test_basic.py | 44 +++++++++++ .../scenarios/designate/test_utils.py | 63 ++++++++++++++++ 14 files changed, 419 insertions(+), 9 deletions(-) create mode 100644 samples/tasks/scenarios/designate/create-and-delete-zone.json create mode 100644 samples/tasks/scenarios/designate/create-and-delete-zone.yaml create mode 100644 samples/tasks/scenarios/designate/create-and-list-zones.json create mode 100644 samples/tasks/scenarios/designate/create-and-list-zones.yaml create mode 100644 samples/tasks/scenarios/designate/list-recordsets.json create mode 100644 samples/tasks/scenarios/designate/list-recordsets.yaml create mode 100644 samples/tasks/scenarios/designate/list-zones.json create mode 100644 samples/tasks/scenarios/designate/list-zones.yaml create mode 100644 tests/unit/plugins/openstack/context/designate/__init__.py diff --git a/rally-jobs/rally-designate.yaml b/rally-jobs/rally-designate.yaml index bdbe2360..12bc0e93 100644 --- a/rally-jobs/rally-designate.yaml +++ b/rally-jobs/rally-designate.yaml @@ -115,3 +115,44 @@ failure_rate: max: 0 + DesignateBasic.create_and_list_zones: + - + runner: + type: "constant" + times: 10 + concurrency: 1 + context: + users: + tenants: 2 + users_per_tenant: 2 + sla: + failure_rate: + max: 0 + + DesignateBasic.create_and_delete_zone: + - + runner: + type: "constant" + times: 10 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 2 + sla: + failure_rate: + max: 0 + + DesignateBasic.list_zones: + - + runner: + type: "constant" + times: 4 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 2 + sla: + failure_rate: + max: 0 diff --git a/rally/plugins/openstack/scenarios/designate/basic.py b/rally/plugins/openstack/scenarios/designate/basic.py index e0575318..77c9afc8 100644 --- a/rally/plugins/openstack/scenarios/designate/basic.py +++ b/rally/plugins/openstack/scenarios/designate/basic.py @@ -26,7 +26,7 @@ class DesignateBasic(utils.DesignateScenario): @validation.required_services(consts.Service.DESIGNATE) @validation.required_openstack(users=True) - @scenario.configure(context={"cleanup": ["designate"]}) + @scenario.configure(context={"cleanup": ["designate_v1"]}) def create_and_list_domains(self): """Create a domain and list all domains. @@ -43,7 +43,7 @@ class DesignateBasic(utils.DesignateScenario): @validation.required_services(consts.Service.DESIGNATE) @validation.required_openstack(users=True) - @scenario.configure(context={"cleanup": ["designate"]}) + @scenario.configure(context={"cleanup": ["designate_v1"]}) def list_domains(self): """List Designate domains. @@ -59,7 +59,7 @@ class DesignateBasic(utils.DesignateScenario): @validation.required_services(consts.Service.DESIGNATE) @validation.required_openstack(users=True) - @scenario.configure(context={"cleanup": ["designate"]}) + @scenario.configure(context={"cleanup": ["designate_v1"]}) def create_and_delete_domain(self): """Create and then delete a domain. @@ -71,7 +71,7 @@ class DesignateBasic(utils.DesignateScenario): @validation.required_services(consts.Service.DESIGNATE) @validation.required_openstack(users=True) - @scenario.configure(context={"cleanup": ["designate"]}) + @scenario.configure(context={"cleanup": ["designate_v1"]}) def create_and_delete_records(self, records_per_domain=5): """Create and then delete records. @@ -98,7 +98,7 @@ class DesignateBasic(utils.DesignateScenario): @validation.required_services(consts.Service.DESIGNATE) @validation.required_openstack(users=True) - @scenario.configure(context={"cleanup": ["designate"]}) + @scenario.configure(context={"cleanup": ["designate_v1"]}) def list_records(self, domain_id): """List Designate records. @@ -116,7 +116,7 @@ class DesignateBasic(utils.DesignateScenario): @validation.required_services(consts.Service.DESIGNATE) @validation.required_openstack(users=True) - @scenario.configure(context={"cleanup": ["designate"]}) + @scenario.configure(context={"cleanup": ["designate_v1"]}) def create_and_list_records(self, records_per_domain=5): """Create and then list records. @@ -139,7 +139,7 @@ class DesignateBasic(utils.DesignateScenario): @validation.required_services(consts.Service.DESIGNATE) @validation.required_openstack(admin=True) - @scenario.configure(context={"cleanup": ["designate"]}) + @scenario.configure(context={"cleanup": ["designate_v1"]}) def create_and_list_servers(self): """Create a Designate server and list all servers. @@ -154,7 +154,7 @@ class DesignateBasic(utils.DesignateScenario): @validation.required_services(consts.Service.DESIGNATE) @validation.required_openstack(admin=True) - @scenario.configure(context={"cleanup": ["designate"]}) + @scenario.configure(context={"cleanup": ["designate_v1"]}) def create_and_delete_server(self): """Create and then delete a server. @@ -166,7 +166,7 @@ class DesignateBasic(utils.DesignateScenario): @validation.required_services(consts.Service.DESIGNATE) @validation.required_openstack(admin=True) - @scenario.configure(context={"cleanup": ["designate"]}) + @scenario.configure(context={"cleanup": ["designate_v1"]}) def list_servers(self): """List Designate servers. @@ -174,3 +174,59 @@ class DesignateBasic(utils.DesignateScenario): all the servers. """ self._list_servers() + + # NOTE: API V2 + @validation.required_services(consts.Service.DESIGNATE) + @validation.required_openstack(users=True) + @scenario.configure(context={"cleanup": ["designate_v2"]}) + def create_and_list_zones(self): + """Create a zone and list all zones. + + Measure the "openstack zone list" command performance. + + If you have only 1 user in your context, you will + add 1 zone on every iteration. So you will have more + and more zone and will be able to measure the + performance of the "openstack zone list" command depending on + the number of zones owned by users. + """ + self._create_zone() + self._list_zones() + + @validation.required_services(consts.Service.DESIGNATE) + @validation.required_openstack(users=True) + @scenario.configure(context={"cleanup": ["designate_v2"]}) + def list_zones(self): + """List Designate zones. + + This simple scenario tests the openstack zone list command by listing + all the zones. + """ + + self._list_zones() + + @validation.required_services(consts.Service.DESIGNATE) + @validation.required_openstack(users=True) + @scenario.configure(context={"cleanup": ["designate_v2"]}) + def create_and_delete_zone(self): + """Create and then delete a zone. + + Measure the performance of creating and deleting zones + with different level of load. + """ + zone = self._create_zone() + self._delete_zone(zone["id"]) + + @validation.required_services(consts.Service.DESIGNATE) + @validation.required_openstack(users=True) + @scenario.configure(context={"cleanup": ["designate_v2"]}) + def list_recordsets(self, zone_id): + """List Designate recordsets. + + This simple scenario tests the openstack recordset list command by + listing all the recordsets in a zone. + + :param zone_id: Zone ID + """ + + self._list_recordsets(zone_id) diff --git a/rally/plugins/openstack/scenarios/designate/utils.py b/rally/plugins/openstack/scenarios/designate/utils.py index 62be960c..b37ace3b 100644 --- a/rally/plugins/openstack/scenarios/designate/utils.py +++ b/rally/plugins/openstack/scenarios/designate/utils.py @@ -115,3 +115,64 @@ class DesignateScenario(scenario.OpenStackScenario): :param server_id: unicode server ID """ self.admin_clients("designate").servers.delete(server_id) + + # NOTE: API V2 + @atomic.action_timer("designate.create_zone") + def _create_zone(self, name=None, type_=None, email=None, description=None, + ttl=None): + """Create zone. + + :param name: Zone name + :param type_: Zone type, PRIMARY or SECONDARY + :param email: Zone owner email + :param description: Zone description + :param ttl: Zone ttl - Time to live in seconds + :returns: designate zone dict + """ + type_ = type_ or "PRIMARY" + + if type_ == "PRIMARY": + email = email or "root@random.name" + # Name is only useful to be random for PRIMARY + name = name or "%s.name." % self.generate_random_name() + + return self.clients("designate", version="2").zones.create( + name=name, + type_=type_, + email=email, + description=description, + ttl=ttl + ) + + @atomic.action_timer("designate.list_zones") + def _list_zones(self, criterion=None, marker=None, limit=None): + """Return user zone list. + + :param criterion: API Criterion to filter by + :param marker: UUID marker of the item to start the page from + :param limit: How many items to return in the page. + : returns: list of designate zones + """ + return self.clients("designate", version="2").zones.list() + + @atomic.action_timer("designate.delete_zone") + def _delete_zone(self, zone_id): + """Delete designate zone. + + :param zone_id: Zone ID + """ + self.clients("designate", version="2").zones.delete(zone_id) + + @atomic.action_timer("designate.list_recordsets") + def _list_recordsets(self, zone_id, criterion=None, marker=None, + limit=None): + """List zone recordsets. + + :param zone_id: Zone ID + :param criterion: API Criterion to filter by + :param marker: UUID marker of the item to start the page from + :param limit: How many items to return in the page. + :returns: zone recordsets list + """ + return self.clients("designate", version="2").recordsets.list( + zone_id, criterion=criterion, marker=marker, limit=limit) diff --git a/samples/tasks/scenarios/designate/create-and-delete-zone.json b/samples/tasks/scenarios/designate/create-and-delete-zone.json new file mode 100644 index 00000000..998d681e --- /dev/null +++ b/samples/tasks/scenarios/designate/create-and-delete-zone.json @@ -0,0 +1,25 @@ +{ + "DesignateBasic.create_and_delete_zone": [ + { + "runner": { + "type": "constant", + "times": 10, + "concurrency": 10 + }, + "context": { + "quotas": { + "designate": { + "domains": 100, + "domain_recordsets": 500, + "domain_records": 2000, + "recordset_records": 2000 + } + }, + "users": { + "tenants": 2, + "users_per_tenant": 2 + } + } + } + ] +} diff --git a/samples/tasks/scenarios/designate/create-and-delete-zone.yaml b/samples/tasks/scenarios/designate/create-and-delete-zone.yaml new file mode 100644 index 00000000..286a64a9 --- /dev/null +++ b/samples/tasks/scenarios/designate/create-and-delete-zone.yaml @@ -0,0 +1,17 @@ +--- + DesignateBasic.create_and_delete_zone: + - + runner: + type: "constant" + times: 10 + concurrency: 10 + context: + quotas: + designate: + domains: 100 + domain_recordsets: 500 + domain_records: 2000 + recordset_records: 2000 + users: + tenants: 2 + users_per_tenant: 2 diff --git a/samples/tasks/scenarios/designate/create-and-list-zones.json b/samples/tasks/scenarios/designate/create-and-list-zones.json new file mode 100644 index 00000000..4f366a42 --- /dev/null +++ b/samples/tasks/scenarios/designate/create-and-list-zones.json @@ -0,0 +1,25 @@ +{ + "DesignateBasic.create_and_list_zones": [ + { + "runner": { + "type": "constant", + "times": 10, + "concurrency": 10 + }, + "context": { + "quotas": { + "designate": { + "domains": 100, + "domain_recordsets": 500, + "domain_records": 2000, + "recordset_records": 2000 + } + }, + "users": { + "tenants": 2, + "users_per_tenant": 2 + } + } + } + ] +} diff --git a/samples/tasks/scenarios/designate/create-and-list-zones.yaml b/samples/tasks/scenarios/designate/create-and-list-zones.yaml new file mode 100644 index 00000000..bda61e6f --- /dev/null +++ b/samples/tasks/scenarios/designate/create-and-list-zones.yaml @@ -0,0 +1,17 @@ +--- + DesignateBasic.create_and_list_zones: + - + runner: + type: "constant" + times: 10 + concurrency: 10 + context: + quotas: + designate: + domains: 100 + domain_recordsets: 500 + domain_records: 2000 + recordset_records: 2000 + users: + tenants: 2 + users_per_tenant: 2 diff --git a/samples/tasks/scenarios/designate/list-recordsets.json b/samples/tasks/scenarios/designate/list-recordsets.json new file mode 100644 index 00000000..0c9a897b --- /dev/null +++ b/samples/tasks/scenarios/designate/list-recordsets.json @@ -0,0 +1,20 @@ +{ + "DesignateBasic.list_recordsets": [ + { + "args": { + "zone_id": "" + }, + "runner": { + "type": "constant", + "times": 3, + "concurrency": 2 + }, + "context": { + "users": { + "tenants": 2, + "users_per_tenant": 2 + } + } + } + ] +} diff --git a/samples/tasks/scenarios/designate/list-recordsets.yaml b/samples/tasks/scenarios/designate/list-recordsets.yaml new file mode 100644 index 00000000..64a5e3b6 --- /dev/null +++ b/samples/tasks/scenarios/designate/list-recordsets.yaml @@ -0,0 +1,13 @@ +--- + DesignateBasic.list_recordsets: + - + args: + zone_id: + runner: + type: "constant" + times: 3 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 2 diff --git a/samples/tasks/scenarios/designate/list-zones.json b/samples/tasks/scenarios/designate/list-zones.json new file mode 100644 index 00000000..f7cdb03d --- /dev/null +++ b/samples/tasks/scenarios/designate/list-zones.json @@ -0,0 +1,17 @@ +{ + "DesignateBasic.list_zones": [ + { + "runner": { + "type": "constant", + "times": 3, + "concurrency": 2 + }, + "context": { + "users": { + "tenants": 2, + "users_per_tenant": 2 + } + } + } + ] +} diff --git a/samples/tasks/scenarios/designate/list-zones.yaml b/samples/tasks/scenarios/designate/list-zones.yaml new file mode 100644 index 00000000..400d324a --- /dev/null +++ b/samples/tasks/scenarios/designate/list-zones.yaml @@ -0,0 +1,11 @@ +--- + DesignateBasic.list_zones: + - + runner: + type: "constant" + times: 3 + concurrency: 2 + context: + users: + tenants: 2 + users_per_tenant: 2 diff --git a/tests/unit/plugins/openstack/context/designate/__init__.py b/tests/unit/plugins/openstack/context/designate/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/plugins/openstack/scenarios/designate/test_basic.py b/tests/unit/plugins/openstack/scenarios/designate/test_basic.py index e3528709..7030b0ce 100644 --- a/tests/unit/plugins/openstack/scenarios/designate/test_basic.py +++ b/tests/unit/plugins/openstack/scenarios/designate/test_basic.py @@ -155,3 +155,47 @@ class DesignateBasicTestCase(test.ScenarioTestCase): # Default options scenario.list_servers() mock_designate_basic__list_servers.assert_called_once_with() + + # NOTE: API V2 + @mock.patch(DESIGNATE_BASIC + "._list_zones") + @mock.patch(DESIGNATE_BASIC + "._create_zone") + def test_create_and_list_zones(self, mock_designate_basic__create_zone, + mock_designate_basic__list_zones): + scenario = basic.DesignateBasic(self.context) + + # Default options + scenario.create_and_list_zones() + mock_designate_basic__create_zone.assert_called_once_with() + mock_designate_basic__list_zones.assert_called_once_with() + + @mock.patch(DESIGNATE_BASIC + "._delete_zone") + @mock.patch(DESIGNATE_BASIC + "._create_zone") + def test_create_and_delete_zone( + self, mock_designate_basic__create_zone, + mock_designate_basic__delete_zone): + + scenario = basic.DesignateBasic(self.context) + + mock_designate_basic__create_zone.return_value = {"id": "123"} + + # Default options + scenario.create_and_delete_zone() + + mock_designate_basic__create_zone.assert_called_once_with() + mock_designate_basic__delete_zone.assert_called_once_with("123") + + @mock.patch(DESIGNATE_BASIC + "._list_zones") + def test_list_zones(self, mock_designate_basic__list_zones): + scenario = basic.DesignateBasic(self.context) + + # Default options + scenario.list_zones() + mock_designate_basic__list_zones.assert_called_once_with() + + @mock.patch(DESIGNATE_BASIC + "._list_recordsets") + def test_list_recordsets(self, mock_designate_basic__list_recordsets): + scenario = basic.DesignateBasic(self.context) + + # Default options + scenario.list_recordsets("123") + mock_designate_basic__list_recordsets.assert_called_once_with("123") diff --git a/tests/unit/plugins/openstack/scenarios/designate/test_utils.py b/tests/unit/plugins/openstack/scenarios/designate/test_utils.py index 2154e1ba..4cfe7abe 100644 --- a/tests/unit/plugins/openstack/scenarios/designate/test_utils.py +++ b/tests/unit/plugins/openstack/scenarios/designate/test_utils.py @@ -29,8 +29,11 @@ class DesignateScenarioTestCase(test.ScenarioTestCase): def setUp(self): super(DesignateScenarioTestCase, self).setUp() self.domain = mock.Mock() + self.zone = mock.Mock() self.server = mock.Mock() + self.client = self.clients("designate", version="2") + @ddt.data( {}, {"email": "root@zone.name"}) @@ -147,3 +150,63 @@ class DesignateScenarioTestCase(test.ScenarioTestCase): "foo_id") self._test_atomic_action_timer(scenario.atomic_actions(), "designate.delete_server") + + # NOTE: API V2 + @ddt.data( + {}, + {"email": "root@zone.name"}, + {"name": "example.name."}, + { + "email": "root@zone.name", + "name": "example.name." + }) + def test_create_zone(self, zone_data): + scenario = utils.DesignateScenario() + + random_name = "foo" + + scenario = utils.DesignateScenario(context=self.context) + scenario.generate_random_name = mock.Mock(return_value=random_name) + self.client.zones.create.return_value = self.zone + + expected = { + "email": "root@random.name", + "name": "%s.name." % random_name, + "type_": "PRIMARY" + } + expected.update(zone_data) + + # Check that the defaults / randoms are used if nothing is specified + zone = scenario._create_zone(**zone_data) + self.client.zones.create.assert_called_once_with( + description=None, + ttl=None, + **expected) + self.assertEqual(self.zone, zone) + self._test_atomic_action_timer(scenario.atomic_actions(), + "designate.create_zone") + + def test_list_zones(self): + scenario = utils.DesignateScenario(context=self.context) + return_zones_list = scenario._list_zones() + self.assertEqual(self.client.zones.list.return_value, + return_zones_list) + self._test_atomic_action_timer(scenario.atomic_actions(), + "designate.list_zones") + + def test_delete_zone(self): + scenario = utils.DesignateScenario(context=self.context) + + zone = scenario._create_zone() + scenario._delete_zone(zone["id"]) + self._test_atomic_action_timer(scenario.atomic_actions(), + "designate.delete_zone") + + def test_list_recordsets(self): + scenario = utils.DesignateScenario(context=self.context) + return_recordsets_list = scenario._list_recordsets("123") + self.assertEqual( + self.client.recordsets.list.return_value, + return_recordsets_list) + self._test_atomic_action_timer(scenario.atomic_actions(), + "designate.list_recordsets")