From 9611927787ba477b5849f3fbe180b6475f249339 Mon Sep 17 00:00:00 2001 From: Oleh Anufriiev Date: Mon, 27 Oct 2014 17:11:54 +0200 Subject: [PATCH] add ability to refer deployment by uuid or name also deployment name turned unique in db Change-Id: I513b5259e0cfa66780b4ce00cf78dc57aeeb57db --- doc/source/usage.rst | 4 +- rally/cmd/commands/deployment.py | 69 ++++++++++--------- rally/cmd/commands/show.py | 58 ++++++++-------- rally/cmd/commands/task.py | 26 +++---- rally/cmd/commands/use.py | 42 +++-------- rally/cmd/commands/verify.py | 13 ++-- rally/cmd/envutils.py | 4 +- rally/cmd/manage.py | 12 ++-- rally/db/api.py | 6 +- rally/db/sqlalchemy/api.py | 37 ++++++---- rally/db/sqlalchemy/models.py | 2 +- .../serverprovider/providers/openstack.py | 8 +-- rally/exceptions.py | 6 +- rally/objects/deploy.py | 4 +- rally/orchestrator/api.py | 64 ++++++++++------- .../verification/verifiers/tempest/config.py | 8 +-- .../verification/verifiers/tempest/tempest.py | 8 +-- tests/ci/rally-gate.sh | 2 +- tests/unit/cmd/commands/test_deployment.py | 56 +++++++-------- tests/unit/cmd/commands/test_show.py | 22 +++--- tests/unit/cmd/commands/test_task.py | 12 ++-- tests/unit/cmd/commands/test_use.py | 44 +++++++----- tests/unit/cmd/commands/test_verify.py | 16 ++--- tests/unit/cmd/test_envutils.py | 6 +- tests/unit/cmd/test_manage.py | 10 +-- tests/unit/orchestrator/test_api.py | 60 +++++++++++----- .../verification/verifiers/test_config.py | 6 +- .../verification/verifiers/test_tempest.py | 4 +- tools/rally.bash_completion | 30 ++++---- 29 files changed, 341 insertions(+), 298 deletions(-) diff --git a/doc/source/usage.rst b/doc/source/usage.rst index 50040ccd6f..a28957e13a 100644 --- a/doc/source/usage.rst +++ b/doc/source/usage.rst @@ -59,8 +59,8 @@ Note the last line in the output. It says that the just created deployment is no .. code-block:: none - $ rally use deployment --deploy-id= - Using deployment : + $ rally use deployment + Using deployment : Finally, the **deployment check** command enables you to verify that your current deployment is healthy and ready to be benchmarked: diff --git a/rally/cmd/commands/deployment.py b/rally/cmd/commands/deployment.py index b9de7c1f9f..57ccf550a4 100644 --- a/rally/cmd/commands/deployment.py +++ b/rally/cmd/commands/deployment.py @@ -117,50 +117,53 @@ class DeploymentCommands(object): except jsonschema.ValidationError: print(_("Config schema validation error: %s.") % sys.exc_info()[1]) return(1) + except exceptions.DeploymentNameExists: + print(_("Error: %s") % sys.exc_info()[1]) + return(1) self.list(deployment_list=[deployment]) if do_use: use.UseCommands().deployment(deployment['uuid']) - @cliutils.args('--uuid', dest='deploy_id', type=str, required=False, - help='UUID of a deployment.') - @envutils.with_default_deploy_id - def recreate(self, deploy_id=None): + @cliutils.args('--deployment', dest='deployment', type=str, + required=False, help='UUID or name of a deployment.') + @envutils.with_default_deployment + def recreate(self, deployment=None): """Destroy and create an existing deployment. Unlike 'deployment destroy' command deployment database record will not be deleted, so deployment's UUID stay same. - :param deploy_id: a UUID of the deployment + :param deployment: a UUID or name of the deployment """ - api.recreate_deploy(deploy_id) + api.recreate_deploy(deployment) - @cliutils.args('--uuid', dest='deploy_id', type=str, required=False, - help='UUID of a deployment.') - @envutils.with_default_deploy_id - def destroy(self, deploy_id=None): + @cliutils.args('--deployment', dest='deployment', type=str, + required=False, help='UUID or name of a deployment.') + @envutils.with_default_deployment + def destroy(self, deployment=None): """Destroy existing deployment. This will delete all containers, virtual machines, OpenStack instances or Fuel clusters created during Rally deployment creation. Also it will remove deployment record from Rally database. - :param deploy_id: a UUID of the deployment + :param deployment: a UUID or name of the deployment """ - api.destroy_deploy(deploy_id) + api.destroy_deploy(deployment) def list(self, deployment_list=None): """List existing deployments.""" headers = ['uuid', 'created_at', 'name', 'status', 'active'] - current_deploy_id = envutils.get_global('RALLY_DEPLOYMENT') + current_deployment = envutils.get_global('RALLY_DEPLOYMENT') deployment_list = deployment_list or db.deployment_list() table_rows = [] if deployment_list: for t in deployment_list: r = [str(t[column]) for column in headers[:-1]] - r.append("" if t["uuid"] != current_deploy_id else "*") + r.append("" if t["uuid"] != current_deployment else "*") table_rows.append(utils.Struct(**dict(zip(headers, r)))) common_cliutils.print_list(table_rows, headers, sortby_index=headers.index( @@ -170,35 +173,35 @@ class DeploymentCommands(object): "To create a new deployment, use:" "\nrally deployment create")) - @cliutils.args('--uuid', dest='deploy_id', type=str, required=False, - help='UUID of a deployment.') - @envutils.with_default_deploy_id - def config(self, deploy_id=None): + @cliutils.args('--deployment', dest='deployment', type=str, + required=False, help='UUID or name of a deployment.') + @envutils.with_default_deployment + def config(self, deployment=None): """Display configuration of the deployment. Output is the configuration of the deployment in a pretty-printed JSON format. - :param deploy_id: a UUID of the deployment + :param deployment: a UUID or name of the deployment """ - deploy = db.deployment_get(deploy_id) - result = deploy['config'] + deploy = db.deployment_get(deployment) + result = deploy["config"] print(json.dumps(result, sort_keys=True, indent=4)) - @cliutils.args('--uuid', dest='deploy_id', type=str, required=False, - help='UUID of a deployment.') - @envutils.with_default_deploy_id - def show(self, deploy_id=None): + @cliutils.args('--deployment', dest='deployment', type=str, + required=False, help='UUID or name of a deployment.') + @envutils.with_default_deployment + def show(self, deployment=None): """Show the endpoints of the deployment. - :param deploy_id: a UUID of the deployment + :param deployment: a UUID or name of the deployment """ headers = ['auth_url', 'username', 'password', 'tenant_name', 'region_name', 'endpoint_type', 'admin_port'] table_rows = [] - deployment = db.deployment_get(deploy_id) + deployment = db.deployment_get(deployment) users = deployment.get("users", []) admin = deployment.get("admin") endpoints = users + [admin] if admin else users @@ -208,19 +211,19 @@ class DeploymentCommands(object): table_rows.append(utils.Struct(**dict(zip(headers, data)))) common_cliutils.print_list(table_rows, headers) - @cliutils.args('--uuid', dest='deploy_id', type=str, required=False, - help='UUID of a deployment.') - @envutils.with_default_deploy_id - def check(self, deploy_id=None): + @cliutils.args('--deployment', dest='deployment', type=str, + required=False, help='UUID or name of a deployment.') + @envutils.with_default_deployment + def check(self, deployment=None): """Check keystone authentication and list all available services. - :param deploy_id: a UUID of the deployment + :param deployment: a UUID or name of the deployment """ headers = ['services', 'type', 'status'] table_rows = [] try: - admin = db.deployment_get(deploy_id)['admin'] + admin = db.deployment_get(deployment)['admin'] # TODO(boris-42): make this work for users in future for endpoint_dict in [admin]: clients = osclients.Clients(endpoint.Endpoint(**endpoint_dict)) diff --git a/rally/cmd/commands/show.py b/rally/cmd/commands/show.py index f25bb64900..9fefbc1d8a 100644 --- a/rally/cmd/commands/show.py +++ b/rally/cmd/commands/show.py @@ -35,20 +35,20 @@ class ShowCommands(object): cloud represented by deployment. """ - def _get_endpoints(self, deploy_id): - deployment = db.deployment_get(deploy_id) + def _get_endpoints(self, deployment): + deployment = db.deployment_get(deployment) admin = deployment.get("admin") admin = [admin] if admin else [] return admin + deployment.get("users", []) - @cliutils.args('--deploy-id', dest='deploy_id', type=str, required=False, - help='the UUID of a deployment') - @envutils.with_default_deploy_id - def images(self, deploy_id=None): + @cliutils.args('--deployment', dest='deployment', type=str, + required=False, help='UUID or name of a deployment') + @envutils.with_default_deployment + def images(self, deployment=None): """Display available images. - :param deploy_id: the UUID of a deployment + :param deployment: UUID or name of a deployment """ headers = ['UUID', 'Name', 'Size (B)'] @@ -60,7 +60,7 @@ class ShowCommands(object): for col in float_cols])) try: - for endpoint_dict in self._get_endpoints(deploy_id): + for endpoint_dict in self._get_endpoints(deployment): clients = osclients.Clients(endpoint.Endpoint(**endpoint_dict)) glance_client = clients.glance() for image in glance_client.images.list(): @@ -76,13 +76,13 @@ class ShowCommands(object): print(_("Authentication Issues: %s") % e) return(1) - @cliutils.args('--deploy-id', dest='deploy_id', type=str, required=False, - help='the UUID of a deployment') - @envutils.with_default_deploy_id - def flavors(self, deploy_id=None): + @cliutils.args('--deployment', dest='deployment', type=str, + required=False, help='UUID or name of a deployment') + @envutils.with_default_deployment + def flavors(self, deployment=None): """Display available flavors. - :param deploy_id: the UUID of a deployment + :param deployment: UUID or name of a deployment """ headers = ['ID', 'Name', 'vCPUs', 'RAM (MB)', 'Swap (MB)', 'Disk (GB)'] @@ -93,7 +93,7 @@ class ShowCommands(object): for col in float_cols])) table_rows = [] try: - for endpoint_dict in self._get_endpoints(deploy_id): + for endpoint_dict in self._get_endpoints(deployment): clients = osclients.Clients(endpoint.Endpoint(**endpoint_dict)) nova_client = clients.nova() for flavor in nova_client.flavors.list(): @@ -110,17 +110,17 @@ class ShowCommands(object): print(_("Authentication Issues: %s") % e) return(1) - @cliutils.args('--deploy-id', dest='deploy_id', type=str, required=False, - help='the UUID of a deployment') - @envutils.with_default_deploy_id - def networks(self, deploy_id=None): + @cliutils.args('--deployment', dest='deployment', type=str, + required=False, help='UUID or name of a deployment') + @envutils.with_default_deployment + def networks(self, deployment=None): """Display configured networks.""" headers = ['ID', 'Label', 'CIDR'] mixed_case_fields = ['ID', 'Label', 'CIDR'] table_rows = [] try: - for endpoint_dict in self._get_endpoints(deploy_id): + for endpoint_dict in self._get_endpoints(deployment): clients = osclients.Clients(endpoint.Endpoint(**endpoint_dict)) nova_client = clients.nova() for network in nova_client.networks.list(): @@ -134,17 +134,17 @@ class ShowCommands(object): print(_("Authentication Issues: %s") % e) return(1) - @cliutils.args('--deploy-id', dest='deploy_id', type=str, required=False, - help='the UUID of a deployment') - @envutils.with_default_deploy_id - def secgroups(self, deploy_id=None): + @cliutils.args('--deployment', dest='deployment', type=str, + required=False, help='UUID or name of a deployment') + @envutils.with_default_deployment + def secgroups(self, deployment=None): """Display security groups.""" headers = ['ID', 'Name', 'Description'] mixed_case_fields = ['ID', 'Name', 'Description'] table_rows = [] try: - for endpoint_dict in self._get_endpoints(deploy_id): + for endpoint_dict in self._get_endpoints(deployment): clients = osclients.Clients(endpoint.Endpoint(**endpoint_dict)) nova_client = clients.nova() for secgroup in nova_client.security_groups.list(): @@ -161,17 +161,17 @@ class ShowCommands(object): print(_("Authentication Issues: %s") % e) return(1) - @cliutils.args('--deploy-id', dest='deploy_id', type=str, required=False, - help='the UUID of a deployment') - @envutils.with_default_deploy_id - def keypairs(self, deploy_id=None): + @cliutils.args('--deployment', dest='deployment', type=str, + required=False, help='UUID or name of a deployment') + @envutils.with_default_deployment + def keypairs(self, deployment=None): """Display available ssh keypairs.""" headers = ['Name', 'Fingerprint'] mixed_case_fields = ['Name', 'Fingerprint'] table_rows = [] try: - for endpoint_dict in self._get_endpoints(deploy_id): + for endpoint_dict in self._get_endpoints(deployment): clients = osclients.Clients(endpoint.Endpoint(**endpoint_dict)) nova_client = clients.nova() for keypair in nova_client.keypairs.list(): diff --git a/rally/cmd/commands/task.py b/rally/cmd/commands/task.py index 6906aa8196..2ff5a8c449 100644 --- a/rally/cmd/commands/task.py +++ b/rally/cmd/commands/task.py @@ -43,57 +43,57 @@ class TaskCommands(object): Set of commands that allow you to manage benchmarking tasks and results. """ - @cliutils.args('--deploy-id', type=str, dest='deploy_id', required=False, - help='UUID of the deployment') + @cliutils.args('--deployment', type=str, dest='deployment', + required=False, help='UUID or name of the deployment') @cliutils.args('--task', '--filename', help='Path to the file with full configuration of task') - @envutils.with_default_deploy_id - def validate(self, task, deploy_id=None): + @envutils.with_default_deployment + def validate(self, task, deployment=None): """Validate a task configuration file. This will check that task configuration file has valid syntax and all required options of scenarios, contexts, SLA and runners are set. :param task: a file with yaml/json configration - :param deploy_id: a UUID of a deployment + :param deployment: UUID or name of a deployment """ task = os.path.expanduser(task) with open(task, "rb") as task_file: config_dict = yaml.safe_load(task_file.read()) try: - api.task_validate(deploy_id, config_dict) + api.task_validate(deployment, config_dict) print("Task config is valid :)") except exceptions.InvalidTaskException as e: print("Task config is invalid: \n") print(e) - @cliutils.args('--deploy-id', type=str, dest='deploy_id', required=False, - help='UUID of the deployment') + @cliutils.args('--deployment', type=str, dest='deployment', + required=False, help='UUID or name of the deployment') @cliutils.args('--task', '--filename', help='Path to the file with full configuration of task') @cliutils.args('--tag', help='Tag for this task') @cliutils.args('--no-use', action='store_false', dest='do_use', help='Don\'t set new task as default for future operations') - @envutils.with_default_deploy_id - def start(self, task, deploy_id=None, tag=None, do_use=False): + @envutils.with_default_deployment + def start(self, task, deployment=None, tag=None, do_use=False): """Start benchmark task. :param task: a file with yaml/json configration - :param deploy_id: a UUID of a deployment + :param deployment: UUID or name of a deployment :param tag: optional tag for this task """ task = os.path.expanduser(task) with open(task, 'rb') as task_file: config_dict = yaml.safe_load(task_file.read()) try: - task = api.create_task(deploy_id, tag) + task = api.create_task(deployment, tag) print("=" * 80) print(_("Task %(tag)s %(uuid)s is started") % {"uuid": task["uuid"], "tag": task["tag"]}) print("-" * 80) - api.start_task(deploy_id, config_dict, task=task) + api.start_task(deployment, config_dict, task=task) self.detailed(task_id=task['uuid']) if do_use: use.UseCommands().task(task['uuid']) diff --git a/rally/cmd/commands/use.py b/rally/cmd/commands/use.py index 6458d902d2..10737e40ce 100644 --- a/rally/cmd/commands/use.py +++ b/rally/cmd/commands/use.py @@ -30,8 +30,8 @@ class UseCommands(object): task UUID in the commands requiring this parameter. """ - def _update_openrc_deployment_file(self, deploy_id, endpoint): - openrc_path = os.path.expanduser('~/.rally/openrc-%s' % deploy_id) + def _update_openrc_deployment_file(self, deployment, endpoint): + openrc_path = os.path.expanduser('~/.rally/openrc-%s' % deployment) # NOTE(msdubov): In case of multiple endpoints write the first one. with open(openrc_path, 'w+') as env_file: env_file.write('export OS_AUTH_URL=%(auth_url)s\n' @@ -55,42 +55,22 @@ class UseCommands(object): if not os.path.exists(os.path.expanduser('~/.rally/')): os.makedirs(os.path.expanduser('~/.rally/')) - @cliutils.args('--uuid', type=str, dest='deploy_id', required=False, - help='UUID of the deployment') - @cliutils.args('--name', type=str, dest='name', required=False, - help='Name of the deployment') - def deployment(self, deploy_id=None, name=None): + @cliutils.args('--deployment', type=str, dest='deployment', + help='UUID or name of the deployment') + def deployment(self, deployment=None): """Set active deployment. - :param deploy_id: a UUID of a deployment + :param deployment: UUID or name of a deployment """ - if not (name or deploy_id): - print('You should specify --name or --uuid of deployment') - return 1 - - deploy = None - - if name: - deployments = db.deployment_list(name=name) - if len(deployments) > 1: - print("Multiple deployments found by name: `%s`" % name) - return 1 - elif not deployments: - print("There is no `%s` deployment" % name) - return 1 - else: - deploy = deployments[0] - deploy_id = deploy["uuid"] - try: - deploy = deploy or db.deployment_get(deploy_id) - print('Using deployment: %s' % deploy_id) + deploy = db.deployment_get(deployment) + print('Using deployment: %s' % deploy['uuid']) self._ensure_rally_configuration_dir_exists() self._update_attribute_in_global_file('RALLY_DEPLOYMENT', - deploy_id) + deploy['uuid']) self._update_openrc_deployment_file( - deploy_id, deploy.get('admin') or deploy.get('users')[0]) + deploy['uuid'], deploy.get('admin') or deploy.get('users')[0]) print ('~/.rally/openrc was updated\n\nHINTS:\n' '* To get your cloud resources, run:\n\t' 'rally show [flavors|images|keypairs|networks|secgroups]\n' @@ -99,7 +79,7 @@ class UseCommands(object): ' OpenStack clients are now configured, e.g run:\n\t' 'glance image-list') except exceptions.DeploymentNotFound: - print('Deployment %s is not found.' % deploy_id) + print('Deployment %s is not found.' % deployment) return 1 @cliutils.args('--uuid', type=str, dest='task_id', required=False, diff --git a/rally/cmd/commands/verify.py b/rally/cmd/commands/verify.py index 036dfc89ff..1197c29068 100644 --- a/rally/cmd/commands/verify.py +++ b/rally/cmd/commands/verify.py @@ -42,8 +42,8 @@ class VerifyCommands(object): OpenStack live cloud. """ - @cliutils.args("--deploy-id", dest="deploy_id", type=str, required=False, - help="UUID of a deployment.") + @cliutils.args("--deployment", dest="deployment", type=str, + required=False, help="UUID or name of a deployment.") @cliutils.args("--set", dest="set_name", type=str, required=False, help="Name of tempest test set. Available sets: %s" % ", ". join(consts.TEMPEST_TEST_SETS)) @@ -54,13 +54,13 @@ class VerifyCommands(object): help="User specified Tempest config file location") @cliutils.args("--no-use", action="store_false", dest="do_use", help="Don't set new task as default for future operations") - @envutils.with_default_deploy_id - def start(self, set_name="smoke", deploy_id=None, regex=None, + @envutils.with_default_deployment + def start(self, set_name="smoke", deployment=None, regex=None, tempest_config=None, do_use=False): """Start set of tests. :param set_name: Name of tempest test set - :param deploy_id: a UUID of a deployment + :param deployment: UUID or name of a deployment :param regex: Regular expression of test :param tempest_config: User specified Tempest config file location """ @@ -71,7 +71,8 @@ class VerifyCommands(object): print("Sorry, but there are no desired tempest test set. Please " "choose from: %s" % ", ".join(consts.TEMPEST_TEST_SETS)) return (1) - verification = api.verify(deploy_id, set_name, regex, tempest_config) + verification = api.verify(deployment, set_name, regex, + tempest_config) if do_use: use.UseCommands().verification(verification["uuid"]) diff --git a/rally/cmd/envutils.py b/rally/cmd/envutils.py index 82ea7c568e..0c7f513564 100644 --- a/rally/cmd/envutils.py +++ b/rally/cmd/envutils.py @@ -65,8 +65,8 @@ def default_from_global(arg_name, env_name, return f(*args, **kwargs) return decorator.decorator(default_from_global) -with_default_deploy_id = default_from_global('deploy_id', ENV_DEPLOYMENT, - "uuid") +with_default_deployment = default_from_global( + "deployment", ENV_DEPLOYMENT, "uuid") with_default_task_id = default_from_global('task_id', ENV_TASK, "uuid") with_default_verification_id = default_from_global( diff --git a/rally/cmd/manage.py b/rally/cmd/manage.py index 9c9acbf163..3268020a80 100644 --- a/rally/cmd/manage.py +++ b/rally/cmd/manage.py @@ -37,12 +37,14 @@ class DBCommands(object): class TempestCommands(object): """Commands for Tempest management.""" - @cliutils.args('--deploy-id', type=str, dest='deploy_id', required=False, - help='UUID of the deployment') - @envutils.with_default_deploy_id - def install(self, deploy_id=None): + @cliutils.args("--deployment", type=str, dest="deployment", + required=False, help="UUID or name of the deployment") + @envutils.with_default_deployment + def install(self, deployment=None): """Install tempest.""" - verifier = tempest.Tempest(deploy_id) + + deployment_uuid = db.deployment_get(deployment)['uuid'] + verifier = tempest.Tempest(deployment_uuid) verifier.install() diff --git a/rally/db/api.py b/rally/db/api.py index 8ad111ab80..cb40422047 100644 --- a/rally/db/api.py +++ b/rally/db/api.py @@ -180,15 +180,15 @@ def deployment_delete(uuid): return IMPL.deployment_delete(uuid) -def deployment_get(uuid): +def deployment_get(deployment): """Get a deployment by UUID. - :param uuid: UUID of the deployment. + :param deployment: UUID or name of the deployment. :raises: :class:`rally.exceptions.DeploymentNotFound` if the deployment does not exist. :returns: a dict with data on the deployment. """ - return IMPL.deployment_get(uuid) + return IMPL.deployment_get(deployment) def deployment_update(uuid, values): diff --git a/rally/db/sqlalchemy/api.py b/rally/db/sqlalchemy/api.py index 69593aaab4..24c8b0541d 100644 --- a/rally/db/sqlalchemy/api.py +++ b/rally/db/sqlalchemy/api.py @@ -164,17 +164,26 @@ class Connection(object): return (self.model_query(models.TaskResult). filter_by(task_uuid=uuid).all()) - def _deployment_get(self, uuid, session=None): - deploy = (self.model_query(models.Deployment, session=session). - filter_by(uuid=uuid).first()) - if not deploy: - raise exceptions.DeploymentNotFound(uuid=uuid) - return deploy + def _deployment_get(self, deployment, session=None): + stored_deployment = self.model_query( + models.Deployment, + session=session).filter_by(name=deployment).first() + if not stored_deployment: + stored_deployment = self.model_query( + models.Deployment, + session=session).filter_by(uuid=deployment).first() + + if not stored_deployment: + raise exceptions.DeploymentNotFound(deployment=deployment) + return stored_deployment def deployment_create(self, values): deployment = models.Deployment() - deployment.update(values) - deployment.save() + try: + deployment.update(values) + deployment.save() + except db_exc.DBDuplicateEntry: + raise exceptions.DeploymentNameExists(deployment=values["name"]) return deployment def deployment_delete(self, uuid): @@ -190,16 +199,16 @@ class Connection(object): if not count: raise exceptions.DeploymentNotFound(uuid=uuid) - def deployment_get(self, uuid): - return self._deployment_get(uuid) + def deployment_get(self, deployment): + return self._deployment_get(deployment) - def deployment_update(self, uuid, values): + def deployment_update(self, deployment, values): session = get_session() values.pop('uuid', None) with session.begin(): - deploy = self._deployment_get(uuid, session=session) - deploy.update(values) - return deploy + dpl = self._deployment_get(deployment, session=session) + dpl.update(values) + return dpl def deployment_list(self, status=None, parent_uuid=None, name=None): query = (self.model_query(models.Deployment). diff --git a/rally/db/sqlalchemy/models.py b/rally/db/sqlalchemy/models.py index cc6f6ec705..59bf93181f 100644 --- a/rally/db/sqlalchemy/models.py +++ b/rally/db/sqlalchemy/models.py @@ -63,7 +63,7 @@ class Deployment(BASE, RallyBase): sa.ForeignKey(uuid, use_alter=True, name='fk_parent_uuid'), default=None, ) - name = sa.Column(sa.String(255)) + name = sa.Column(sa.String(255), unique=True) started_at = sa.Column(sa.DateTime) completed_at = sa.Column(sa.DateTime) # XXX(akscram): Do we need to explicitly store a name of the diff --git a/rally/deploy/serverprovider/providers/openstack.py b/rally/deploy/serverprovider/providers/openstack.py index 8ac5d3f886..bb3755dc3e 100644 --- a/rally/deploy/serverprovider/providers/openstack.py +++ b/rally/deploy/serverprovider/providers/openstack.py @@ -232,9 +232,9 @@ class OpenStackProvider(provider.ProviderFactory): except exceptions.ResourceNotFound: LOG.warning( 'Instance resource record not found in DB, not removing.' - ' Deployment: %(deploy_id)s Instance ID:%(id)s' + ' Deployment: %(deployment)s Instance ID:%(id)s' ' Instance Nova UUID:%(uuid)s' % - dict(deploy_id=resource.deployment_uuid, + dict(deployment=resource.deployment_uuid, id=resource.id, uuid=resource['info']['id'] ) @@ -252,9 +252,9 @@ class OpenStackProvider(provider.ProviderFactory): except exceptions.ResourceNotFound: LOG.warning( 'Keypair resource record not found in DB, not removing.' - ' Deployment: %(deploy_id)s Keypair ID:%(id)s' + ' Deployment: %(deployment)s Keypair ID:%(id)s' ' Keypair Name:%(name)s' % - dict(deploy_id=resource.deployment_uuid, + dict(deployment=resource.deployment_uuid, id=resource.id, name=resource['info']['id'] ) diff --git a/rally/exceptions.py b/rally/exceptions.py index 927c7dfdc4..d1ffec632c 100644 --- a/rally/exceptions.py +++ b/rally/exceptions.py @@ -153,7 +153,11 @@ class TaskNotFound(NotFoundException): class DeploymentNotFound(NotFoundException): - msg_fmt = _("Deployment with uuid=%(uuid)s not found.") + msg_fmt = _("Deployment %(deployment)s not found.") + + +class DeploymentNameExists(RallyException): + msg_fmt = _("Deployment name '%(deployment)s' already registered.") class DeploymentIsBusy(RallyException): diff --git a/rally/objects/deploy.py b/rally/objects/deploy.py index cd1cdb20ae..cfd940f47a 100644 --- a/rally/objects/deploy.py +++ b/rally/objects/deploy.py @@ -32,8 +32,8 @@ class Deployment(object): return self.deployment[key] @staticmethod - def get(uuid): - return Deployment(db.deployment_get(uuid)) + def get(deploy): + return Deployment(db.deployment_get(deploy)) @staticmethod def delete_by_uuid(uuid): diff --git a/rally/orchestrator/api.py b/rally/orchestrator/api.py index ed748795b8..3e1ca936b7 100644 --- a/rally/orchestrator/api.py +++ b/rally/orchestrator/api.py @@ -14,15 +14,18 @@ # under the License. import jsonschema +from oslo.config import cfg from rally.benchmark import engine from rally import consts from rally import deploy from rally import exceptions +from rally.i18n import _ from rally import log as logging from rally import objects from rally.verification.verifiers.tempest import tempest +CONF = cfg.CONF LOG = logging.getLogger(__name__) @@ -32,7 +35,14 @@ def create_deploy(config, name): :param config: a dict with deployment configuration :param name: a str represents a name of the deployment """ - deployment = objects.Deployment(name=name, config=config) + + try: + deployment = objects.Deployment(name=name, config=config) + except exceptions.DeploymentNameExists as e: + if CONF.debug: + LOG.exception(e) + raise + deployer = deploy.EngineFactory.get_engine(deployment['config']['type'], deployment) try: @@ -49,31 +59,31 @@ def create_deploy(config, name): return deployment -def destroy_deploy(deploy_uuid): +def destroy_deploy(deployment): """Destroy the deployment. - :param deploy_uuid: UUID of the deployment + :param deployment: UUID or name of the deployment """ # TODO(akscram): We have to be sure that there are no running # tasks for this deployment. # TODO(akscram): Check that the deployment have got a status that # is equal to "*->finished" or "deploy->inconsistent". - deployment = objects.Deployment.get(deploy_uuid) + deployment = objects.Deployment.get(deployment) deployer = deploy.EngineFactory.get_engine(deployment['config']['type'], deployment) with deployer: deployer.make_cleanup() deployment.delete() - tempest.Tempest(deploy_uuid).uninstall() + tempest.Tempest(deployment['uuid']).uninstall() -def recreate_deploy(deploy_uuid): +def recreate_deploy(deployment): """Performs a clean up and then start to deploy. - :param deploy_uuid: UUID of the deployment + :param deployment: UUID or name of the deployment """ - deployment = objects.Deployment.get(deploy_uuid) + deployment = objects.Deployment.get(deployment) deployer = deploy.EngineFactory.get_engine(deployment['config']['type'], deployment) with deployer: @@ -82,43 +92,45 @@ def recreate_deploy(deploy_uuid): deployment.update_endpoints(endpoints) -def create_task(deploy_uuid, tag): +def create_task(deployment, tag): """Create a task without starting it. Task is a list of benchmarks that will be called one by one, results of execution will be stored in DB. - :param deploy_uuid: UUID of the deployment + :param deployment: UUID or name of the deployment :param tag: tag for this task """ - return objects.Task(deployment_uuid=deploy_uuid, tag=tag) + + deployment_uuid = objects.Deployment.get(deployment)['uuid'] + return objects.Task(deployment_uuid=deployment_uuid, tag=tag) -def task_validate(deploy_uuid, config): +def task_validate(deployment, config): """Validate a task config against specified deployment. - :param deploy_uuid: UUID of the deployment + :param deployment: UUID or name of the deployment :param config: a dict with a task configuration """ - deployment = objects.Deployment.get(deploy_uuid) - task = objects.Task(deployment_uuid=deploy_uuid) + deployment = objects.Deployment.get(deployment) + task = objects.Task(deployment_uuid=deployment['uuid']) benchmark_engine = engine.BenchmarkEngine(config, task) benchmark_engine.bind(admin=deployment["admin"], users=deployment["users"]) benchmark_engine.validate() -def start_task(deploy_uuid, config, task=None): +def start_task(deployment, config, task=None): """Start a task. Task is a list of benchmarks that will be called one by one, results of execution will be stored in DB. - :param deploy_uuid: UUID of the deployment + :param deployment: UUID or name of the deployment :param config: a dict with a task configuration """ - deployment = objects.Deployment.get(deploy_uuid) - task = task or objects.Task(deployment_uuid=deploy_uuid) + deployment = objects.Deployment.get(deployment) + task = task or objects.Task(deployment_uuid=deployment['uuid']) LOG.info("Benchmark Task %s on Deployment %s" % (task['uuid'], deployment['uuid'])) benchmark_engine = engine.BenchmarkEngine(config, task) @@ -157,23 +169,25 @@ def delete_task(task_uuid, force=False): objects.Task.delete_by_uuid(task_uuid, status=status) -def verify(deploy_id, set_name, regex, tempest_config): +def verify(deployment, set_name, regex, tempest_config): """Start verifying. - :param deploy_id: a UUID of a deployment. + :param deployment: UUID or name of a deployment. :param set_name: Valid name of tempest test set. :param regex: Regular expression of test :param tempest_config: User specified Tempest config file """ - verification = objects.Verification(deployment_uuid=deploy_id) - verifier = tempest.Tempest(deploy_id, verification=verification, + deployment_uuid = objects.Deployment.get(deployment)["uuid"] + + verification = objects.Verification(deployment_uuid=deployment_uuid) + verifier = tempest.Tempest(deployment_uuid, verification=verification, tempest_config=tempest_config) if not verifier.is_installed(): print("Tempest is not installed for specified deployment.") - print("Installing Tempest for deployment %s" % deploy_id) + print("Installing Tempest for deployment %s" % deploy) verifier.install() - LOG.info("Starting verification of deployment: %s" % deploy_id) + LOG.info("Starting verification of deployment: %s" % deploy) verification.set_running() verifier.verify(set_name=set_name, regex=regex) diff --git a/rally/verification/verifiers/tempest/config.py b/rally/verification/verifiers/tempest/config.py index 71e5b13104..fd13f3f845 100644 --- a/rally/verification/verifiers/tempest/config.py +++ b/rally/verification/verifiers/tempest/config.py @@ -52,8 +52,8 @@ class TempestConfigCreationFailure(exceptions.RallyException): class TempestConf(object): - def __init__(self, deploy_id): - self.endpoint = db.deployment_get(deploy_id)['admin'] + def __init__(self, deployment): + self.endpoint = db.deployment_get(deployment)['admin'] self.clients = osclients.Clients(endpoint.Endpoint(**self.endpoint)) try: self.keystoneclient = self.clients.verified_keystone() @@ -67,7 +67,7 @@ class TempestConf(object): self.conf = configparser.ConfigParser() self.conf.read(os.path.join(os.path.dirname(__file__), 'config.ini')) - self.deploy_id = deploy_id + self.deployment = deployment self.data_path = os.path.join(os.path.expanduser('~'), '.rally', 'tempest', 'data') if not os.path.exists(self.data_path): @@ -111,7 +111,7 @@ class TempestConf(object): def _set_default(self): lock_path = os.path.join(self.data_path, - 'lock_files_%s' % self.deploy_id) + 'lock_files_%s' % self.deployment) if not os.path.exists(lock_path): os.makedirs(lock_path) self.conf.set('DEFAULT', 'lock_path', lock_path) diff --git a/rally/verification/verifiers/tempest/tempest.py b/rally/verification/verifiers/tempest/tempest.py index 34c03864cf..c103de3038 100644 --- a/rally/verification/verifiers/tempest/tempest.py +++ b/rally/verification/verifiers/tempest/tempest.py @@ -46,11 +46,11 @@ class Tempest(object): base_repo = os.path.join(os.path.expanduser("~"), ".rally/tempest/base") - def __init__(self, deploy_id, verification=None, tempest_config=None): - self.deploy_id = deploy_id + def __init__(self, deployment, verification=None, tempest_config=None): + self.deployment = deployment self._path = os.path.join(os.path.expanduser("~"), ".rally/tempest", - "for-deployment-%s" % deploy_id) + "for-deployment-%s" % deployment) self.config_file = tempest_config or self.path("tempest.conf") self.log_file_raw = self.path("subunit.stream") self.venv_wrapper = self.path("tools/with_venv.sh") @@ -99,7 +99,7 @@ class Tempest(object): msg = _("Creation of configuration file for tempest.") LOG.info(_("Starting: ") + msg) - config.TempestConf(self.deploy_id).generate(self.config_file) + config.TempestConf(self.deployment).generate(self.config_file) LOG.info(_("Completed: ") + msg) else: LOG.info("Tempest is already configured.") diff --git a/tests/ci/rally-gate.sh b/tests/ci/rally-gate.sh index 295ecc46ed..5784a30565 100755 --- a/tests/ci/rally-gate.sh +++ b/tests/ci/rally-gate.sh @@ -35,7 +35,7 @@ fi env set -o pipefail -rally use deployment --name devstack +rally use deployment --deployment devstack rally deployment check rally show flavors rally show images diff --git a/tests/unit/cmd/commands/test_deployment.py b/tests/unit/cmd/commands/test_deployment.py index bed516d2bd..a047d96d01 100644 --- a/tests/unit/cmd/commands/test_deployment.py +++ b/tests/unit/cmd/commands/test_deployment.py @@ -28,7 +28,7 @@ class DeploymentCommandsTestCase(test.TestCase): super(DeploymentCommandsTestCase, self).setUp() self.deployment = deployment.DeploymentCommands() - @mock.patch.dict(os.environ, {'RALLY_DEPLOYMENT': 'my_deploy_id'}) + @mock.patch.dict(os.environ, {'RALLY_DEPLOYMENT': 'my_deployment_id'}) @mock.patch('rally.cmd.commands.deployment.DeploymentCommands.list') @mock.patch('rally.cmd.commands.deployment.api.create_deploy') @mock.patch('rally.cmd.commands.deployment.open', @@ -78,24 +78,24 @@ class DeploymentCommandsTestCase(test.TestCase): @mock.patch('rally.cmd.commands.deployment.api.recreate_deploy') def test_recreate(self, mock_recreate): - deploy_id = '43924f8b-9371-4152-af9f-4cf02b4eced4' - self.deployment.recreate(deploy_id) - mock_recreate.assert_called_once_with(deploy_id) + deployment_id = '43924f8b-9371-4152-af9f-4cf02b4eced4' + self.deployment.recreate(deployment_id) + mock_recreate.assert_called_once_with(deployment_id) @mock.patch('rally.cmd.commands.deployment.envutils.get_global') - def test_recreate_no_deploy_id(self, mock_default): + def test_recreate_no_deployment_id(self, mock_default): mock_default.side_effect = exceptions.InvalidArgumentsException self.assertRaises(exceptions.InvalidArgumentsException, self.deployment.recreate, None) @mock.patch('rally.cmd.commands.deployment.api.destroy_deploy') def test_destroy(self, mock_destroy): - deploy_id = '53fd0273-60ce-42e5-a759-36f1a683103e' - self.deployment.destroy(deploy_id) - mock_destroy.assert_called_once_with(deploy_id) + deployment_id = '53fd0273-60ce-42e5-a759-36f1a683103e' + self.deployment.destroy(deployment_id) + mock_destroy.assert_called_once_with(deployment_id) @mock.patch('rally.cmd.commands.deployment.envutils.get_global') - def test_destroy_no_deploy_id(self, mock_default): + def test_destroy_no_deployment_id(self, mock_default): mock_default.side_effect = exceptions.InvalidArgumentsException self.assertRaises(exceptions.InvalidArgumentsException, self.deployment.destroy, None) @@ -104,11 +104,11 @@ class DeploymentCommandsTestCase(test.TestCase): @mock.patch('rally.cmd.commands.deployment.utils.Struct') @mock.patch('rally.cmd.commands.deployment.envutils.get_global') @mock.patch('rally.cmd.commands.deployment.db.deployment_list') - def test_list_different_deploy_id(self, mock_deployments, - mock_default, mock_struct, - mock_print_list): - current_deploy_id = '26a3ce76-0efa-40e4-86e5-514574bd1ff6' - mock_default.return_value = current_deploy_id + def test_list_different_deployment_id(self, mock_deployments, + mock_default, mock_struct, + mock_print_list): + current_deployment_id = '26a3ce76-0efa-40e4-86e5-514574bd1ff6' + mock_default.return_value = current_deployment_id fake_deployment_list = [ {'uuid': 'fa34aea2-ae2e-4cf7-a072-b08d67466e3e', 'created_at': '03-12-2014', @@ -132,12 +132,12 @@ class DeploymentCommandsTestCase(test.TestCase): @mock.patch('rally.cmd.commands.deployment.utils.Struct') @mock.patch('rally.cmd.commands.deployment.envutils.get_global') @mock.patch('rally.cmd.commands.deployment.db.deployment_list') - def test_list_current_deploy_id(self, mock_deployments, - mock_default, mock_struct, - mock_print_list): - current_deploy_id = '64258e84-ffa1-4011-9e4c-aba07bdbcc6b' - mock_default.return_value = current_deploy_id - fake_deployment_list = [{'uuid': current_deploy_id, + def test_list_current_deployment_id(self, mock_deployments, + mock_default, mock_struct, + mock_print_list): + current_deployment_id = '64258e84-ffa1-4011-9e4c-aba07bdbcc6b' + mock_default.return_value = current_deployment_id + fake_deployment_list = [{'uuid': current_deployment_id, 'created_at': '13-12-2014', 'name': 'dep2', 'status': 'deploy->finished', @@ -157,16 +157,16 @@ class DeploymentCommandsTestCase(test.TestCase): @mock.patch('rally.cmd.commands.deployment.db.deployment_get') @mock.patch('json.dumps') def test_config(self, mock_json_dumps, mock_deployment): - deploy_id = 'fa4a423e-f15d-4d83-971a-89574f892999' + deployment_id = 'fa4a423e-f15d-4d83-971a-89574f892999' value = {'config': 'config'} mock_deployment.return_value = value - self.deployment.config(deploy_id) + self.deployment.config(deployment_id) mock_json_dumps.assert_called_once_with(value['config'], sort_keys=True, indent=4) - mock_deployment.assert_called_once_with(deploy_id) + mock_deployment.assert_called_once_with(deployment_id) @mock.patch('rally.cmd.commands.deployment.envutils.get_global') - def test_config_no_deploy_id(self, mock_default): + def test_config_no_deployment_id(self, mock_default): mock_default.side_effect = exceptions.InvalidArgumentsException self.assertRaises(exceptions.InvalidArgumentsException, self.deployment.config, None) @@ -175,7 +175,7 @@ class DeploymentCommandsTestCase(test.TestCase): @mock.patch('rally.cmd.commands.deployment.utils.Struct') @mock.patch('rally.cmd.commands.deployment.db.deployment_get') def test_show(self, mock_deployment, mock_struct, mock_print_list): - deploy_id = "b1a6153e-a314-4cb3-b63b-cf08c1a416c3" + deployment_id = "b1a6153e-a314-4cb3-b63b-cf08c1a416c3" value = { "admin": { "auth_url": "url", @@ -189,8 +189,8 @@ class DeploymentCommandsTestCase(test.TestCase): "users": [] } mock_deployment.return_value = value - self.deployment.show(deploy_id) - mock_deployment.assert_called_once_with(deploy_id) + self.deployment.show(deployment_id) + mock_deployment.assert_called_once_with(deployment_id) headers = ["auth_url", "username", "password", "tenant_name", "region_name", "endpoint_type", "admin_port"] @@ -200,7 +200,7 @@ class DeploymentCommandsTestCase(test.TestCase): mock_print_list.assert_called_once_with([mock_struct()], headers) @mock.patch('rally.cmd.commands.deployment.envutils.get_global') - def test_deploy_no_deploy_id(self, mock_default): + def test_deploy_no_deployment_id(self, mock_default): mock_default.side_effect = exceptions.InvalidArgumentsException self.assertRaises(exceptions.InvalidArgumentsException, self.deployment.show, None) diff --git a/tests/unit/cmd/commands/test_show.py b/tests/unit/cmd/commands/test_show.py index e49a84e802..8d6927ffc3 100644 --- a/tests/unit/cmd/commands/test_show.py +++ b/tests/unit/cmd/commands/test_show.py @@ -29,7 +29,7 @@ class ShowCommandsTestCase(test.TestCase): 'password': 'fake_password', 'tenant_name': 'fake_tenant_name', 'auth_url': 'http://fake.auth.url'} - self.fake_deploy_id = '7f6e88e0-897e-45c0-947c-595ce2437bee' + self.fake_deployment_id = '7f6e88e0-897e-45c0-947c-595ce2437bee' self.fake_clients = fakes.FakeClients() self.fake_glance_client = fakes.FakeGlanceClient() self.fake_nova_client = fakes.FakeNovaClient() @@ -46,8 +46,8 @@ class ShowCommandsTestCase(test.TestCase): fake_image.size = 1 mock_get_glance.return_value = self.fake_glance_client mock_deployment_get.return_value = {'admin': self.fake_endpoint} - self.show.images(self.fake_deploy_id) - mock_deployment_get.assert_called_once_with(self.fake_deploy_id) + self.show.images(self.fake_deployment_id) + mock_deployment_get.assert_called_once_with(self.fake_deployment_id) mock_get_glance.assert_called_once_with() headers = ['UUID', 'Name', 'Size (B)'] @@ -75,8 +75,8 @@ class ShowCommandsTestCase(test.TestCase): fake_flavor.ram, fake_flavor.swap, fake_flavor.disk = 1024, 128, 10 mock_get_nova.return_value = self.fake_nova_client mock_deployment_get.return_value = {'admin': self.fake_endpoint} - self.show.flavors(self.fake_deploy_id) - mock_deployment_get.assert_called_once_with(self.fake_deploy_id) + self.show.flavors(self.fake_deployment_id) + mock_deployment_get.assert_called_once_with(self.fake_deployment_id) mock_get_nova.assert_called_once_with() headers = ['ID', 'Name', 'vCPUs', 'RAM (MB)', 'Swap (MB)', 'Disk (GB)'] @@ -106,8 +106,8 @@ class ShowCommandsTestCase(test.TestCase): fake_network.cidr = '10.0.0.0/24' mock_get_nova.return_value = self.fake_nova_client mock_deployment_get.return_value = {'admin': self.fake_endpoint} - self.show.networks(self.fake_deploy_id) - mock_deployment_get.assert_called_once_with(self.fake_deploy_id) + self.show.networks(self.fake_deployment_id) + mock_deployment_get.assert_called_once_with(self.fake_deployment_id) mock_get_nova.assert_called_once_with() headers = ['ID', 'Label', 'CIDR'] @@ -130,8 +130,8 @@ class ShowCommandsTestCase(test.TestCase): fake_secgroup.id = 0 mock_get_nova.return_value = self.fake_nova_client mock_deployment_get.return_value = {'admin': self.fake_endpoint} - self.show.secgroups(self.fake_deploy_id) - mock_deployment_get.assert_called_once_with(self.fake_deploy_id) + self.show.secgroups(self.fake_deployment_id) + mock_deployment_get.assert_called_once_with(self.fake_deployment_id) mock_get_nova.assert_called_once_with() headers = ['ID', 'Name', 'Description'] @@ -155,8 +155,8 @@ class ShowCommandsTestCase(test.TestCase): fake_keypair.fingerprint = '84:87:58' mock_get_nova.return_value = self.fake_nova_client mock_deployment_get.return_value = {'admin': self.fake_endpoint} - self.show.keypairs(self.fake_deploy_id) - mock_deployment_get.assert_called_once_with(self.fake_deploy_id) + self.show.keypairs(self.fake_deployment_id) + mock_deployment_get.assert_called_once_with(self.fake_deployment_id) mock_get_nova.assert_called_once_with() headers = ['Name', 'Fingerprint'] diff --git a/tests/unit/cmd/commands/test_task.py b/tests/unit/cmd/commands/test_task.py index 14a2678523..b4037f678a 100644 --- a/tests/unit/cmd/commands/test_task.py +++ b/tests/unit/cmd/commands/test_task.py @@ -38,13 +38,13 @@ class TaskCommandsTestCase(test.TestCase): dict(uuid='fc1a9bbe-1ead-4740-92b5-0feecf421634', created_at='2014-01-14 09:14:45.395822', status='init', failed=False, tag=None)) - deploy_id = 'e0617de9-77d1-4875-9b49-9d5789e29f20' - self.task.start('path_to_config.json', deploy_id) - mock_api.assert_called_once_with(deploy_id, {u'some': u'json'}, + deployment_id = 'e0617de9-77d1-4875-9b49-9d5789e29f20' + self.task.start('path_to_config.json', deployment_id) + mock_api.assert_called_once_with(deployment_id, {u'some': u'json'}, task=mock_create_task.return_value) @mock.patch('rally.cmd.commands.task.envutils.get_global') - def test_start_no_deploy_id(self, mock_default): + def test_start_no_deployment_id(self, mock_default): mock_default.side_effect = exceptions.InvalidArgumentsException self.assertRaises(exceptions.InvalidArgumentsException, self.task.start, 'path_to_config.json', None) @@ -62,9 +62,9 @@ class TaskCommandsTestCase(test.TestCase): created_at='2014-01-14 09:14:45.395822', status='init', failed=False, tag=None)) mock_api.start_task.side_effect = KeyboardInterrupt - deploy_id = 'f586dcd7-8473-4c2e-a4d4-22be26371c10' + deployment_id = 'f586dcd7-8473-4c2e-a4d4-22be26371c10' self.assertRaises(KeyboardInterrupt, self.task.start, - 'path_to_config.json', deploy_id) + 'path_to_config.json', deployment_id) mock_api.abort_task.assert_called_once_with( mock_api.create_task.return_value['uuid']) diff --git a/tests/unit/cmd/commands/test_use.py b/tests/unit/cmd/commands/test_use.py index 9ba4c86179..e2a10ad29e 100644 --- a/tests/unit/cmd/commands/test_use.py +++ b/tests/unit/cmd/commands/test_use.py @@ -20,6 +20,7 @@ import mock from rally.cmd.commands import use from rally.cmd import envutils from rally import exceptions +from tests.unit import fakes from tests.unit import test MOD = 'rally.cmd.commands.use.' @@ -30,7 +31,9 @@ class UseCommandsTestCase(test.TestCase): super(UseCommandsTestCase, self).setUp() self.use = use.UseCommands() - def test_deployment_use_no_args(self): + @mock.patch('rally.cmd.commands.use.db.deployment_get', + side_effect=exceptions.DeploymentNotFound()) + def test_deployment_use_no_args(self, mock_d_get): status = self.use.deployment() self.assertEqual(1, status) @@ -39,58 +42,61 @@ class UseCommandsTestCase(test.TestCase): @mock.patch(MOD + 'UseCommands._ensure_rally_configuration_dir_exists') @mock.patch(MOD + 'db') def test_deployment_use_by_name(self, m_db, m_ercde, m_uaigf, m_uodf): - fake_deployment = {'uuid': 'fake_uuid', - 'admin': 'fake_endpoints'} + fake_deployment = fakes.FakeDeployment( + uuid='fake_uuid', + admin='fake_endpoints') m_db.deployment_list.return_value = [fake_deployment] m_db.deployment_get.return_value = fake_deployment - status = self.use.deployment(name='fake_name') + status = self.use.deployment(deployment='fake_name') self.assertIsNone(status) - m_db.deployment_list.assert_called_once_with(name='fake_name') + m_db.deployment_get.assert_called_once_with('fake_name') m_ercde.assert_called_once_with() m_uaigf.assert_called_once_with(envutils.ENV_DEPLOYMENT, 'fake_uuid') m_uodf.assert_called_once_with('fake_uuid', 'fake_endpoints') @mock.patch('os.remove') @mock.patch('os.symlink') - @mock.patch(MOD + 'db.deployment_get') + @mock.patch( + MOD + 'db.deployment_get', + return_value=fakes.FakeDeployment( + uuid='593b683c-4b16-4b2b-a56b-e162bd60f10b')) @mock.patch('os.path.exists', return_value=True) @mock.patch(MOD + 'fileutils.update_env_file') def test_deployment(self, mock_env, mock_path, mock_deployment, mock_symlink, mock_remove): - deploy_id = '593b683c-4b16-4b2b-a56b-e162bd60f10b' - endpoints = { - 'admin': { + deployment_id = mock_deployment.return_value["uuid"] + + mock_deployment.return_value["admin"] = { 'auth_url': 'fake_auth_url', 'username': 'fake_username', 'password': 'fake_password', 'tenant_name': 'fake_tenant_name', - 'region_name': None - } - } - mock_deployment.return_value = endpoints + 'region_name': None} + with mock.patch('rally.cmd.commands.use.open', mock.mock_open(), create=True) as mock_file: - self.use.deployment(deploy_id) + self.use.deployment(deployment_id) self.assertEqual(2, mock_path.call_count) mock_env.assert_called_once_with(os.path.expanduser( - '~/.rally/globals'), 'RALLY_DEPLOYMENT', '%s\n' % deploy_id) + '~/.rally/globals'), + 'RALLY_DEPLOYMENT', '%s\n' % deployment_id) mock_file.return_value.write.assert_called_once_with( 'export OS_AUTH_URL=fake_auth_url\n' 'export OS_USERNAME=fake_username\n' 'export OS_PASSWORD=fake_password\n' 'export OS_TENANT_NAME=fake_tenant_name\n') mock_symlink.assert_called_once_with( - os.path.expanduser('~/.rally/openrc-%s' % deploy_id), + os.path.expanduser('~/.rally/openrc-%s' % deployment_id), os.path.expanduser('~/.rally/openrc')) mock_remove.assert_called_once_with(os.path.expanduser( '~/.rally/openrc')) @mock.patch(MOD + 'db.deployment_get') def test_deployment_not_found(self, mock_deployment): - deploy_id = 'e87e4dca-b515-4477-888d-5f6103f13b42' + deployment_id = 'e87e4dca-b515-4477-888d-5f6103f13b42' mock_deployment.side_effect = exceptions.DeploymentNotFound( - uuid=deploy_id) - self.assertEqual(1, self.use.deployment(deploy_id)) + uuid=deployment_id) + self.assertEqual(1, self.use.deployment(deployment_id)) @mock.patch(MOD + 'fileutils._rewrite_env_file') @mock.patch(MOD + 'db.task_get', return_value=True) diff --git a/tests/unit/cmd/commands/test_verify.py b/tests/unit/cmd/commands/test_verify.py index cb68c63872..d3a00c03fe 100644 --- a/tests/unit/cmd/commands/test_verify.py +++ b/tests/unit/cmd/commands/test_verify.py @@ -47,17 +47,17 @@ class VerifyCommandsTestCase(test.TestCase): @mock.patch("rally.osclients.Clients") @mock.patch("rally.orchestrator.api.verify") def test_start(self, mock_verify, mock_clients): - deploy_id = "0fba91c6-82d5-4ce1-bd00-5d7c989552d9" + deployment_id = "0fba91c6-82d5-4ce1-bd00-5d7c989552d9" mock_clients().glance().images.list.return_value = [ self.image1, self.image2] mock_clients().nova().flavors.list.return_value = [ self.flavor1, self.flavor2] - self.verify.start(deploy_id=deploy_id) + self.verify.start(deployment=deployment_id) default_set_name = "smoke" default_regex = None - mock_verify.assert_called_once_with(deploy_id, + mock_verify.assert_called_once_with(deployment_id, default_set_name, default_regex, None) @@ -65,29 +65,29 @@ class VerifyCommandsTestCase(test.TestCase): @mock.patch("rally.orchestrator.api.verify") def test_start_with_user_specified_tempest_config(self, mock_verify, mock_clients): - deploy_id = "0fba91c6-82d5-4ce1-bd00-5d7c989552d9" + deployment_id = "0fba91c6-82d5-4ce1-bd00-5d7c989552d9" mock_clients().glance().images.list.return_value = [ self.image1, self.image2] mock_clients().nova().flavors.list.return_value = [ self.flavor1, self.flavor2] tempest_config = tempfile.NamedTemporaryFile() - self.verify.start(deploy_id=deploy_id, + self.verify.start(deployment=deployment_id, tempest_config=tempest_config.name) default_set_name = "smoke" default_regex = None - mock_verify.assert_called_once_with(deploy_id, + mock_verify.assert_called_once_with(deployment_id, default_set_name, default_regex, tempest_config.name) tempest_config.close() @mock.patch("rally.orchestrator.api.verify") def test_start_with_wrong_set_name(self, mock_verify): - deploy_id = "f2009aae-6ef3-468e-96b2-3c987d584010" + deployment_id = "f2009aae-6ef3-468e-96b2-3c987d584010" wrong_set_name = "unexpected_value" - self.verify.start(deploy_id, wrong_set_name) + self.verify.start(deployment_id, wrong_set_name) self.assertNotIn(wrong_set_name, consts.TEMPEST_TEST_SETS) self.assertFalse(mock_verify.called) diff --git a/tests/unit/cmd/test_envutils.py b/tests/unit/cmd/test_envutils.py index bf44447e37..237da6de17 100644 --- a/tests/unit/cmd/test_envutils.py +++ b/tests/unit/cmd/test_envutils.py @@ -40,11 +40,11 @@ class EnvUtilsTestCase(test.TestCase): "Missing argument: --test_missing_arg\n") @mock.patch.dict(os.environ, - values={envutils.ENV_DEPLOYMENT: 'my_deploy_id'}, + values={envutils.ENV_DEPLOYMENT: 'my_deployment_id'}, clear=True) def test_get_deployment_id_in_env(self): - deploy_id = envutils.get_global(envutils.ENV_DEPLOYMENT) - self.assertEqual('my_deploy_id', deploy_id) + deployment_id = envutils.get_global(envutils.ENV_DEPLOYMENT) + self.assertEqual('my_deployment_id', deployment_id) @mock.patch.dict(os.environ, values={}, clear=True) @mock.patch('rally.cmd.envutils.fileutils.load_env_file') diff --git a/tests/unit/cmd/test_manage.py b/tests/unit/cmd/test_manage.py index eaffdac666..04804ec2a5 100644 --- a/tests/unit/cmd/test_manage.py +++ b/tests/unit/cmd/test_manage.py @@ -51,9 +51,11 @@ class TempestCommandsTestCase(test.TestCase): self.tempest_commands = manage.TempestCommands() self.tempest = mock.Mock() - @mock.patch('rally.verification.verifiers.tempest.tempest.Tempest') - def test_install(self, mock_tempest): - deploy_id = 'e24b5af0-0e2a-4a70-9443-b30a88ab152e' + @mock.patch("rally.cmd.manage.db.deployment_get", + return_value={"uuid": "e24b5af0-0e2a-4a70-9443-b30a88ab152e"}) + @mock.patch("rally.verification.verifiers.tempest.tempest.Tempest") + def test_install(self, mock_tempest, mock_d_get): + deployment_id = mock_d_get.return_value["uuid"] mock_tempest.return_value = self.tempest - self.tempest_commands.install(deploy_id) + self.tempest_commands.install(deployment_id) self.tempest.install.assert_called_once_with() diff --git a/tests/unit/orchestrator/test_api.py b/tests/unit/orchestrator/test_api.py index 65328d8c6f..7d0155ec2a 100644 --- a/tests/unit/orchestrator/test_api.py +++ b/tests/unit/orchestrator/test_api.py @@ -22,6 +22,7 @@ import mock from rally import consts from rally import exceptions from rally.orchestrator import api +from tests.unit import fakes from tests.unit import test @@ -70,12 +71,12 @@ class APITestCase(test.TestCase): @mock.patch("rally.orchestrator.api.objects.Task") @mock.patch("rally.orchestrator.api.objects.Deployment.get", - return_value={"uuid": "deploy_uuid", - "admin": mock.MagicMock(), - "users": []}) + return_value=fakes.FakeDeployment(uuid="deploy_uuid", + admin=mock.MagicMock(), + users=[])) @mock.patch("rally.orchestrator.api.engine.BenchmarkEngine") def test_task_validate(self, mock_engine, mock_deployment_get, mock_task): - api.task_validate(self.deploy_uuid, "config") + api.task_validate(mock_deployment_get.return_value['uuid'], "config") mock_engine.assert_has_calls([ mock.call("config", mock_task.return_value), @@ -84,25 +85,29 @@ class APITestCase(test.TestCase): mock.call().validate(), ]) - mock_task.assert_called_once_with(deployment_uuid=self.deploy_uuid) - mock_deployment_get.assert_called_once_with(self.deploy_uuid) + mock_task.assert_called_once_with( + deployment_uuid=mock_deployment_get.return_value["uuid"]) + mock_deployment_get.assert_called_once_with( + mock_deployment_get.return_value["uuid"]) + @mock.patch("rally.objects.Deployment.get", + return_value={'uuid': 'b0d9cd6c-2c94-4417-a238-35c7019d0257'}) @mock.patch("rally.objects.Task") - def test_create_task(self, mock_task): - deployment_uuid = "b0d9cd6c-2c94-4417-a238-35c7019d0257" + def test_create_task(self, mock_task, mock_d_get): tag = "a" - api.create_task(deployment_uuid, tag) - mock_task.assert_called_once_with(deployment_uuid=deployment_uuid, - tag=tag) + api.create_task(mock_d_get.return_value["uuid"], tag) + mock_task.assert_called_once_with( + deployment_uuid=mock_d_get.return_value["uuid"], tag=tag) @mock.patch("rally.orchestrator.api.objects.Task") @mock.patch("rally.orchestrator.api.objects.Deployment.get", - return_value={"uuid": "deploy_uuid", - "admin": mock.MagicMock(), - "users": []}) + return_value=fakes.FakeDeployment(uuid="deploy_uuid", + admin=mock.MagicMock(), + users=[])) @mock.patch("rally.orchestrator.api.engine.BenchmarkEngine") def test_start_task(self, mock_engine, mock_deployment_get, mock_task): - api.start_task(self.deploy_uuid, "config") + + api.start_task(mock_deployment_get.return_value["uuid"], "config") mock_engine.assert_has_calls([ mock.call("config", mock_task.return_value), @@ -112,8 +117,10 @@ class APITestCase(test.TestCase): mock.call().run(), ]) - mock_task.assert_called_once_with(deployment_uuid=self.deploy_uuid) - mock_deployment_get.assert_called_once_with(self.deploy_uuid) + mock_task.assert_called_once_with( + deployment_uuid=mock_deployment_get.return_value["uuid"]) + mock_deployment_get.assert_called_once_with( + mock_deployment_get.return_value["uuid"]) @mock.patch("rally.orchestrator.api.objects.Task") @mock.patch("rally.orchestrator.api.objects.Deployment.get") @@ -184,6 +191,16 @@ class APITestCase(test.TestCase): self.deploy_uuid, {'status': consts.DeployStatus.DEPLOY_FAILED}) + @mock.patch("rally.orchestrator.api.LOG") + @mock.patch("rally.objects.deploy.db.deployment_create", + side_effect=exceptions.DeploymentNameExists( + deployment='fake_deploy')) + def test_create_deploy_duplication_error(self, mock_d_create, + mock_log): + + self.assertRaises(exceptions.DeploymentNameExists, + api.create_deploy, self.deploy_config, "fake_deploy") + @mock.patch("rally.objects.deploy.db.deployment_delete") @mock.patch("rally.objects.deploy.db.deployment_update") @mock.patch("rally.objects.deploy.db.deployment_get") @@ -205,9 +222,12 @@ class APITestCase(test.TestCase): mock.call(self.deploy_uuid, self.endpoints) ]) + @mock.patch("rally.objects.Deployment.get") @mock.patch("rally.orchestrator.api.objects.Verification") @mock.patch("rally.verification.verifiers.tempest.tempest.Tempest") - def test_verify(self, mock_tempest, mock_verification): + def test_verify(self, mock_tempest, mock_verification, mock_d_get): + mock_d_get.return_value = {"uuid": self.deploy_uuid} + mock_tempest.return_value = self.tempest self.tempest.is_installed.return_value = True api.verify(self.deploy_uuid, "smoke", None, None) @@ -216,10 +236,12 @@ class APITestCase(test.TestCase): self.tempest.verify.assert_called_once_with(set_name="smoke", regex=None) + @mock.patch("rally.orchestrator.api.objects.Deployment.get") @mock.patch("rally.orchestrator.api.objects.Verification") @mock.patch("rally.verification.verifiers.tempest.tempest.Tempest") def test_verify_tempest_not_installed(self, mock_tempest, - mock_verification): + mock_verification, mock_d_get): + mock_d_get.return_value = {"uuid": self.deploy_uuid} mock_tempest.return_value = self.tempest self.tempest.is_installed.return_value = False api.verify(self.deploy_uuid, "smoke", None, None) diff --git a/tests/unit/verification/verifiers/test_config.py b/tests/unit/verification/verifiers/test_config.py index f6135b1923..4c95d67962 100644 --- a/tests/unit/verification/verifiers/test_config.py +++ b/tests/unit/verification/verifiers/test_config.py @@ -42,8 +42,8 @@ class ConfigTestCase(test.TestCase): "auth_url": "http://test/v2.0", "permission": "admin"} mock_get.return_value = {"admin": self.endpoint} - self.deploy_id = "fake_deploy_id" - self.conf_generator = config.TempestConf(self.deploy_id) + self.deployment = "fake_deployment" + self.conf_generator = config.TempestConf(self.deployment) self.conf_generator.clients.services = mock_services keystone_patcher = mock.patch("rally.osclients.create_keystone_client") @@ -212,7 +212,7 @@ class ConfigTestCase(test.TestCase): def test__set_default(self, mock_makedirs, mock_exists): self.conf_generator._set_default() lock_path = os.path.join(self.conf_generator.data_path, "lock_files_%s" - % self.deploy_id) + % self.deployment) mock_makedirs.assert_called_once_with(lock_path) expected = (("debug", "True"), ("log_file", "tempest.log"), ("use_stderr", "False"), diff --git a/tests/unit/verification/verifiers/test_tempest.py b/tests/unit/verification/verifiers/test_tempest.py index eb4e274187..3c7da0710f 100644 --- a/tests/unit/verification/verifiers/test_tempest.py +++ b/tests/unit/verification/verifiers/test_tempest.py @@ -34,7 +34,7 @@ TEMPEST_PATH = "rally.verification.verifiers.tempest" class BaseTestCase(test.TestCase): def setUp(self): super(BaseTestCase, self).setUp() - self.verifier = tempest.Tempest('fake_deploy_id', + self.verifier = tempest.Tempest('fake_deployment_id', verification=mock.MagicMock()) self.verifier._path = "/tmp" @@ -268,7 +268,7 @@ class TempestVerifyTestCase(BaseTestCase): self.verifier.verify(set_name, None) self.assertEqual(2, mock_is_configured.call_count) - mock_conf.assert_called_once_with(self.verifier.deploy_id) + mock_conf.assert_called_once_with(self.verifier.deployment) mock_conf().generate.assert_called_once_with(self.verifier.config_file) self.verifier.verification.start_verifying.assert_called_once_with( set_name) diff --git a/tools/rally.bash_completion b/tools/rally.bash_completion index 9bce6982bf..eae07cdfa1 100644 --- a/tools/rally.bash_completion +++ b/tools/rally.bash_completion @@ -12,7 +12,7 @@ _rally() OPTS["info_ServerProviders"]="" OPTS["info_find"]="--query" OPTS["info_list"]="" - OPTS["use_deployment"]="--uuid --name" + OPTS["use_deployment"]="--deployment" OPTS["use_task"]="--uuid" OPTS["use_verification"]="--uuid" OPTS["task_abort"]="--uuid" @@ -23,27 +23,27 @@ _rally() OPTS["task_report"]="--uuid --out --open" OPTS["task_results"]="--uuid" OPTS["task_sla_check"]="--uuid --json" - OPTS["task_start"]="--deploy-id --task --tag --no-use" + OPTS["task_start"]="--deployment --task --tag --no-use" OPTS["task_status"]="--uuid" - OPTS["task_validate"]="--deploy-id --task" - OPTS["show_flavors"]="--deploy-id" - OPTS["show_images"]="--deploy-id" - OPTS["show_keypairs"]="--deploy-id" - OPTS["show_networks"]="--deploy-id" - OPTS["show_secgroups"]="--deploy-id" + OPTS["task_validate"]="--deployment --task" + OPTS["show_flavors"]="--deployment" + OPTS["show_images"]="--deployment" + OPTS["show_keypairs"]="--deployment" + OPTS["show_networks"]="--deployment" + OPTS["show_secgroups"]="--deployment" OPTS["verify_compare"]="--uuid-1 --uuid-2 --csv --html --json --output-file --threshold" OPTS["verify_detailed"]="--uuid --sort-by" OPTS["verify_list"]="" OPTS["verify_results"]="--uuid --html --json --output-file" OPTS["verify_show"]="--uuid --sort-by --detailed" - OPTS["verify_start"]="--deploy-id --set --regex --tempest-config --no-use" - OPTS["deployment_check"]="--uuid" - OPTS["deployment_config"]="--uuid" + OPTS["verify_start"]="--deployment --set --regex --tempest-config --no-use" + OPTS["deployment_check"]="--deployment" + OPTS["deployment_config"]="--deployment" OPTS["deployment_create"]="--name --fromenv --filename --no-use" - OPTS["deployment_destroy"]="--uuid" + OPTS["deployment_destroy"]="--deployment" OPTS["deployment_list"]="" - OPTS["deployment_recreate"]="--uuid" - OPTS["deployment_show"]="--uuid" + OPTS["deployment_recreate"]="--deployment" + OPTS["deployment_show"]="--deployment" for OPT in ${!OPTS[*]} ; do @@ -75,4 +75,4 @@ _rally() fi return 0 } -complete -F _rally rally +complete -F _rally rally \ No newline at end of file