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:
parent
b4d0d04856
commit
a6297b14ca
1
.gitignore
vendored
1
.gitignore
vendored
@ -26,6 +26,7 @@ pip-log.txt
|
||||
.tox
|
||||
nosetests.xml
|
||||
.testrepository
|
||||
*.sqlite
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
|
@ -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'
|
||||
|
@ -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)
|
||||
|
@ -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,25 +45,25 @@ class EngineFactoryTestCase(test.NoDBTestCase):
|
||||
pass
|
||||
|
||||
class EngineFake1(EngineMixIn, deploy.EngineFactory):
|
||||
def __init__(self, config):
|
||||
pass
|
||||
pass
|
||||
|
||||
class EngineFake2(EngineMixIn, deploy.EngineFactory):
|
||||
def __init__(self, config):
|
||||
pass
|
||||
pass
|
||||
|
||||
class EngineFake3(EngineFake2):
|
||||
def __init__(self, config):
|
||||
pass
|
||||
pass
|
||||
|
||||
return [EngineFake1, EngineFake2, EngineFake3]
|
||||
|
||||
def test_get_engine(self):
|
||||
engines = self._create_fake_engines()
|
||||
for e in engines:
|
||||
engine_inst = deploy.EngineFactory.get_engine(e.__name__, None)
|
||||
# TODO(boris-42): make it work through assertIsInstance
|
||||
self.assertEqual(str(type(engine_inst)), str(e))
|
||||
with mock.patch('rally.deploy.engine.db'):
|
||||
for e in engines:
|
||||
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))
|
||||
|
||||
def test_get_available_engines(self):
|
||||
engines = set([e.__name__ for e in self._create_fake_engines()])
|
||||
@ -80,7 +87,9 @@ class EngineFactoryTestCase(test.NoDBTestCase):
|
||||
def cleanup(self):
|
||||
self.cleanuped = True
|
||||
|
||||
with deploy.EngineFactory.get_engine('A', None) as deployment:
|
||||
self.assertTrue(deployment.deployed)
|
||||
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)
|
||||
|
@ -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', {})
|
||||
self.assertIsInstance(engine, fake_engine.FakeEngine)
|
||||
with mock.patch('rally.db'):
|
||||
engine = deploy.EngineFactory.get_engine('FakeEngine',
|
||||
uuid.uuid4(), {})
|
||||
self.assertIsInstance(engine, fake_engine.FakeEngine)
|
||||
|
92
tests/deploy/test_task_status.py
Normal file
92
tests/deploy/test_task_status.py
Normal 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)
|
Loading…
Reference in New Issue
Block a user