Add task status tracking

Task state is storing in database and updating with db.api methods.
Task uuid is stored in self.task_uuid property of engine.
Added method `update_status' in base engine class.

Blueprint db-task-track

Change-Id: I34be803d3f0566e62321e064fdf46b37145348e0
This commit is contained in:
Sergey Skripnick 2013-09-17 17:57:04 +03:00
parent b4d0d04856
commit a6297b14ca
6 changed files with 139 additions and 18 deletions

1
.gitignore vendored
View File

@ -26,6 +26,7 @@ pip-log.txt
.tox
nosetests.xml
.testrepository
*.sqlite
# Translations
*.mo

View File

@ -47,6 +47,7 @@ class _TaskStatus(_Immutable, _Enum):
REPO_TOOL_GETTING_REPOS = 'repo_tool->getting_repos'
DEPLOY_STARTED = 'deploy->started'
DEPLOY_CREATING_VENV = 'deploy->create_venv_to_deploy_openstack'
DEPLOY_BUILDING_OPENSTACK_IN_VENV = 'deploy->building_openstack_in_venv'
DEPLOY_BUILDING_IMAGE = 'deploy->building_images_with_openstack'

View File

@ -17,6 +17,8 @@
import abc
from rally import consts
from rally import db
from rally import exceptions
from rally import utils
@ -49,11 +51,14 @@ class EngineFactory(object):
__metaclass__ = abc.ABCMeta
@staticmethod
def get_engine(name, config):
def get_engine(name, uuid, config):
"""Returns instance of deploy engine with corresponding name."""
for engine in utils.itersubclasses(EngineFactory):
if name == engine.__name__:
return engine(config)
new_engine = engine(config)
new_engine.task_uuid = str(uuid)
db.task_create({'uuid': str(uuid)})
return new_engine
raise exceptions.NoSuchEngine(engine_name=name)
@staticmethod
@ -69,8 +74,16 @@ class EngineFactory(object):
def cleanup(self):
"""Cleanup OpenStack deployment."""
def update_status(self, status):
db.task_update(self.task_uuid, {'status': status})
def __enter__(self):
return self.deploy()
self.update_status(consts.TaskStatus.DEPLOY_STARTED)
deploy = self.deploy()
self.update_status(consts.TaskStatus.DEPLOY_FINISHED)
return deploy
def __exit__(self, type, value, traceback):
self.update_status(consts.TaskStatus.CLEANUP)
self.cleanup()
self.update_status(consts.TaskStatus.FINISHED)

View File

@ -17,6 +17,9 @@
"""Test for deploy engines."""
import mock
import uuid
from rally import deploy
from rally import exceptions
from rally import test
@ -26,11 +29,15 @@ class EngineFactoryTestCase(test.NoDBTestCase):
def test_get_engine_not_found(self):
self.assertRaises(exceptions.NoSuchEngine,
deploy.EngineFactory.get_engine,
deploy.EngineFactory.get_engine, uuid.uuid4(),
"non_existing_engine", None)
def _create_fake_engines(self):
class EngineMixIn(object):
def __init__(self, config):
pass
def deploy(self):
pass
@ -38,23 +45,23 @@ class EngineFactoryTestCase(test.NoDBTestCase):
pass
class EngineFake1(EngineMixIn, deploy.EngineFactory):
def __init__(self, config):
pass
class EngineFake2(EngineMixIn, deploy.EngineFactory):
def __init__(self, config):
pass
class EngineFake3(EngineFake2):
def __init__(self, config):
pass
return [EngineFake1, EngineFake2, EngineFake3]
def test_get_engine(self):
engines = self._create_fake_engines()
with mock.patch('rally.deploy.engine.db'):
for e in engines:
engine_inst = deploy.EngineFactory.get_engine(e.__name__, None)
engine_inst = deploy.EngineFactory.get_engine(e.__name__,
uuid.uuid4(),
{})
# TODO(boris-42): make it work through assertIsInstance
self.assertEqual(str(type(engine_inst)), str(e))
@ -80,7 +87,9 @@ class EngineFactoryTestCase(test.NoDBTestCase):
def cleanup(self):
self.cleanuped = True
with deploy.EngineFactory.get_engine('A', None) as deployment:
with mock.patch('rally.deploy.engine.db'):
with deploy.EngineFactory.get_engine('A', uuid.uuid4(),
None) as deployment:
self.assertTrue(deployment.deployed)
self.assertTrue(deployment.cleanuped)

View File

@ -17,6 +17,9 @@
"""Test fake deploy engines."""
import mock
import uuid
from rally import deploy
from rally.deploy.engines import fake_engine
from rally import test
@ -40,5 +43,7 @@ class TestFakeDeployEngine(test.NoDBTestCase):
fake_engine.FakeEngine({}).cleanup()
def test_fake_engine_is_in_factory(self):
engine = deploy.EngineFactory.get_engine('FakeEngine', {})
with mock.patch('rally.db'):
engine = deploy.EngineFactory.get_engine('FakeEngine',
uuid.uuid4(), {})
self.assertIsInstance(engine, fake_engine.FakeEngine)

View File

@ -0,0 +1,92 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013: Mirantis Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Test task status update."""
import mock
import uuid
from rally import consts
from rally import deploy
from rally import test
class FakeFailure(Exception):
pass
class EngineFailedDeploy(deploy.engines.fake_engine.FakeEngine):
def deploy(self):
raise FakeFailure('fake deploy failed')
class EngineFailedCleanup(deploy.engines.fake_engine.FakeEngine):
def cleanup(self):
raise FakeFailure('fake deploy failed')
get_engine = deploy.EngineFactory.get_engine
class TaskStatusTestCase(test.NoDBTestCase):
def test_task_status_basic_chain(self):
task_uuid = str(uuid.uuid4())
with mock.patch('rally.deploy.engine.db') as mock_obj:
with get_engine('FakeEngine', task_uuid, {}):
pass
s = consts.TaskStatus
expected = [
mock.call.task_create({'uuid': task_uuid}),
mock.call.task_update(task_uuid, {'status': s.DEPLOY_STARTED}),
mock.call.task_update(task_uuid, {'status': s.DEPLOY_FINISHED}),
mock.call.task_update(task_uuid, {'status': s.CLEANUP}),
mock.call.task_update(task_uuid, {'status': s.FINISHED}),
]
self.assertEqual(mock_obj.mock_calls, expected)
def _test_failure(self, task_uuid, engine, expected_calls):
with mock.patch('rally.deploy.engine.db') as mock_obj:
engine = get_engine(engine, task_uuid, {})
try:
with engine:
pass
except FakeFailure:
pass
self.assertEqual(mock_obj.mock_calls, expected_calls)
def test_task_status_failed_deploy(self):
task_uuid = str(uuid.uuid4())
s = consts.TaskStatus
expected = [
mock.call.task_create({'uuid': task_uuid}),
mock.call.task_update(task_uuid, {'status': s.DEPLOY_STARTED}),
]
self._test_failure(task_uuid, 'EngineFailedDeploy', expected)
def test_task_status_failed_cleanup(self):
task_uuid = str(uuid.uuid4())
s = consts.TaskStatus
expected = [
mock.call.task_create({'uuid': task_uuid}),
mock.call.task_update(task_uuid, {'status': s.DEPLOY_STARTED}),
mock.call.task_update(task_uuid, {'status': s.DEPLOY_FINISHED}),
mock.call.task_update(task_uuid, {'status': s.CLEANUP}),
]
self._test_failure(task_uuid, 'EngineFailedCleanup', expected)