9093275886
rally.plugins.openstack -> rally_openstack - rally_openstack.context -> rally_openstack.contexts rally.plugins.workloads -> rally_openstack/workloads rally.consts -> rally_openstack.consts TODO: fix pep8
134 lines
4.9 KiB
Python
134 lines
4.9 KiB
Python
# Copyright 2014: 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.common import cfg
|
|
from rally.task import utils
|
|
|
|
CONF = cfg.CONF
|
|
|
|
cleanup_group = cfg.OptGroup(name="cleanup", title="Cleanup Options")
|
|
|
|
|
|
# NOTE(andreykurilin): There are cases when there is no way to use any kind
|
|
# of "name" for resource as an identifier of alignment resource to the
|
|
# particular task run and even to Rally itself. Previously, we used empty
|
|
# strings as a workaround for name matching specific templates, but
|
|
# theoretically such behaviour can hide other cases when resource should have
|
|
# a name property, but it is missed.
|
|
# Let's use instances of specific class to return as a name of resources
|
|
# which do not have names at all.
|
|
class NoName(object):
|
|
def __init__(self, resource_type):
|
|
self.resource_type = resource_type
|
|
|
|
def __repr__(self):
|
|
return "<NoName %s resource>" % self.resource_type
|
|
|
|
|
|
def resource(service, resource, order=0, admin_required=False,
|
|
perform_for_admin_only=False, tenant_resource=False,
|
|
max_attempts=3, timeout=CONF.openstack.resource_deletion_timeout,
|
|
interval=1, threads=CONF.openstack.cleanup_threads):
|
|
"""Decorator that overrides resource specification.
|
|
|
|
Just put it on top of your resource class and specify arguments that you
|
|
need.
|
|
|
|
:param service: It is equal to client name for corresponding service.
|
|
E.g. "nova", "cinder" or "zaqar"
|
|
:param resource: Client manager name for resource. E.g. in case of
|
|
nova.servers you should write here "servers"
|
|
:param order: Used to adjust priority of cleanup for different resource
|
|
types
|
|
:param admin_required: Admin user is required
|
|
:param perform_for_admin_only: Perform cleanup for admin user only
|
|
:param tenant_resource: Perform deletion only 1 time per tenant
|
|
:param max_attempts: Max amount of attempts to delete single resource
|
|
:param timeout: Max duration of deletion in seconds
|
|
:param interval: Resource status pooling interval
|
|
:param threads: Amount of threads (workers) that are deleting resources
|
|
simultaneously
|
|
"""
|
|
|
|
def inner(cls):
|
|
# TODO(boris-42): This can be written better I believe =)
|
|
cls._service = service
|
|
cls._resource = resource
|
|
cls._order = order
|
|
cls._admin_required = admin_required
|
|
cls._perform_for_admin_only = perform_for_admin_only
|
|
cls._max_attempts = max_attempts
|
|
cls._timeout = timeout
|
|
cls._interval = interval
|
|
cls._threads = threads
|
|
cls._tenant_resource = tenant_resource
|
|
|
|
return cls
|
|
|
|
return inner
|
|
|
|
|
|
@resource(service=None, resource=None)
|
|
class ResourceManager(object):
|
|
"""Base class for cleanup plugins for specific resources.
|
|
|
|
You should use @resource decorator to specify major configuration of
|
|
resource manager. Usually you should specify: service, resource and order.
|
|
|
|
If project python client is very specific, you can override delete(),
|
|
list() and is_deleted() methods to make them fit to your case.
|
|
"""
|
|
|
|
def __init__(self, resource=None, admin=None, user=None, tenant_uuid=None):
|
|
self.admin = admin
|
|
self.user = user
|
|
self.raw_resource = resource
|
|
self.tenant_uuid = tenant_uuid
|
|
|
|
def _manager(self):
|
|
client = self._admin_required and self.admin or self.user
|
|
return getattr(getattr(client, self._service)(), self._resource)
|
|
|
|
def id(self):
|
|
"""Returns id of resource."""
|
|
return self.raw_resource.id
|
|
|
|
def name(self):
|
|
"""Returns name of resource."""
|
|
return self.raw_resource.name
|
|
|
|
def is_deleted(self):
|
|
"""Checks if the resource is deleted.
|
|
|
|
Fetch resource by id from service and check it status.
|
|
In case of NotFound or status is DELETED or DELETE_COMPLETE returns
|
|
True, otherwise False.
|
|
"""
|
|
try:
|
|
resource = self._manager().get(self.id())
|
|
except Exception as e:
|
|
return getattr(e, "code", getattr(e, "http_status", 400)) == 404
|
|
|
|
return utils.get_status(resource) in ("DELETED", "DELETE_COMPLETE")
|
|
|
|
def delete(self):
|
|
"""Delete resource that corresponds to instance of this class."""
|
|
self._manager().delete(self.id())
|
|
|
|
def list(self):
|
|
"""List all resources specific for admin or user."""
|
|
return self._manager().list()
|