diff --git a/ec2api/tests/functional/base.py b/ec2api/tests/functional/base.py index cbd22ea7..69064646 100644 --- a/ec2api/tests/functional/base.py +++ b/ec2api/tests/functional/base.py @@ -235,7 +235,9 @@ class EC2TestCase(base.BaseTestCase): @safe_setup def setUpClass(cls): super(EC2TestCase, cls).setUpClass() - cls.client = botocoreclient.APIClientEC2() + cls.client = botocoreclient.APIClientEC2( + CONF.aws.ec2_url, CONF.aws.aws_region, + CONF.aws.aws_access, CONF.aws.aws_secret) TesterStateHolder().ec2_client = cls.client @classmethod diff --git a/ec2api/tests/functional/botocoreclient.py b/ec2api/tests/functional/botocoreclient.py index 77452134..0ddb992f 100644 --- a/ec2api/tests/functional/botocoreclient.py +++ b/ec2api/tests/functional/botocoreclient.py @@ -18,23 +18,18 @@ import types from botocore import session from oslo_log import log as logging -from ec2api.tests.functional import config as cfg - -CONF = cfg.CONF LOG = logging.getLogger(__name__) class BotocoreClientBase(object): - def __init__(self, *args, **kwargs): - self.region = CONF.aws.aws_region + def __init__(self, region, access, secret): + self.region = region self.connection_data = { 'config_file': (None, 'AWS_CONFIG_FILE', None), 'region': ('region', 'BOTO_DEFAULT_REGION', self.region), } - access = CONF.aws.aws_access - secret = CONF.aws.aws_secret if not access or not secret: raise Exception('Auth params did not provided') @@ -57,9 +52,10 @@ class BotocoreClientBase(object): class APIClientEC2(BotocoreClientBase): - def __init__(self, *args, **kwargs): - super(APIClientEC2, self).__init__(*args, **kwargs) + def __init__(self, url, region, access, secret, *args, **kwargs): + super(APIClientEC2, self).__init__(region, access, secret, + *args, **kwargs) self.service = self.session.get_service('ec2') self.endpoint = self.service.get_endpoint( region_name=self.region, - endpoint_url=CONF.aws.ec2_url) + endpoint_url=url) diff --git a/rally-scenarios/README.rst b/rally-scenarios/README.rst new file mode 100644 index 00000000..2c4a4848 --- /dev/null +++ b/rally-scenarios/README.rst @@ -0,0 +1,5 @@ +This directory contains rally benchmark scenarios to be run by OpenStack CI. + + +* more about rally: https://wiki.openstack.org/wiki/Rally +* how to add rally-gates: https://wiki.openstack.org/wiki/Rally/RallyGates diff --git a/rally-scenarios/ec2-api-fakevirt.yaml b/rally-scenarios/ec2-api-fakevirt.yaml new file mode 100644 index 00000000..4aee2427 --- /dev/null +++ b/rally-scenarios/ec2-api-fakevirt.yaml @@ -0,0 +1,30 @@ +--- + EC2APIPlugin.describe_instances: + - + runner: + type: "constant" + times: 20 + concurrency: 1 + context: + users: + tenants: 1 + users_per_tenant: 1 + servers: + flavor: + name: "m1.nano" + image: + name: "^cirros.*uec$" + servers_per_tenant: 500 + prepare_ec2_client: + + EC2APIPlugin.describe_regions: + - + runner: + type: "constant" + times: 10 + concurrency: 1 + context: + users: + tenants: 1 + users_per_tenant: 1 + prepare_ec2_client: diff --git a/rally-scenarios/extra/README.rst b/rally-scenarios/extra/README.rst new file mode 100644 index 00000000..836f35a0 --- /dev/null +++ b/rally-scenarios/extra/README.rst @@ -0,0 +1,5 @@ +Extra files +=========== + +All files from this directory will be copy pasted to gates, so you are able to +use absolute path in rally tasks. Files will be in ~/.rally/extra/* diff --git a/rally-scenarios/plugins/README.rst b/rally-scenarios/plugins/README.rst new file mode 100644 index 00000000..33bec0d2 --- /dev/null +++ b/rally-scenarios/plugins/README.rst @@ -0,0 +1,9 @@ +Rally plugins +============= + +All *.py modules from this directory will be auto-loaded by Rally and all +plugins will be discoverable. There is no need of any extra configuration +and there is no difference between writing them here and in rally code base. + +Note that it is better to push all interesting and useful benchmarks to Rally +code base, this simplifies administration for Operators. diff --git a/rally-scenarios/plugins/context_plugin.py b/rally-scenarios/plugins/context_plugin.py new file mode 100644 index 00000000..7012744d --- /dev/null +++ b/rally-scenarios/plugins/context_plugin.py @@ -0,0 +1,55 @@ +# Copyright 2013: Mirantis Inc. +# 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.benchmark.context import base +from rally.common import log as logging +from rally import osclients + +LOG = logging.getLogger(__name__) + + +@base.context(name="prepare_ec2_client", order=1000) +class PrepareEC2ClientContext(base.Context): + + def setup(self): + """This method is called before the task start.""" + try: + user = self.context['users'][0] + osclient = osclients.Clients(user['endpoint']) + keystone = osclient.keystone() + creds = keystone.ec2.list(user['id']) + if not creds: + creds = keystone.ec2.create(user['id'], user['tenant_id']) + else: + creds = creds[0] + url = keystone.service_catalog.url_for(service_type='ec2') + url_parts = url.rpartition(':') + nova_url = url_parts[0] + ':8773/' + url_parts[2].partition('/')[2] + self.context['users'][0]['ec2args'] = { + 'region': 'RegionOne', + 'url': url, + 'nova_url': nova_url, + 'access': creds.access, + 'secret': creds.secret + } + except Exception as e: + msg = "Can't prepare ec2 client: %s" % e.message + if logging.is_debug(): + LOG.exception(msg) + else: + LOG.warning(msg) + + def cleanup(self): + pass diff --git a/rally-scenarios/plugins/ec2api_plugin.py b/rally-scenarios/plugins/ec2api_plugin.py new file mode 100644 index 00000000..7d877486 --- /dev/null +++ b/rally-scenarios/plugins/ec2api_plugin.py @@ -0,0 +1,59 @@ +# 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 functools + +from rally.benchmark.scenarios import base +from rally.common import log as logging + +from ec2api.tests.functional import botocoreclient + +LOG = logging.getLogger(__name__) + + +class EC2APIPlugin(base.Scenario): + """Plugin which lists instances.""" + + def _get_client(self, is_nova): + args = self.context['user']['ec2args'] + url = args['nova_url'] if is_nova else args['url'] + client = botocoreclient.APIClientEC2( + url, args['region'], args['access'], args['secret']) + return client + + def _run(self, base_name, func): + client = self._get_client(False) + with base.AtomicAction(self, base_name + '_ec2api'): + func(self, client) + client = self._get_client(True) + with base.AtomicAction(self, base_name + '_nova'): + func(self, client) + + def _both_api_runner(): + def wrap(func): + @functools.wraps(func) + def runner(self, *args, **kwargs): + self._run(func.__name__, func) + return runner + return wrap + + @base.scenario() + @_both_api_runner() + def describe_instances(self, client): + resp, data = client.DescribeInstances() + assert 200 == resp.status_code + + @base.scenario() + @_both_api_runner() + def describe_regions(self, client): + resp, data = client.DescribeRegions() + assert 200 == resp.status_code