Add designate support with domain scenarios

*) Add designate client
*) Add designate cleanup 
*) Add domain benchmarks 

Change-Id: I4d791411487788ba157f60c3f99aa48bf237b10b
This commit is contained in:
Endre Karlson 2014-08-22 23:52:45 +02:00 committed by Boris Pavlovic
parent d091b3bfc8
commit e8d8099d4d
17 changed files with 367 additions and 2 deletions

View File

@ -0,0 +1,17 @@
{
"DesignateBasic.create_and_delete_domain": [
{
"runner": {
"type": "constant",
"times": 3,
"concurrency": 2
},
"context": {
"users": {
"tenants": 2,
"users_per_tenant": 2
}
}
}
]
}

View File

@ -0,0 +1,11 @@
---
DesignateBasic.create_and_delete_domain:
-
runner:
type: "constant"
times: 3
concurrency: 2
context:
users:
tenants: 2
users_per_tenant: 2

View File

@ -0,0 +1,17 @@
{
"DesignateBasic.create_and_list_domains": [
{
"runner": {
"type": "constant",
"times": 3,
"concurrency": 2
},
"context": {
"users": {
"tenants": 2,
"users_per_tenant": 2
}
}
}
]
}

View File

@ -0,0 +1,11 @@
---
DesignateBasic.create_and_list_domains:
-
runner:
type: "constant"
times: 3
concurrency: 2
context:
users:
tenants: 2
users_per_tenant: 2

View File

@ -0,0 +1,17 @@
{
"DesignateBasic.list_domains": [
{
"runner": {
"type": "constant",
"times": 3,
"concurrency": 2
},
"context": {
"users": {
"tenants": 2,
"users_per_tenant": 2
}
}
}
]
}

View File

@ -0,0 +1,11 @@
---
DesignateBasic.list_domains:
-
runner:
type: "constant"
times: 3
concurrency: 2
context:
users:
tenants: 2
users_per_tenant: 2

View File

@ -41,7 +41,7 @@ class UserCleanup(base.Context):
"items": {
"type": "string",
"enum": ["nova", "glance", "cinder",
"neutron", "ceilometer", "heat", "sahara"]
"neutron", "ceilometer", "heat", "sahara", "designate"]
},
"uniqueItems": True
}
@ -64,7 +64,9 @@ class UserCleanup(base.Context):
"ceilometer": (utils.delete_ceilometer_resources,
clients.ceilometer, tenant_id),
"heat": (utils.delete_heat_resources, clients.heat),
"sahara": (utils.delete_sahara_resources, clients.sahara)
"sahara": (utils.delete_sahara_resources, clients.sahara),
"designate": (utils.delete_designate_resources,
clients.designate),
}
for service_name in self.config:

View File

@ -154,6 +154,11 @@ def delete_neutron_resources(neutron, project_uuid):
neutron.delete_network(network["id"])
def delete_designate_resources(designate):
for domain in designate.domains.list():
designate.domains.delete(domain.id)
def delete_ceilometer_resources(ceilometer, project_uuid):
delete_alarms(ceilometer, project_uuid)

View File

@ -0,0 +1,66 @@
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# Author: Endre Karlson <endre.karlson@hp.com>
#
# 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.benchmark.scenarios import base
from rally.benchmark.scenarios.designate import utils
from rally.benchmark import validation
from rally import consts
class DesignateBasic(utils.DesignateScenario):
@base.scenario(context={"cleanup": ["designate"]})
@validation.required_services(consts.Service.DESIGNATE)
def create_and_list_domains(self):
"""Tests creating a domain and listing domains.
This scenario is a very useful tool to measure
the "designate domain-list" command performance.
If you have only 1 user in your context, you will
add 1 domain on every iteration. So you will have more
and more domain and will be able to measure the
performance of the "designate domain-list" command depending on
the number of domains owned by users.
"""
self._create_domain()
self._list_domains()
@base.scenario(context={"cleanup": ["designate"]})
@validation.required_services(consts.Service.DESIGNATE)
def list_domains(self):
"""Test the designate domain-list command.
This simple scenario tests the designate domain-list command by listing
all the domains.
Suppose if we have 2 users in context and each has 2 domains
uploaded for them we will be able to test the performance of
designate domain-list command in this case.
"""
self._list_domains()
@base.scenario(context={"cleanup": ["designate"]})
@validation.required_services(consts.Service.DESIGNATE)
def create_and_delete_domain(self):
"""Test adds and then deletes domain.
This is very useful to measure perfromance of creating and deleting
domains with different level of load.
"""
domain = self._create_domain()
self._delete_domain(domain['id'])

View File

@ -0,0 +1,49 @@
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# Author: Endre Karlson <endre.karlson@hp.com>
#
# 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.benchmark.scenarios import base
class DesignateScenario(base.Scenario):
"""This class should contain base operations for benchmarking designate."""
RESOURCE_NAME_PREFIX = "rally_"
@base.atomic_action_timer('designate.create_domain')
def _create_domain(self, domain=None):
"""Create domain.
:param domain: dict, POST /v1/domains request options
:returns: designate domain dict
"""
domain = domain or {}
domain.setdefault('email', 'root@random.name')
domain.setdefault('name', '%s.name.' % self._generate_random_name())
return self.clients("designate").domains.create(domain)
@base.atomic_action_timer('designate.list_domains')
def _list_domains(self):
"""Return user domain list."""
return self.clients("designate").domains.list()
@base.atomic_action_timer('designate.delete_domain')
def _delete_domain(self, domain_id):
"""Delete designate zone.
:param domain: Domain object
"""
self.clients("designate").domains.delete(domain_id)

View File

@ -28,6 +28,7 @@ TEMPEST_TEST_SETS = ("full",
"smoke",
"baremetal",
"compute",
"dns",
"data_processing",
"identity",
"image",
@ -87,6 +88,7 @@ class _Service(utils.ImmutableMixin, utils.EnumMixin):
HEAT = "heat"
KEYSTONE = "keystone"
NEUTRON = "neutron"
DESIGNATE = "designate"
CEILOMETER = "ceilometer"
S3 = "s3"
TROVE = "trove"
@ -106,6 +108,7 @@ class _ServiceType(utils.ImmutableMixin, utils.EnumMixin):
COMPUTE = "compute"
COMPUTEV3 = "computev3"
NETWORK = "network"
DNS = "dns"
METERING = "metering"
S3 = "s3"
DATABASE = "database"
@ -123,6 +126,7 @@ class _ServiceType(utils.ImmutableMixin, utils.EnumMixin):
self.ORCHESTRATION: _Service.HEAT,
self.IDENTITY: _Service.KEYSTONE,
self.NETWORK: _Service.NEUTRON,
self.DNS: _Service.DESIGNATE,
self.METERING: _Service.CEILOMETER,
self.S3: _Service.S3,
self.DATABASE: _Service.TROVE,

View File

@ -17,6 +17,7 @@ import urlparse
from ceilometerclient import client as ceilometer
from cinderclient import client as cinder
from designateclient import v1 as designate
import glanceclient as glance
from heatclient import client as heat
from ironicclient import client as ironic
@ -250,6 +251,19 @@ class Clients(object):
return client
@cached
def designate(self):
"""Return designate client."""
kc = self.keystone()
dns_api_url = kc.service_catalog.url_for(
service_type='dns', endpoint_type='public',
region_name=self.endpoint.region_name)
client = designate.Client(
endpoint=dns_api_url,
token=kc.auth_token,
insecure=CONF.https_insecure)
return client
@cached
def services(self):
"""Return available services names and types.

View File

@ -11,6 +11,7 @@ pbr>=0.6,!=0.7,<1.0
pecan>=0.5.0
PrettyTable>=0.7,<0.8
PyYAML>=3.1.0
python-designateclient>=1.0.0
python-glanceclient>=0.13.1
python-keystoneclient>=0.10.0
python-novaclient>=2.17.0

View File

@ -0,0 +1,56 @@
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# Author: Endre Karlson <endre.karlson@hp.com>
#
# 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.benchmark.scenarios.designate import basic
from tests import test
DESIGNATE_BASIC = "rally.benchmark.scenarios.designate.basic.DesignateBasic"
class DesignateBasicTestCase(test.TestCase):
@mock.patch(DESIGNATE_BASIC + "._list_domains")
@mock.patch(DESIGNATE_BASIC + "._create_domain")
def test_create_and_list_networks(self, mock_create, mock_list):
scenario = basic.DesignateBasic()
# Default options
scenario.create_and_list_domains()
mock_create.assert_called_once_with()
mock_list.assert_called_once_with()
@mock.patch(DESIGNATE_BASIC + "._delete_domain")
@mock.patch(DESIGNATE_BASIC + "._create_domain")
def test_create_and_delete_domain(self, mock_create, mock_delete):
scenario = basic.DesignateBasic()
mock_create.return_value = {"id": "123"}
# Default options
scenario.create_and_delete_domain()
mock_create.assert_called_once_with()
mock_delete.assert_called_once_with("123")
@mock.patch(DESIGNATE_BASIC + "._list_domains")
def test_list_domains(self, mock_list):
scenario = basic.DesignateBasic()
# Default options
scenario.list_domains()
mock_list.assert_called_once_with()

View File

@ -0,0 +1,84 @@
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# Author: Endre Karlson <endre.karlson@hp.com>
#
# 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.benchmark.scenarios.designate import utils
from tests.benchmark.scenarios import test_base
from tests import test
DESIGNATE_UTILS = "rally.benchmark.scenarios.designate.utils."
class DesignateScenarioTestCase(test.TestCase):
def setUp(self):
super(DesignateScenarioTestCase, self).setUp()
self.domain = mock.Mock()
def _test_atomic_action_timer(self, atomic_actions_time, name):
action_duration = test_base.get_atomic_action_timer_value_by_name(
atomic_actions_time, name)
self.assertIsNotNone(action_duration)
self.assertIsInstance(action_duration, float)
@mock.patch(DESIGNATE_UTILS + 'DesignateScenario._generate_random_name')
@mock.patch(DESIGNATE_UTILS + 'DesignateScenario.clients')
def test_create_domain(self, mock_clients, mock_random_name):
scenario = utils.DesignateScenario()
random_name = "foo"
explicit_name = "bar.io."
email = "root@zone.name"
mock_random_name.return_value = random_name
mock_clients("designate").domains.create.return_value = self.domain
# Check that the defaults / randoms are used if nothing is specified
domain = scenario._create_domain()
mock_clients("designate").domains.create.assert_called_once_with(
{"email": "root@random.name", "name": '%s.name.' % random_name})
self.assertEqual(self.domain, domain)
self._test_atomic_action_timer(scenario.atomic_actions(),
'designate.create_domain')
mock_clients("designate").domains.create.reset_mock()
# Check that when specifying zone defaults are not used...
data = {"email": email, "name": explicit_name}
domain = scenario._create_domain(data)
mock_clients("designate").domains.create.assert_called_once_with(data)
self.assertEqual(self.domain, domain)
@mock.patch(DESIGNATE_UTILS + 'DesignateScenario.clients')
def test_list_domains(self, mock_clients):
scenario = utils.DesignateScenario()
domains_list = []
mock_clients("designate").domains.list.return_value = domains_list
return_domains_list = scenario._list_domains()
self.assertEqual(domains_list, return_domains_list)
self._test_atomic_action_timer(scenario.atomic_actions(),
'designate.list_domains')
@mock.patch(DESIGNATE_UTILS + 'DesignateScenario.clients')
def test_delete_domain(self, mock_clients):
scenario = utils.DesignateScenario()
domain = scenario._create_domain()
scenario._delete_domain(domain['id'])
self._test_atomic_action_timer(scenario.atomic_actions(),
'designate.delete_domain')