Get rid of TaskDetails in favor of TaskStub
Change I0b406e4662cfd3cb496b71be77ad10a90c178baa introduces a new class TaskStub. This class is designed to be a subset of what a task is in the domain layer: it doesn't contain input, message and result. TaskStub should be used when listing tasks in order to avoid extra-overhead of transporting these text fields. As a result, the TaskDetails introduced by change I0b406e4662cfd3cb496b71be77ad10a90c178baa doesn't need to exist. With this patch, the domain layer contains Task and TaskStub instead of Task, TaskStub and TaskDetails. partially implements bp async-glance-workers Change-Id: I2a20b0c5033c6920749370355c2d672dec707c28
This commit is contained in:
parent
2c0d214a18
commit
7f512fd0ac
|
@ -67,6 +67,17 @@ def is_task_mutable(context, task):
|
|||
return task.owner == context.owner
|
||||
|
||||
|
||||
def is_task_stub_mutable(context, task_stub):
|
||||
"""Return True if the task stub is mutable in this context."""
|
||||
if context.is_admin:
|
||||
return True
|
||||
|
||||
if context.owner is None:
|
||||
return False
|
||||
|
||||
return task_stub.owner == context.owner
|
||||
|
||||
|
||||
def proxy_task(context, task):
|
||||
if is_task_mutable(context, task):
|
||||
return task
|
||||
|
@ -74,11 +85,11 @@ def proxy_task(context, task):
|
|||
return ImmutableTaskProxy(task)
|
||||
|
||||
|
||||
def proxy_task_details(context, task, task_details):
|
||||
if is_task_mutable(context, task):
|
||||
return task_details
|
||||
def proxy_task_stub(context, task_stub):
|
||||
if is_task_stub_mutable(context, task_stub):
|
||||
return task_stub
|
||||
else:
|
||||
return ImmutableTaskDetailsProxy(task_details)
|
||||
return ImmutableTaskStubProxy(task_stub)
|
||||
|
||||
|
||||
class ImageRepoProxy(glance.domain.proxy.Repo):
|
||||
|
@ -342,6 +353,9 @@ class ImmutableTaskProxy(object):
|
|||
expires_at = _immutable_attr('base', 'expires_at')
|
||||
created_at = _immutable_attr('base', 'created_at')
|
||||
updated_at = _immutable_attr('base', 'updated_at')
|
||||
input = _immutable_attr('base', 'input')
|
||||
message = _immutable_attr('base', 'message')
|
||||
result = _immutable_attr('base', 'result')
|
||||
|
||||
def run(self, executor):
|
||||
self.base.run(executor)
|
||||
|
@ -359,13 +373,18 @@ class ImmutableTaskProxy(object):
|
|||
raise exception.Forbidden(message)
|
||||
|
||||
|
||||
class ImmutableTaskDetailsProxy(object):
|
||||
class ImmutableTaskStubProxy(object):
|
||||
def __init__(self, base):
|
||||
self.base = base
|
||||
self.resource_name = 'task stub'
|
||||
|
||||
input = _immutable_attr('base', 'input')
|
||||
message = _immutable_attr('base', 'message')
|
||||
result = _immutable_attr('base', 'result')
|
||||
task_id = _immutable_attr('base', 'task_id')
|
||||
type = _immutable_attr('base', 'type')
|
||||
status = _immutable_attr('base', 'status')
|
||||
owner = _immutable_attr('base', 'owner')
|
||||
expires_at = _immutable_attr('base', 'expires_at')
|
||||
created_at = _immutable_attr('base', 'created_at')
|
||||
updated_at = _immutable_attr('base', 'updated_at')
|
||||
|
||||
|
||||
class ImageProxy(glance.domain.proxy.Image):
|
||||
|
@ -391,13 +410,6 @@ class TaskProxy(glance.domain.proxy.Task):
|
|||
super(TaskProxy, self).__init__(task)
|
||||
|
||||
|
||||
class TaskDetailsProxy(glance.domain.proxy.TaskDetails):
|
||||
|
||||
def __init__(self, task_details):
|
||||
self.task_details = task_details
|
||||
super(TaskDetailsProxy, self).__init__(task_details)
|
||||
|
||||
|
||||
class TaskFactoryProxy(glance.domain.proxy.TaskFactory):
|
||||
|
||||
def __init__(self, task_factory, context):
|
||||
|
@ -405,8 +417,7 @@ class TaskFactoryProxy(glance.domain.proxy.TaskFactory):
|
|||
self.context = context
|
||||
super(TaskFactoryProxy, self).__init__(
|
||||
task_factory,
|
||||
task_proxy_class=TaskProxy,
|
||||
task_details_proxy_class=TaskDetailsProxy)
|
||||
task_proxy_class=TaskProxy)
|
||||
|
||||
def new_task(self, **kwargs):
|
||||
owner = kwargs.get('owner', self.context.owner)
|
||||
|
@ -429,12 +440,18 @@ class TaskRepoProxy(glance.domain.proxy.TaskRepo):
|
|||
self.context = context
|
||||
super(TaskRepoProxy, self).__init__(task_repo)
|
||||
|
||||
def get_task_stub_and_details(self, task_id):
|
||||
task, task_details = self.task_repo.get_task_stub_and_details(task_id)
|
||||
return proxy_task(self.context, task), proxy_task_details(self.context,
|
||||
task,
|
||||
task_details)
|
||||
def get(self, task_id):
|
||||
task = self.task_repo.get(task_id)
|
||||
return proxy_task(self.context, task)
|
||||
|
||||
def list_tasks(self, *args, **kwargs):
|
||||
tasks = self.task_repo.list_tasks(*args, **kwargs)
|
||||
return [proxy_task(self.context, t) for t in tasks]
|
||||
|
||||
class TaskStubRepoProxy(glance.domain.proxy.TaskStubRepo):
|
||||
|
||||
def __init__(self, task_stub_repo, context):
|
||||
self.task_stub_repo = task_stub_repo
|
||||
self.context = context
|
||||
super(TaskStubRepoProxy, self).__init__(task_stub_repo)
|
||||
|
||||
def list(self, *args, **kwargs):
|
||||
task_stubs = self.task_stub_repo.list(*args, **kwargs)
|
||||
return [proxy_task_stub(self.context, t) for t in task_stubs]
|
||||
|
|
|
@ -353,17 +353,14 @@ class TaskProxy(glance.domain.proxy.Task):
|
|||
self.policy = policy
|
||||
super(TaskProxy, self).__init__(task)
|
||||
|
||||
def run(self, executor):
|
||||
self.base.run(executor)
|
||||
|
||||
class TaskStubProxy(glance.domain.proxy.TaskStub):
|
||||
|
||||
class TaskDetailsProxy(glance.domain.proxy.TaskDetails):
|
||||
|
||||
def __init__(self, task_details, context, policy):
|
||||
self.task_details = task_details
|
||||
def __init__(self, task_stub, context, policy):
|
||||
self.task_stub = task_stub
|
||||
self.context = context
|
||||
self.policy = policy
|
||||
super(TaskDetailsProxy, self).__init__(task_details)
|
||||
super(TaskStubProxy, self).__init__(task_stub)
|
||||
|
||||
|
||||
class TaskRepoProxy(glance.domain.proxy.TaskRepo):
|
||||
|
@ -376,25 +373,36 @@ class TaskRepoProxy(glance.domain.proxy.TaskRepo):
|
|||
super(TaskRepoProxy,
|
||||
self).__init__(task_repo,
|
||||
task_proxy_class=TaskProxy,
|
||||
task_proxy_kwargs=proxy_kwargs,
|
||||
task_details_proxy_class=TaskDetailsProxy,
|
||||
task_details_proxy_kwargs=proxy_kwargs)
|
||||
task_proxy_kwargs=proxy_kwargs)
|
||||
|
||||
def get_task_stub_and_details(self, task_id):
|
||||
def get(self, task_id):
|
||||
self.policy.enforce(self.context, 'get_task', {})
|
||||
return super(TaskRepoProxy, self).get_task_stub_and_details(task_id)
|
||||
return super(TaskRepoProxy, self).get(task_id)
|
||||
|
||||
def list_tasks(self, *args, **kwargs):
|
||||
self.policy.enforce(self.context, 'get_tasks', {})
|
||||
return super(TaskRepoProxy, self).list_tasks(*args, **kwargs)
|
||||
|
||||
def add(self, task, task_details=None):
|
||||
def add(self, task):
|
||||
self.policy.enforce(self.context, 'add_task', {})
|
||||
super(TaskRepoProxy, self).add(task, task_details)
|
||||
super(TaskRepoProxy, self).add(task)
|
||||
|
||||
def save(self, task, task_details=None):
|
||||
def save(self, task):
|
||||
self.policy.enforce(self.context, 'modify_task', {})
|
||||
super(TaskRepoProxy, self).save(task, task_details)
|
||||
super(TaskRepoProxy, self).save(task)
|
||||
|
||||
|
||||
class TaskStubRepoProxy(glance.domain.proxy.TaskStubRepo):
|
||||
|
||||
def __init__(self, task_stub_repo, context, task_policy):
|
||||
self.context = context
|
||||
self.policy = task_policy
|
||||
self.task_stub_repo = task_stub_repo
|
||||
proxy_kwargs = {'context': self.context, 'policy': self.policy}
|
||||
super(TaskStubRepoProxy,
|
||||
self).__init__(task_stub_repo,
|
||||
task_stub_proxy_class=TaskStubProxy,
|
||||
task_stub_proxy_kwargs=proxy_kwargs)
|
||||
|
||||
def list(self, *args, **kwargs):
|
||||
self.policy.enforce(self.context, 'get_tasks', {})
|
||||
return super(TaskStubRepoProxy, self).list(*args, **kwargs)
|
||||
|
||||
|
||||
class TaskFactoryProxy(glance.domain.proxy.TaskFactory):
|
||||
|
@ -407,6 +415,4 @@ class TaskFactoryProxy(glance.domain.proxy.TaskFactory):
|
|||
super(TaskFactoryProxy, self).__init__(
|
||||
task_factory,
|
||||
task_proxy_class=TaskProxy,
|
||||
task_proxy_kwargs=proxy_kwargs,
|
||||
task_details_proxy_class=TaskDetailsProxy,
|
||||
task_details_proxy_kwargs=proxy_kwargs)
|
||||
task_proxy_kwargs=proxy_kwargs)
|
||||
|
|
|
@ -56,20 +56,17 @@ class TasksController(object):
|
|||
task_repo = self.gateway.get_task_repo(req.context)
|
||||
live_time = CONF.task.task_time_to_live
|
||||
try:
|
||||
new_task = task_factory.new_task_stub(task_type=task['type'],
|
||||
owner=req.context.owner,
|
||||
task_time_to_live=live_time)
|
||||
new_task_details = task_factory.new_task_details(new_task.task_id,
|
||||
task['input'])
|
||||
task_repo.add(new_task, new_task_details)
|
||||
new_task = task_factory.new_task(task_type=task['type'],
|
||||
owner=req.context.owner,
|
||||
task_time_to_live=live_time,
|
||||
task_input=task['input'])
|
||||
task_repo.add(new_task)
|
||||
except exception.Forbidden as e:
|
||||
msg = (_("Forbidden to create task. Reason: %(reason)s")
|
||||
% {'reason': unicode(e)})
|
||||
LOG.info(msg)
|
||||
raise webob.exc.HTTPForbidden(explanation=e.msg)
|
||||
|
||||
result = {'task': new_task, 'task_details': new_task_details}
|
||||
return result
|
||||
return new_task
|
||||
|
||||
def index(self, req, marker=None, limit=None, sort_key='created_at',
|
||||
sort_dir='desc', filters=None):
|
||||
|
@ -82,13 +79,10 @@ class TasksController(object):
|
|||
limit = CONF.limit_param_default
|
||||
limit = min(CONF.api_limit_max, limit)
|
||||
|
||||
task_repo = self.gateway.get_task_repo(req.context)
|
||||
task_repo = self.gateway.get_task_stub_repo(req.context)
|
||||
try:
|
||||
tasks = task_repo.list_tasks(marker,
|
||||
limit,
|
||||
sort_key,
|
||||
sort_dir,
|
||||
filters)
|
||||
tasks = task_repo.list(marker, limit, sort_key,
|
||||
sort_dir, filters)
|
||||
if len(tasks) != 0 and len(tasks) == limit:
|
||||
result['next_marker'] = tasks[-1].task_id
|
||||
except (exception.NotFound, exception.InvalidSortKey,
|
||||
|
@ -104,7 +98,7 @@ class TasksController(object):
|
|||
def get(self, req, task_id):
|
||||
try:
|
||||
task_repo = self.gateway.get_task_repo(req.context)
|
||||
task, task_details = task_repo.get_task_stub_and_details(task_id)
|
||||
task = task_repo.get(task_id)
|
||||
except exception.NotFound as e:
|
||||
msg = (_("Failed to find task %(task_id)s. Reason: %(reason)s") %
|
||||
{'task_id': task_id, 'reason': unicode(e)})
|
||||
|
@ -115,8 +109,7 @@ class TasksController(object):
|
|||
{'task_id': task_id, 'reason': unicode(e)})
|
||||
LOG.info(msg)
|
||||
raise webob.exc.HTTPForbidden(explanation=e.msg)
|
||||
result = {'task': task, 'task_details': task_details}
|
||||
return result
|
||||
return task
|
||||
|
||||
def delete(self, req, task_id):
|
||||
msg = (_("This operation is currently not permitted on Glance Tasks. "
|
||||
|
@ -238,16 +231,15 @@ class ResponseSerializer(wsgi.JSONResponseSerializer):
|
|||
def _get_task_location(self, task):
|
||||
return '/v2/tasks/%s' % task.task_id
|
||||
|
||||
def _format_task(self, schema, task, task_details=None):
|
||||
def _format_task(self, schema, task):
|
||||
task_view = {}
|
||||
task_attributes = ['type', 'status', 'owner']
|
||||
task_details_attributes = ['input', 'result', 'message']
|
||||
for key in task_attributes:
|
||||
task_view[key] = getattr(task, key)
|
||||
if task_details:
|
||||
for key in task_details_attributes:
|
||||
task_view[key] = getattr(task_details, key)
|
||||
task_view['id'] = task.task_id
|
||||
task_view['input'] = task.task_input
|
||||
task_view['type'] = task.type
|
||||
task_view['status'] = task.status
|
||||
task_view['owner'] = task.owner
|
||||
task_view['message'] = task.message
|
||||
task_view['result'] = task.result
|
||||
if task.expires_at:
|
||||
task_view['expires_at'] = timeutils.isotime(task.expires_at)
|
||||
task_view['created_at'] = timeutils.isotime(task.created_at)
|
||||
|
@ -257,20 +249,28 @@ class ResponseSerializer(wsgi.JSONResponseSerializer):
|
|||
task_view = schema.filter(task_view) # domain
|
||||
return task_view
|
||||
|
||||
def create(self, response, result):
|
||||
def _format_task_stub(self, schema, task):
|
||||
task_view = {}
|
||||
task_view['id'] = task.task_id
|
||||
task_view['type'] = task.type
|
||||
task_view['status'] = task.status
|
||||
task_view['owner'] = task.owner
|
||||
if task.expires_at:
|
||||
task_view['expires_at'] = timeutils.isotime(task.expires_at)
|
||||
task_view['created_at'] = timeutils.isotime(task.created_at)
|
||||
task_view['updated_at'] = timeutils.isotime(task.updated_at)
|
||||
task_view['self'] = self._get_task_location(task)
|
||||
task_view['schema'] = '/v2/schemas/task'
|
||||
task_view = schema.filter(task_view) # domain
|
||||
return task_view
|
||||
|
||||
def create(self, response, task):
|
||||
response.status_int = 201
|
||||
task = result['task']
|
||||
task_details = result['task_details']
|
||||
self._inject_location_header(response, task)
|
||||
self._get(response, task, task_details)
|
||||
self.get(response, task)
|
||||
|
||||
def get(self, response, result):
|
||||
task = result['task']
|
||||
task_details = result['task_details']
|
||||
self._get(response, task, task_details)
|
||||
|
||||
def _get(self, response, task, task_details):
|
||||
task_view = self._format_task(self.task_schema, task, task_details)
|
||||
def get(self, response, task):
|
||||
task_view = self._format_task(self.task_schema, task)
|
||||
body = json.dumps(task_view, ensure_ascii=False)
|
||||
response.unicode_body = unicode(body)
|
||||
response.content_type = 'application/json'
|
||||
|
@ -280,7 +280,7 @@ class ResponseSerializer(wsgi.JSONResponseSerializer):
|
|||
params.pop('marker', None)
|
||||
query = urlparse.urlencode(params)
|
||||
body = {
|
||||
'tasks': [self._format_task(self.partial_task_schema, task)
|
||||
'tasks': [self._format_task_stub(self.partial_task_schema, task)
|
||||
for task in result['tasks']],
|
||||
'first': '/v2/tasks',
|
||||
'schema': '/v2/schemas/tasks',
|
||||
|
|
|
@ -290,6 +290,20 @@ class TaskRepo(object):
|
|||
self.context = context
|
||||
self.db_api = db_api
|
||||
|
||||
def _format_task_from_db(self, db_task):
|
||||
return glance.domain.Task(
|
||||
task_id=db_task['id'],
|
||||
task_type=db_task['type'],
|
||||
status=db_task['status'],
|
||||
owner=db_task['owner'],
|
||||
expires_at=db_task['expires_at'],
|
||||
created_at=db_task['created_at'],
|
||||
updated_at=db_task['updated_at'],
|
||||
task_input=db_task['input'],
|
||||
result=db_task['result'],
|
||||
message=db_task['message'],
|
||||
)
|
||||
|
||||
def _format_task_stub_from_db(self, db_task):
|
||||
return glance.domain.TaskStub(
|
||||
task_id=db_task['id'],
|
||||
|
@ -301,50 +315,30 @@ class TaskRepo(object):
|
|||
updated_at=db_task['updated_at'],
|
||||
)
|
||||
|
||||
def _format_task_details_from_db(self, db_task):
|
||||
return glance.domain.TaskDetails(
|
||||
task_id=db_task['id'],
|
||||
task_input=db_task['input'],
|
||||
result=db_task['result'],
|
||||
message=db_task['message'],
|
||||
)
|
||||
|
||||
def _format_task_stub_and_details_to_db(self, task, task_details=None):
|
||||
def _format_task_to_db(self, task):
|
||||
task = {'id': task.task_id,
|
||||
'type': task.type,
|
||||
'status': task.status,
|
||||
'input': None,
|
||||
'result': None,
|
||||
'input': task.task_input,
|
||||
'result': task.result,
|
||||
'owner': task.owner,
|
||||
'message': None,
|
||||
'message': task.message,
|
||||
'expires_at': task.expires_at,
|
||||
'created_at': task.created_at,
|
||||
'updated_at': task.updated_at}
|
||||
|
||||
if task_details is not None:
|
||||
task.update({
|
||||
'input': task_details.input,
|
||||
'result': task_details.result,
|
||||
'message': task_details.message,
|
||||
})
|
||||
|
||||
'updated_at': task.updated_at,
|
||||
}
|
||||
return task
|
||||
|
||||
def get_task_stub_and_details(self, task_id):
|
||||
def get(self, task_id):
|
||||
try:
|
||||
db_api_task = self.db_api.task_get(self.context, task_id)
|
||||
except (exception.NotFound, exception.Forbidden):
|
||||
msg = _('Could not find task %s') % task_id
|
||||
raise exception.NotFound(msg)
|
||||
return (self._format_task_stub_from_db(db_api_task),
|
||||
self._format_task_details_from_db(db_api_task))
|
||||
return self._format_task_from_db(db_api_task)
|
||||
|
||||
def list_tasks(self,
|
||||
marker=None,
|
||||
limit=None,
|
||||
sort_key='created_at',
|
||||
sort_dir='desc',
|
||||
filters=None):
|
||||
def list(self, marker=None, limit=None, sort_key='created_at',
|
||||
sort_dir='desc', filters=None):
|
||||
db_api_tasks = self.db_api.task_get_all(self.context,
|
||||
filters=filters,
|
||||
marker=marker,
|
||||
|
@ -353,9 +347,8 @@ class TaskRepo(object):
|
|||
sort_dir=sort_dir)
|
||||
return [self._format_task_stub_from_db(task) for task in db_api_tasks]
|
||||
|
||||
def save(self, task, task_details=None):
|
||||
task_values = self._format_task_stub_and_details_to_db(task,
|
||||
task_details)
|
||||
def save(self, task):
|
||||
task_values = self._format_task_to_db(task)
|
||||
try:
|
||||
updated_values = self.db_api.task_update(self.context,
|
||||
task.task_id,
|
||||
|
@ -365,15 +358,14 @@ class TaskRepo(object):
|
|||
raise exception.NotFound(msg)
|
||||
task.updated_at = updated_values['updated_at']
|
||||
|
||||
def add(self, task, task_details=None):
|
||||
task_values = self._format_task_stub_and_details_to_db(task,
|
||||
task_details)
|
||||
def add(self, task):
|
||||
task_values = self._format_task_to_db(task)
|
||||
updated_values = self.db_api.task_create(self.context, task_values)
|
||||
task.created_at = updated_values['created_at']
|
||||
task.updated_at = updated_values['updated_at']
|
||||
|
||||
def remove(self, task):
|
||||
task_values = self._format_task_stub_and_details_to_db(task)
|
||||
task_values = self._format_task_to_db(task)
|
||||
try:
|
||||
self.db_api.task_update(self.context, task.task_id, task_values)
|
||||
updated_values = self.db_api.task_delete(self.context,
|
||||
|
|
|
@ -384,17 +384,19 @@ class Task(object):
|
|||
self._set_task_status(new_status)
|
||||
self.expires_at = timeutils.utcnow() + self._time_to_live
|
||||
|
||||
def run(self, executor):
|
||||
pass
|
||||
|
||||
|
||||
class TaskStub(object):
|
||||
|
||||
def __init__(self, task_id, task_type, status, owner,
|
||||
expires_at, created_at, updated_at, task_time_to_live=48):
|
||||
expires_at, created_at, updated_at):
|
||||
self.task_id = task_id
|
||||
self._status = status
|
||||
self.type = task_type
|
||||
self.owner = owner
|
||||
self.expires_at = expires_at
|
||||
self._time_to_live = datetime.timedelta(hours=task_time_to_live)
|
||||
self.created_at = created_at
|
||||
self.updated_at = updated_at
|
||||
|
||||
|
@ -402,25 +404,11 @@ class TaskStub(object):
|
|||
def status(self):
|
||||
return self._status
|
||||
|
||||
def run(self, executor):
|
||||
pass
|
||||
|
||||
|
||||
class TaskDetails(object):
|
||||
|
||||
def __init__(self, task_id, task_input, message, result):
|
||||
if task_id is None:
|
||||
raise exception.TaskException(_('task_id is required to create '
|
||||
'a new TaskDetails object'))
|
||||
self.task_id = task_id
|
||||
self.input = task_input
|
||||
self.message = message
|
||||
self.result = result
|
||||
|
||||
|
||||
class TaskFactory(object):
|
||||
|
||||
def new_task(self, task_type, owner, task_time_to_live=48):
|
||||
def new_task(self, task_type, owner, task_time_to_live=48,
|
||||
task_input=None, **kwargs):
|
||||
task_id = str(uuid.uuid4())
|
||||
status = 'pending'
|
||||
# Note(nikhil): expires_at would be set on the task, only when it
|
||||
|
@ -436,30 +424,8 @@ class TaskFactory(object):
|
|||
expires_at,
|
||||
created_at,
|
||||
updated_at,
|
||||
None, # input
|
||||
None, # result
|
||||
None, # message
|
||||
task_input,
|
||||
kwargs.get('message'),
|
||||
kwargs.get('result'),
|
||||
task_time_to_live
|
||||
)
|
||||
|
||||
def new_task_stub(self, task_type, owner, task_time_to_live=48):
|
||||
task_id = str(uuid.uuid4())
|
||||
status = 'pending'
|
||||
# Note(nikhil): expires_at would be set on the task, only when it
|
||||
# succeeds or fails.
|
||||
expires_at = None
|
||||
created_at = timeutils.utcnow()
|
||||
updated_at = created_at
|
||||
return TaskStub(
|
||||
task_id,
|
||||
task_type,
|
||||
status,
|
||||
owner,
|
||||
expires_at,
|
||||
created_at,
|
||||
updated_at,
|
||||
task_time_to_live
|
||||
)
|
||||
|
||||
def new_task_details(self, task_id, task_input, message=None, result=None):
|
||||
return TaskDetails(task_id, task_input, message, result)
|
||||
|
|
|
@ -45,38 +45,38 @@ class Helper(object):
|
|||
|
||||
|
||||
class TaskRepo(object):
|
||||
def __init__(self,
|
||||
base,
|
||||
task_proxy_class=None, task_proxy_kwargs=None,
|
||||
task_details_proxy_class=None,
|
||||
task_details_proxy_kwargs=None):
|
||||
def __init__(self, base,
|
||||
task_proxy_class=None, task_proxy_kwargs=None):
|
||||
self.base = base
|
||||
self.task_proxy_helper = Helper(task_proxy_class, task_proxy_kwargs)
|
||||
self.task_details_proxy_helper = Helper(task_details_proxy_class,
|
||||
task_details_proxy_kwargs)
|
||||
|
||||
def get_task_stub_and_details(self, task_id):
|
||||
task, task_details = self.base.get_task_stub_and_details(task_id)
|
||||
return (self.task_proxy_helper.proxy(task),
|
||||
self.task_details_proxy_helper.proxy(task_details))
|
||||
def get(self, task_id):
|
||||
task = self.base.get(task_id)
|
||||
return self.task_proxy_helper.proxy(task)
|
||||
|
||||
def list_tasks(self, *args, **kwargs):
|
||||
tasks = self.base.list_tasks(*args, **kwargs)
|
||||
return [self.task_proxy_helper.proxy(task) for task in tasks]
|
||||
def add(self, task):
|
||||
self.base.add(self.task_proxy_helper.unproxy(task))
|
||||
|
||||
def add(self, task, task_details=None):
|
||||
self.base.add(self.task_proxy_helper.unproxy(task),
|
||||
self.task_details_proxy_helper.unproxy(task_details))
|
||||
|
||||
def save(self, task, task_details=None):
|
||||
self.base.save(self.task_proxy_helper.unproxy(task),
|
||||
self.task_details_proxy_helper.unproxy(task_details))
|
||||
def save(self, task):
|
||||
self.base.save(self.task_proxy_helper.unproxy(task))
|
||||
|
||||
def remove(self, task):
|
||||
base_task = self.task_proxy_helper.unproxy(task)
|
||||
self.base.remove(base_task)
|
||||
|
||||
|
||||
class TaskStubRepo(object):
|
||||
def __init__(self, base, task_stub_proxy_class=None,
|
||||
task_stub_proxy_kwargs=None):
|
||||
self.base = base
|
||||
self.task_stub_proxy_helper = Helper(task_stub_proxy_class,
|
||||
task_stub_proxy_kwargs)
|
||||
|
||||
def list(self, *args, **kwargs):
|
||||
tasks = self.base.list(*args, **kwargs)
|
||||
return [self.task_stub_proxy_helper.proxy(task) for task in tasks]
|
||||
|
||||
|
||||
class Repo(object):
|
||||
def __init__(self, base, item_proxy_class=None, item_proxy_kwargs=None):
|
||||
self.base = base
|
||||
|
@ -191,6 +191,9 @@ class Task(object):
|
|||
def fail(self, message):
|
||||
self.base.fail(message)
|
||||
|
||||
def run(self, executor):
|
||||
self.base.run(executor)
|
||||
|
||||
|
||||
class TaskStub(object):
|
||||
def __init__(self, base):
|
||||
|
@ -204,40 +207,15 @@ class TaskStub(object):
|
|||
created_at = _proxy('base', 'created_at')
|
||||
updated_at = _proxy('base', 'updated_at')
|
||||
|
||||
def run(self, executor):
|
||||
self.base.run(executor)
|
||||
|
||||
|
||||
class TaskDetails(object):
|
||||
def __init__(self, base):
|
||||
self.base = base
|
||||
|
||||
task_id = _proxy('base', 'task_id')
|
||||
input = _proxy('base', 'input')
|
||||
result = _proxy('base', 'result')
|
||||
message = _proxy('base', 'message')
|
||||
|
||||
|
||||
class TaskFactory(object):
|
||||
def __init__(self,
|
||||
base,
|
||||
task_proxy_class=None,
|
||||
task_proxy_kwargs=None,
|
||||
task_details_proxy_class=None,
|
||||
task_details_proxy_kwargs=None):
|
||||
task_proxy_kwargs=None):
|
||||
self.task_helper = Helper(task_proxy_class, task_proxy_kwargs)
|
||||
self.task_details_helper = Helper(task_details_proxy_class,
|
||||
task_details_proxy_kwargs)
|
||||
self.base = base
|
||||
|
||||
def new_task(self, **kwargs):
|
||||
t = self.base.new_task(**kwargs)
|
||||
return self.task_helper.proxy(t)
|
||||
|
||||
def new_task_stub(self, **kwargs):
|
||||
t = self.base.new_task_stub(**kwargs)
|
||||
return self.task_helper.proxy(t)
|
||||
|
||||
def new_task_details(self, task_id, task_input, message=None, result=None):
|
||||
td = self.base.new_task_details(task_id, task_input, message, result)
|
||||
return self.task_details_helper.proxy(td)
|
||||
|
|
|
@ -107,3 +107,13 @@ class Gateway(object):
|
|||
authorized_task_repo = authorization.TaskRepoProxy(
|
||||
notifier_task_repo, context)
|
||||
return authorized_task_repo
|
||||
|
||||
def get_task_stub_repo(self, context):
|
||||
task_stub_repo = glance.db.TaskRepo(context, self.db_api)
|
||||
policy_task_stub_repo = policy.TaskStubRepoProxy(
|
||||
task_stub_repo, context, self.policy)
|
||||
notifier_task_stub_repo = glance.notifier.TaskStubRepoProxy(
|
||||
policy_task_stub_repo, context, self.notifier)
|
||||
authorized_task_stub_repo = authorization.TaskStubRepoProxy(
|
||||
notifier_task_stub_repo, context)
|
||||
return authorized_task_stub_repo
|
||||
|
|
|
@ -311,14 +311,12 @@ class TaskRepoProxy(glance.domain.proxy.TaskRepo):
|
|||
super(TaskRepoProxy, self) \
|
||||
.__init__(task_repo,
|
||||
task_proxy_class=TaskProxy,
|
||||
task_proxy_kwargs=proxy_kwargs,
|
||||
task_details_proxy_class=TaskDetailsProxy,
|
||||
task_details_proxy_kwargs=proxy_kwargs)
|
||||
task_proxy_kwargs=proxy_kwargs)
|
||||
|
||||
def add(self, task, task_details=None):
|
||||
def add(self, task):
|
||||
self.notifier.info('task.create',
|
||||
format_task_notification(task))
|
||||
super(TaskRepoProxy, self).add(task, task_details)
|
||||
super(TaskRepoProxy, self).add(task)
|
||||
|
||||
def remove(self, task):
|
||||
payload = format_task_notification(task)
|
||||
|
@ -328,15 +326,26 @@ class TaskRepoProxy(glance.domain.proxy.TaskRepo):
|
|||
super(TaskRepoProxy, self).remove(task)
|
||||
|
||||
|
||||
class TaskStubRepoProxy(glance.domain.proxy.TaskStubRepo):
|
||||
|
||||
def __init__(self, task_stub_repo, context, notifier):
|
||||
self.task_stub_repo = task_stub_repo
|
||||
self.context = context
|
||||
self.notifier = notifier
|
||||
proxy_kwargs = {'context': self.context, 'notifier': self.notifier}
|
||||
super(TaskStubRepoProxy, self) \
|
||||
.__init__(task_stub_repo,
|
||||
task_stub_proxy_class=TaskStubProxy,
|
||||
task_stub_proxy_kwargs=proxy_kwargs)
|
||||
|
||||
|
||||
class TaskFactoryProxy(glance.domain.proxy.TaskFactory):
|
||||
def __init__(self, task_factory, context, notifier):
|
||||
kwargs = {'context': context, 'notifier': notifier}
|
||||
super(TaskFactoryProxy, self).__init__(
|
||||
task_factory,
|
||||
task_proxy_class=TaskProxy,
|
||||
task_proxy_kwargs=kwargs,
|
||||
task_details_proxy_class=TaskDetailsProxy,
|
||||
task_details_proxy_kwargs=kwargs)
|
||||
task_proxy_kwargs=kwargs)
|
||||
|
||||
|
||||
class TaskProxy(glance.domain.proxy.Task):
|
||||
|
@ -364,6 +373,11 @@ class TaskProxy(glance.domain.proxy.Task):
|
|||
format_task_notification(self.task))
|
||||
return super(TaskProxy, self).fail(message)
|
||||
|
||||
def run(self, executor):
|
||||
self.notifier.info('task.run',
|
||||
format_task_notification(self.task))
|
||||
return super(TaskProxy, self).run(executor)
|
||||
|
||||
|
||||
class TaskStubProxy(glance.domain.proxy.TaskStub):
|
||||
|
||||
|
@ -372,17 +386,3 @@ class TaskStubProxy(glance.domain.proxy.TaskStub):
|
|||
self.context = context
|
||||
self.notifier = notifier
|
||||
super(TaskStubProxy, self).__init__(task)
|
||||
|
||||
def run(self, executor):
|
||||
self.notifier.info('task.run',
|
||||
format_task_notification(self.task))
|
||||
return super(TaskStubProxy, self).run(executor)
|
||||
|
||||
|
||||
class TaskDetailsProxy(glance.domain.proxy.TaskDetails):
|
||||
|
||||
def __init__(self, task_details, context, notifier):
|
||||
self.task_details = task_details
|
||||
self.context = context
|
||||
self.notifier = notifier
|
||||
super(TaskDetailsProxy, self).__init__(task_details)
|
||||
|
|
|
@ -105,7 +105,7 @@ class TestTasks(functional.FunctionalTest):
|
|||
u'status',
|
||||
u'type',
|
||||
u'updated_at'])
|
||||
self.assertEqual(set(task.keys()), checked_keys)
|
||||
self.assertEqual(checked_keys, set(task.keys()))
|
||||
expected_task = {
|
||||
'status': 'pending',
|
||||
'type': 'import',
|
||||
|
|
|
@ -207,7 +207,7 @@ class TestTasksApi(base.ApiTest):
|
|||
# 1. POST /tasks
|
||||
# Create a new task with invalid input for type 'import'
|
||||
# Expect BadRequest(400) Error as response
|
||||
task_data = _new_task_fixture(input='{something: invalid}')
|
||||
task_data = _new_task_fixture(task_input='{something: invalid}')
|
||||
task_owner = 'tenant1'
|
||||
body_content = json.dumps(task_data)
|
||||
|
||||
|
|
|
@ -925,6 +925,53 @@ class TestImmutableTask(utils.BaseTestCase):
|
|||
)
|
||||
|
||||
|
||||
class TestImmutableTaskStub(utils.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(TestImmutableTaskStub, self).setUp()
|
||||
task_factory = glance.domain.TaskFactory()
|
||||
self.context = glance.context.RequestContext(tenant=TENANT2)
|
||||
task_type = 'import'
|
||||
owner = TENANT2
|
||||
task = task_factory.new_task(task_type, owner)
|
||||
self.task = authorization.ImmutableTaskStubProxy(task)
|
||||
|
||||
def _test_change(self, attr, value):
|
||||
self.assertRaises(
|
||||
exception.Forbidden,
|
||||
setattr,
|
||||
self.task,
|
||||
attr,
|
||||
value
|
||||
)
|
||||
self.assertRaises(
|
||||
exception.Forbidden,
|
||||
delattr,
|
||||
self.task,
|
||||
attr
|
||||
)
|
||||
|
||||
def test_change_id(self):
|
||||
self._test_change('task_id', UUID2)
|
||||
|
||||
def test_change_type(self):
|
||||
self._test_change('type', 'fake')
|
||||
|
||||
def test_change_status(self):
|
||||
self._test_change('status', 'success')
|
||||
|
||||
def test_change_owner(self):
|
||||
self._test_change('owner', 'fake')
|
||||
|
||||
def test_change_expires_at(self):
|
||||
self._test_change('expires_at', 'fake')
|
||||
|
||||
def test_change_created_at(self):
|
||||
self._test_change('created_at', 'fake')
|
||||
|
||||
def test_change_updated_at(self):
|
||||
self._test_change('updated_at', 'fake')
|
||||
|
||||
|
||||
class TestTaskFactoryProxy(utils.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(TestTaskFactoryProxy, self).setUp()
|
||||
|
@ -977,14 +1024,18 @@ class TestTaskRepoProxy(utils.BaseTestCase):
|
|||
def __init__(self, fixtures):
|
||||
self.fixtures = fixtures
|
||||
|
||||
def get_task_stub_and_details(self, task_id):
|
||||
def get(self, task_id):
|
||||
for f in self.fixtures:
|
||||
if f.task_id == task_id:
|
||||
return f, None
|
||||
return f
|
||||
else:
|
||||
raise ValueError(task_id)
|
||||
|
||||
def list_tasks(self, *args, **kwargs):
|
||||
class TaskStubRepoStub(object):
|
||||
def __init__(self, fixtures):
|
||||
self.fixtures = fixtures
|
||||
|
||||
def list(self, *args, **kwargs):
|
||||
return self.fixtures
|
||||
|
||||
def setUp(self):
|
||||
|
@ -999,27 +1050,28 @@ class TestTaskRepoProxy(utils.BaseTestCase):
|
|||
]
|
||||
self.context = glance.context.RequestContext(tenant=TENANT1)
|
||||
task_repo = self.TaskRepoStub(self.fixtures)
|
||||
task_stub_repo = self.TaskStubRepoStub(self.fixtures)
|
||||
self.task_repo = authorization.TaskRepoProxy(
|
||||
task_repo,
|
||||
self.context
|
||||
)
|
||||
self.task_stub_repo = authorization.TaskStubRepoProxy(
|
||||
task_stub_repo,
|
||||
self.context
|
||||
)
|
||||
|
||||
def test_get_mutable_task(self):
|
||||
task, _ = self.task_repo.get_task_stub_and_details(
|
||||
self.fixtures[0].task_id)
|
||||
task = self.task_repo.get(self.fixtures[0].task_id)
|
||||
self.assertEqual(task.task_id, self.fixtures[0].task_id)
|
||||
|
||||
def test_get_immutable_task(self):
|
||||
task_id = self.fixtures[1].task_id
|
||||
task, task_details = self.task_repo.get_task_stub_and_details(task_id)
|
||||
task = self.task_repo.get(task_id)
|
||||
self.assertRaises(exception.Forbidden,
|
||||
setattr,
|
||||
task_details,
|
||||
'input',
|
||||
'foo')
|
||||
setattr, task, 'input', 'foo')
|
||||
|
||||
def test_list(self):
|
||||
tasks = self.task_repo.list_tasks()
|
||||
tasks = self.task_stub_repo.list()
|
||||
self.assertEqual(tasks[0].task_id, self.fixtures[0].task_id)
|
||||
self.assertRaises(exception.Forbidden,
|
||||
setattr,
|
||||
|
|
|
@ -585,97 +585,92 @@ class TestTaskRepo(test_utils.BaseTestCase):
|
|||
[self.db.task_create(None, task) for task in self.tasks]
|
||||
|
||||
def test_get(self):
|
||||
task, task_details = self.task_repo.get_task_stub_and_details(UUID1)
|
||||
task = self.task_repo.get(UUID1)
|
||||
self.assertEqual(task.task_id, UUID1)
|
||||
self.assertEqual(task.type, 'import')
|
||||
self.assertEqual(task.status, 'pending')
|
||||
self.assertEqual(task.task_id, task_details.task_id)
|
||||
self.assertEqual(task_details.input, self.fake_task_input)
|
||||
self.assertEqual(task_details.result, '')
|
||||
self.assertEqual(task.task_input, self.fake_task_input)
|
||||
self.assertEqual(task.result, '')
|
||||
self.assertEqual(task.message, '')
|
||||
self.assertEqual(task.owner, TENANT1)
|
||||
|
||||
def test_get_not_found(self):
|
||||
self.assertRaises(exception.NotFound,
|
||||
self.task_repo.get_task_stub_and_details,
|
||||
self.task_repo.get,
|
||||
str(uuid.uuid4()))
|
||||
|
||||
def test_get_forbidden(self):
|
||||
self.assertRaises(exception.NotFound,
|
||||
self.task_repo.get_task_stub_and_details,
|
||||
self.task_repo.get,
|
||||
UUID4)
|
||||
|
||||
def test_list(self):
|
||||
tasks = self.task_repo.list_tasks()
|
||||
tasks = self.task_repo.list()
|
||||
task_ids = set([i.task_id for i in tasks])
|
||||
self.assertEqual(set([UUID1, UUID2, UUID3]), task_ids)
|
||||
|
||||
def test_list_with_type(self):
|
||||
filters = {'type': 'import'}
|
||||
tasks = self.task_repo.list_tasks(filters=filters)
|
||||
tasks = self.task_repo.list(filters=filters)
|
||||
task_ids = set([i.task_id for i in tasks])
|
||||
self.assertEqual(set([UUID1, UUID2, UUID3]), task_ids)
|
||||
|
||||
def test_list_with_status(self):
|
||||
filters = {'status': 'failure'}
|
||||
tasks = self.task_repo.list_tasks(filters=filters)
|
||||
tasks = self.task_repo.list(filters=filters)
|
||||
task_ids = set([i.task_id for i in tasks])
|
||||
self.assertEqual(set([UUID3]), task_ids)
|
||||
|
||||
def test_list_with_marker(self):
|
||||
full_tasks = self.task_repo.list_tasks()
|
||||
full_tasks = self.task_repo.list()
|
||||
full_ids = [i.task_id for i in full_tasks]
|
||||
marked_tasks = self.task_repo.list_tasks(marker=full_ids[0])
|
||||
marked_tasks = self.task_repo.list(marker=full_ids[0])
|
||||
actual_ids = [i.task_id for i in marked_tasks]
|
||||
self.assertEqual(actual_ids, full_ids[1:])
|
||||
|
||||
def test_list_with_last_marker(self):
|
||||
tasks = self.task_repo.list_tasks()
|
||||
marked_tasks = self.task_repo.list_tasks(marker=tasks[-1].task_id)
|
||||
tasks = self.task_repo.list()
|
||||
marked_tasks = self.task_repo.list(marker=tasks[-1].task_id)
|
||||
self.assertEqual(len(marked_tasks), 0)
|
||||
|
||||
def test_limited_list(self):
|
||||
limited_tasks = self.task_repo.list_tasks(limit=2)
|
||||
limited_tasks = self.task_repo.list(limit=2)
|
||||
self.assertEqual(len(limited_tasks), 2)
|
||||
|
||||
def test_list_with_marker_and_limit(self):
|
||||
full_tasks = self.task_repo.list_tasks()
|
||||
full_tasks = self.task_repo.list()
|
||||
full_ids = [i.task_id for i in full_tasks]
|
||||
marked_tasks = self.task_repo.list_tasks(marker=full_ids[0], limit=1)
|
||||
marked_tasks = self.task_repo.list(marker=full_ids[0], limit=1)
|
||||
actual_ids = [i.task_id for i in marked_tasks]
|
||||
self.assertEqual(actual_ids, full_ids[1:2])
|
||||
|
||||
def test_sorted_list(self):
|
||||
tasks = self.task_repo.list_tasks(sort_key='status', sort_dir='desc')
|
||||
tasks = self.task_repo.list(sort_key='status', sort_dir='desc')
|
||||
task_ids = [i.task_id for i in tasks]
|
||||
self.assertEqual([UUID2, UUID1, UUID3], task_ids)
|
||||
|
||||
def test_add_task(self):
|
||||
task_type = 'import'
|
||||
task = self.task_factory.new_task(task_type, None)
|
||||
task = self.task_factory.new_task(task_type, None,
|
||||
task_input=self.fake_task_input)
|
||||
self.assertEqual(task.updated_at, task.created_at)
|
||||
task_details = self.task_factory.new_task_details(task.task_id,
|
||||
self.fake_task_input)
|
||||
|
||||
self.task_repo.add(task, task_details)
|
||||
retrieved_task, retrieved_task_details = \
|
||||
self.task_repo.get_task_stub_and_details(task.task_id)
|
||||
self.assertEqual(retrieved_task.updated_at, task.updated_at)
|
||||
self.assertEqual(retrieved_task_details.task_id,
|
||||
retrieved_task.task_id)
|
||||
self.assertEqual(retrieved_task_details.input, task_details.input)
|
||||
self.task_repo.add(task)
|
||||
retrieved_task = self.task_repo.get(task.task_id)
|
||||
self.assertEqual(task.updated_at, retrieved_task.updated_at)
|
||||
self.assertEqual(self.fake_task_input, retrieved_task.task_input)
|
||||
|
||||
def test_save_task(self):
|
||||
task, task_details = self.task_repo.get_task_stub_and_details(UUID1)
|
||||
task = self.task_repo.get(UUID1)
|
||||
original_update_time = task.updated_at
|
||||
self.task_repo.save(task)
|
||||
current_update_time = task.updated_at
|
||||
self.assertTrue(current_update_time > original_update_time)
|
||||
task, task_details = self.task_repo.get_task_stub_and_details(UUID1)
|
||||
task = self.task_repo.get(UUID1)
|
||||
self.assertEqual(task.updated_at, current_update_time)
|
||||
|
||||
def test_remove_task(self):
|
||||
task, task_details = self.task_repo.get_task_stub_and_details(UUID1)
|
||||
task = self.task_repo.get(UUID1)
|
||||
self.task_repo.remove(task)
|
||||
self.assertRaises(exception.NotFound,
|
||||
self.task_repo.get_task_stub_and_details,
|
||||
self.task_repo.get,
|
||||
task.task_id)
|
||||
|
|
|
@ -306,29 +306,19 @@ class TestTaskFactory(test_utils.BaseTestCase):
|
|||
def test_new_task(self):
|
||||
task_type = 'import'
|
||||
owner = TENANT1
|
||||
task = self.task_factory.new_task(task_type, owner)
|
||||
task_input = 'input'
|
||||
task = self.task_factory.new_task(task_type, owner,
|
||||
task_input=task_input)
|
||||
self.assertIsNotNone(task.task_id)
|
||||
self.assertEqual('pending', task.status)
|
||||
self.assertEqual(task_type, task.type)
|
||||
self.assertEqual(owner, task.owner)
|
||||
self.assertIsNone(task.expires_at)
|
||||
self.assertIsNotNone(task.created_at)
|
||||
self.assertEqual(task_type, task.type)
|
||||
self.assertEqual(task.created_at, task.updated_at)
|
||||
self.assertIsNone(task.task_input)
|
||||
self.assertIsNone(task.result)
|
||||
self.assertEqual('pending', task.status)
|
||||
self.assertIsNone(task.expires_at)
|
||||
self.assertEqual(owner, task.owner)
|
||||
self.assertEqual(task_input, task.task_input)
|
||||
self.assertIsNone(task.message)
|
||||
|
||||
def test_new_task_stub(self):
|
||||
task_type = 'import'
|
||||
owner = TENANT1
|
||||
task = self.task_factory.new_task_stub(task_type, owner)
|
||||
self.assertIsNotNone(task.task_id)
|
||||
self.assertEqual('pending', task.status)
|
||||
self.assertEqual(task_type, task.type)
|
||||
self.assertEqual(owner, task.owner)
|
||||
self.assertIsNone(task.expires_at)
|
||||
self.assertIsNotNone(task.created_at)
|
||||
self.assertEqual(task.created_at, task.updated_at)
|
||||
self.assertIsNone(task.result)
|
||||
|
||||
def test_new_task_invalid_type(self):
|
||||
task_type = 'blah'
|
||||
|
@ -340,20 +330,6 @@ class TestTaskFactory(test_utils.BaseTestCase):
|
|||
owner,
|
||||
)
|
||||
|
||||
def test_new_task_details(self):
|
||||
task_id = 'fake_task_id'
|
||||
task_input = '{"import_from": "fake"}'
|
||||
result = '{"result": "success"}'
|
||||
message = 'fake message'
|
||||
task_details = self.task_factory.new_task_details(task_id,
|
||||
task_input,
|
||||
message,
|
||||
result)
|
||||
self.assertEqual(task_details.task_id, task_id)
|
||||
self.assertEqual(task_details.input, task_input)
|
||||
self.assertEqual(task_details.result, result)
|
||||
self.assertEqual(task_details.message, message)
|
||||
|
||||
|
||||
class TestTask(test_utils.BaseTestCase):
|
||||
|
||||
|
@ -381,8 +357,8 @@ class TestTask(test_utils.BaseTestCase):
|
|||
created_at=timeutils.utcnow(),
|
||||
updated_at=timeutils.utcnow(),
|
||||
task_input=None,
|
||||
result=None,
|
||||
message=None
|
||||
message=None,
|
||||
result=None
|
||||
)
|
||||
|
||||
def test_validate_status_transition_from_pending(self):
|
||||
|
@ -489,8 +465,7 @@ class TestTaskStub(test_utils.BaseTestCase):
|
|||
self.owner,
|
||||
'expires_at',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
task_time_to_live=self.task_ttl
|
||||
'updated_at'
|
||||
)
|
||||
self.assertEqual(self.task_id, task.task_id)
|
||||
self.assertEqual(self.task_type, task.type)
|
||||
|
@ -509,32 +484,6 @@ class TestTaskStub(test_utils.BaseTestCase):
|
|||
self.owner,
|
||||
'expires_at',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
task_time_to_live=self.task_ttl
|
||||
'updated_at'
|
||||
)
|
||||
self.assertEqual(status, task.status)
|
||||
|
||||
|
||||
class TestTaskDetails(test_utils.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(TestTaskDetails, self).setUp()
|
||||
self.task_input = ('{"import_from": "file:///home/a.img",'
|
||||
' "import_from_format": "qcow2"}')
|
||||
|
||||
def test_task_details_init(self):
|
||||
task_details_values = ['task_id_1',
|
||||
self.task_input,
|
||||
'result',
|
||||
'None']
|
||||
task_details = domain.TaskDetails(*task_details_values)
|
||||
self.assertIsNotNone(task_details)
|
||||
|
||||
def test_task_details_with_no_task_id(self):
|
||||
task_id = None
|
||||
task_details_values = [task_id,
|
||||
self.task_input,
|
||||
'result',
|
||||
'None']
|
||||
self.assertRaises(exception.TaskException,
|
||||
domain.TaskDetails,
|
||||
*task_details_values)
|
||||
|
|
|
@ -305,24 +305,13 @@ class TestTaskFactory(test_utils.BaseTestCase):
|
|||
owner=self.fake_owner
|
||||
)
|
||||
|
||||
proxy_factory.new_task_details("task_01", "input")
|
||||
|
||||
self.factory.new_task_details.assert_called_once_with(
|
||||
"task_01",
|
||||
"input",
|
||||
None, None
|
||||
)
|
||||
|
||||
def test_proxy_wrapping(self):
|
||||
proxy_factory = proxy.TaskFactory(
|
||||
self.factory,
|
||||
task_proxy_class=FakeProxy,
|
||||
task_proxy_kwargs={'dog': 'bark'},
|
||||
task_details_proxy_class=FakeProxy,
|
||||
task_details_proxy_kwargs={'dog': 'bark'})
|
||||
task_proxy_kwargs={'dog': 'bark'})
|
||||
|
||||
self.factory.new_task.return_value = 'fake_task'
|
||||
self.factory.new_task_details.return_value = 'fake_task_detail'
|
||||
|
||||
task = proxy_factory.new_task(
|
||||
type=self.fake_type,
|
||||
|
@ -335,14 +324,3 @@ class TestTaskFactory(test_utils.BaseTestCase):
|
|||
)
|
||||
self.assertIsInstance(task, FakeProxy)
|
||||
self.assertEqual(task.base, 'fake_task')
|
||||
|
||||
task_details = proxy_factory.new_task_details('task_01', "input")
|
||||
|
||||
self.factory.new_task_details.assert_called_once_with(
|
||||
'task_01',
|
||||
"input",
|
||||
None, None
|
||||
)
|
||||
|
||||
self.assertIsInstance(task_details, FakeProxy)
|
||||
self.assertEqual(task_details.base, 'fake_task_detail')
|
||||
|
|
|
@ -21,7 +21,6 @@ import webob
|
|||
|
||||
from glance.common import exception
|
||||
import glance.context
|
||||
from glance import domain
|
||||
from glance import notifier
|
||||
from glance.openstack.common import timeutils
|
||||
import glance.tests.unit.utils as unit_test_utils
|
||||
|
@ -427,10 +426,6 @@ class TestTaskNotifications(utils.BaseTestCase):
|
|||
result='res',
|
||||
message='blah'
|
||||
)
|
||||
self.task_details = domain.TaskDetails(task_id=self.task.task_id,
|
||||
task_input=task_input,
|
||||
result='',
|
||||
message='')
|
||||
self.context = glance.context.RequestContext(
|
||||
tenant=TENANT2,
|
||||
user=USER1
|
||||
|
@ -452,9 +447,6 @@ class TestTaskNotifications(utils.BaseTestCase):
|
|||
self.context,
|
||||
self.notifier
|
||||
)
|
||||
self.task_details_proxy = notifier.TaskDetailsProxy(self.task_details,
|
||||
self.context,
|
||||
self.notifier)
|
||||
self.patcher = mock.patch.object(timeutils, 'utcnow')
|
||||
mock_utcnow = self.patcher.start()
|
||||
mock_utcnow.return_value = datetime.datetime.utcnow()
|
||||
|
@ -464,8 +456,7 @@ class TestTaskNotifications(utils.BaseTestCase):
|
|||
self.patcher.stop()
|
||||
|
||||
def test_task_create_notification(self):
|
||||
self.task_repo_proxy.add(self.task_stub_proxy,
|
||||
self.task_details_proxy)
|
||||
self.task_repo_proxy.add(self.task_stub_proxy)
|
||||
output_logs = self.notifier.get_logs()
|
||||
self.assertEqual(len(output_logs), 1)
|
||||
output_log = output_logs[0]
|
||||
|
@ -508,7 +499,7 @@ class TestTaskNotifications(utils.BaseTestCase):
|
|||
self.fail('Notification contained location field.')
|
||||
|
||||
def test_task_run_notification(self):
|
||||
self.task_stub_proxy.run(executor=None)
|
||||
self.task_proxy.run(executor=None)
|
||||
output_logs = self.notifier.get_logs()
|
||||
self.assertEqual(len(output_logs), 1)
|
||||
output_log = output_logs[0]
|
||||
|
|
|
@ -85,13 +85,13 @@ class ImageMembershipStub(object):
|
|||
|
||||
|
||||
class TaskRepoStub(object):
|
||||
def get_task_stub_and_details(self, *args, **kwargs):
|
||||
return 'task_from_get', 'task_details_from_get'
|
||||
def get(self, *args, **kwargs):
|
||||
return 'task_from_get'
|
||||
|
||||
def add(self, *args, **kwargs):
|
||||
return 'task_from_add'
|
||||
|
||||
def list_tasks(self, *args, **kwargs):
|
||||
def list(self, *args, **kwargs):
|
||||
return ['task_from_list_0', 'task_from_list_1']
|
||||
|
||||
|
||||
|
@ -386,7 +386,7 @@ class TestTaskPolicy(test_utils.BaseTestCase):
|
|||
self.policy
|
||||
)
|
||||
self.assertRaises(exception.Forbidden,
|
||||
task_repo.get_task_stub_and_details,
|
||||
task_repo.get,
|
||||
UUID1)
|
||||
|
||||
def test_get_task_allowed(self):
|
||||
|
@ -397,32 +397,32 @@ class TestTaskPolicy(test_utils.BaseTestCase):
|
|||
{},
|
||||
self.policy
|
||||
)
|
||||
task, task_details = task_repo.get_task_stub_and_details(UUID1)
|
||||
task = task_repo.get(UUID1)
|
||||
self.assertIsInstance(task, glance.api.policy.TaskProxy)
|
||||
self.assertEqual(task.task, 'task_from_get')
|
||||
|
||||
def test_get_tasks_not_allowed(self):
|
||||
rules = {"get_tasks": False}
|
||||
self.policy.set_rules(rules)
|
||||
task_repo = glance.api.policy.TaskRepoProxy(
|
||||
task_repo = glance.api.policy.TaskStubRepoProxy(
|
||||
self.task_repo_stub,
|
||||
{},
|
||||
self.policy
|
||||
)
|
||||
self.assertRaises(exception.Forbidden, task_repo.list_tasks)
|
||||
self.assertRaises(exception.Forbidden, task_repo.list)
|
||||
|
||||
def test_get_tasks_allowed(self):
|
||||
rules = {"get_task": True}
|
||||
self.policy.set_rules(rules)
|
||||
task_repo = glance.api.policy.TaskRepoProxy(
|
||||
task_repo = glance.api.policy.TaskStubRepoProxy(
|
||||
self.task_repo_stub,
|
||||
{},
|
||||
self.policy
|
||||
)
|
||||
tasks = task_repo.list_tasks()
|
||||
tasks = task_repo.list()
|
||||
for i, task in enumerate(tasks):
|
||||
self.assertIsInstance(task, glance.api.policy.TaskProxy)
|
||||
self.assertEqual(task.task, 'task_from_list_%d' % i)
|
||||
self.assertIsInstance(task, glance.api.policy.TaskStubProxy)
|
||||
self.assertEqual(task.task_stub, 'task_from_list_%d' % i)
|
||||
|
||||
def test_add_task_not_allowed(self):
|
||||
rules = {"add_task": False}
|
||||
|
|
|
@ -71,13 +71,12 @@ def _domain_fixture(task_id, **kwargs):
|
|||
'expires_at': kwargs.get('expires_at', None),
|
||||
'created_at': kwargs.get('created_at', default_datetime),
|
||||
'updated_at': kwargs.get('updated_at', default_datetime),
|
||||
'task_input': kwargs.get('task_input', {}),
|
||||
'message': kwargs.get('message', None),
|
||||
'result': kwargs.get('result', None)
|
||||
}
|
||||
task = glance.domain.TaskStub(**task_properties)
|
||||
task_details = glance.domain.TaskDetails(task_id,
|
||||
kwargs.get('input', {}),
|
||||
kwargs.get('message', None),
|
||||
kwargs.get('result', None))
|
||||
return {'task': task, 'task_details': task_details}
|
||||
task = glance.domain.Task(**task_properties)
|
||||
return task
|
||||
|
||||
|
||||
class TestTasksController(test_utils.BaseTestCase):
|
||||
|
@ -267,11 +266,8 @@ class TestTasksController(test_utils.BaseTestCase):
|
|||
|
||||
def test_get(self):
|
||||
request = unit_test_utils.get_fake_request()
|
||||
output = self.controller.get(request, task_id=UUID1)
|
||||
task = output['task']
|
||||
task_details = output['task_details']
|
||||
task = self.controller.get(request, task_id=UUID1)
|
||||
self.assertEqual(UUID1, task.task_id)
|
||||
self.assertEqual(UUID1, task_details.task_id)
|
||||
self.assertEqual('import', task.type)
|
||||
|
||||
def test_get_non_existent(self):
|
||||
|
@ -292,13 +288,11 @@ class TestTasksController(test_utils.BaseTestCase):
|
|||
"import_from": "swift://cloud.foo/myaccount/mycontainer/path",
|
||||
"image_from_format": "qcow2"}
|
||||
}
|
||||
output = self.controller.create(request, task=task)
|
||||
task = output['task']
|
||||
task_details = output['task_details']
|
||||
task = self.controller.create(request, task=task)
|
||||
self.assertEqual('import', task.type)
|
||||
self.assertEqual({
|
||||
"import_from": "swift://cloud.foo/myaccount/mycontainer/path",
|
||||
"image_from_format": "qcow2"}, task_details.input)
|
||||
"image_from_format": "qcow2"}, task.task_input)
|
||||
output_logs = [nlog for nlog in self.notifier.get_logs()
|
||||
if nlog['event_type'] == 'task.create']
|
||||
self.assertEqual(len(output_logs), 1)
|
||||
|
@ -495,21 +489,23 @@ class TestTasksSerializer(test_utils.BaseTestCase):
|
|||
self.serializer = glance.api.v2.tasks.ResponseSerializer()
|
||||
self.fixtures = [
|
||||
_domain_fixture(UUID1, type='import', status='pending',
|
||||
input={'loc': 'fake'}, result={}, owner=TENANT1,
|
||||
message='', created_at=DATETIME,
|
||||
task_input={'loc': 'fake'}, result={},
|
||||
owner=TENANT1, message='', created_at=DATETIME,
|
||||
updated_at=DATETIME),
|
||||
_domain_fixture(UUID2, type='import', status='processing',
|
||||
input={'loc': 'bake'}, owner=TENANT2, message='',
|
||||
created_at=DATETIME, updated_at=DATETIME,
|
||||
result={}),
|
||||
task_input={'loc': 'bake'}, owner=TENANT2,
|
||||
message='', created_at=DATETIME,
|
||||
updated_at=DATETIME, result={}),
|
||||
_domain_fixture(UUID3, type='import', status='success',
|
||||
input={'loc': 'foo'}, owner=TENANT3, message='',
|
||||
created_at=DATETIME, updated_at=DATETIME,
|
||||
result={}, expires_at=DATETIME),
|
||||
task_input={'loc': 'foo'}, owner=TENANT3,
|
||||
message='', created_at=DATETIME,
|
||||
updated_at=DATETIME, result={},
|
||||
expires_at=DATETIME),
|
||||
_domain_fixture(UUID4, type='import', status='failure',
|
||||
input={'loc': 'boo'}, owner=TENANT4, message='',
|
||||
created_at=DATETIME, updated_at=DATETIME,
|
||||
result={}, expires_at=DATETIME),
|
||||
task_input={'loc': 'boo'}, owner=TENANT4,
|
||||
message='', created_at=DATETIME,
|
||||
updated_at=DATETIME, result={},
|
||||
expires_at=DATETIME),
|
||||
]
|
||||
|
||||
def test_index(self):
|
||||
|
@ -563,7 +559,7 @@ class TestTasksSerializer(test_utils.BaseTestCase):
|
|||
}
|
||||
request = webob.Request.blank('/v2/tasks')
|
||||
response = webob.Response(request=request)
|
||||
task_fixtures = [f['task'] for f in self.fixtures]
|
||||
task_fixtures = [f for f in self.fixtures]
|
||||
result = {'tasks': task_fixtures}
|
||||
self.serializer.index(response, result)
|
||||
actual = jsonutils.loads(response.body)
|
||||
|
@ -573,7 +569,7 @@ class TestTasksSerializer(test_utils.BaseTestCase):
|
|||
def test_index_next_marker(self):
|
||||
request = webob.Request.blank('/v2/tasks')
|
||||
response = webob.Response(request=request)
|
||||
task_fixtures = [f['task'] for f in self.fixtures]
|
||||
task_fixtures = [f for f in self.fixtures]
|
||||
result = {'tasks': task_fixtures, 'next_marker': UUID2}
|
||||
self.serializer.index(response, result)
|
||||
output = jsonutils.loads(response.body)
|
||||
|
@ -583,7 +579,7 @@ class TestTasksSerializer(test_utils.BaseTestCase):
|
|||
url = '/v2/tasks?limit=10&sort_key=id&sort_dir=asc'
|
||||
request = webob.Request.blank(url)
|
||||
response = webob.Response(request=request)
|
||||
task_fixtures = [f['task'] for f in self.fixtures]
|
||||
task_fixtures = [f for f in self.fixtures]
|
||||
result = {'tasks': task_fixtures, 'next_marker': UUID2}
|
||||
self.serializer.index(response, result)
|
||||
output = jsonutils.loads(response.body)
|
||||
|
@ -661,11 +657,9 @@ class TestTasksSerializer(test_utils.BaseTestCase):
|
|||
|
||||
serialized_task = jsonutils.loads(response.body)
|
||||
self.assertEqual(response.status_int, 201)
|
||||
self.assertEqual(self.fixtures[3]['task'].task_id,
|
||||
self.assertEqual(self.fixtures[3].task_id,
|
||||
serialized_task['id'])
|
||||
self.assertEqual(self.fixtures[3]['task_details'].task_id,
|
||||
serialized_task['id'])
|
||||
self.assertEqual(self.fixtures[3]['task_details'].input,
|
||||
self.assertEqual(self.fixtures[3].task_input,
|
||||
serialized_task['input'])
|
||||
self.assertTrue('expires_at' in serialized_task)
|
||||
self.assertEqual('application/json', response.content_type)
|
||||
|
@ -677,11 +671,9 @@ class TestTasksSerializer(test_utils.BaseTestCase):
|
|||
|
||||
serialized_task = jsonutils.loads(response.body)
|
||||
self.assertEqual(response.status_int, 201)
|
||||
self.assertEqual(self.fixtures[0]['task'].task_id,
|
||||
self.assertEqual(self.fixtures[0].task_id,
|
||||
serialized_task['id'])
|
||||
self.assertEqual(self.fixtures[0]['task_details'].task_id,
|
||||
serialized_task['id'])
|
||||
self.assertEqual(self.fixtures[0]['task_details'].input,
|
||||
self.assertEqual(self.fixtures[0].task_input,
|
||||
serialized_task['input'])
|
||||
self.assertFalse('expires_at' in serialized_task)
|
||||
self.assertEqual('application/json', response.content_type)
|
||||
|
@ -692,11 +684,9 @@ class TestTasksSerializer(test_utils.BaseTestCase):
|
|||
|
||||
serialized_task = jsonutils.loads(response.body)
|
||||
self.assertEqual(response.status_int, 201)
|
||||
self.assertEqual(self.fixtures[1]['task'].task_id,
|
||||
self.assertEqual(self.fixtures[1].task_id,
|
||||
serialized_task['id'])
|
||||
self.assertEqual(self.fixtures[1]['task_details'].task_id,
|
||||
serialized_task['id'])
|
||||
self.assertEqual(self.fixtures[1]['task_details'].input,
|
||||
self.assertEqual(self.fixtures[1].task_input,
|
||||
serialized_task['input'])
|
||||
self.assertFalse('expires_at' in serialized_task)
|
||||
self.assertEqual('application/json', response.content_type)
|
||||
|
|
Loading…
Reference in New Issue