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
|
.tox
|
||||||
nosetests.xml
|
nosetests.xml
|
||||||
.testrepository
|
.testrepository
|
||||||
|
*.sqlite
|
||||||
|
|
||||||
# Translations
|
# Translations
|
||||||
*.mo
|
*.mo
|
||||||
|
@ -47,6 +47,7 @@ class _TaskStatus(_Immutable, _Enum):
|
|||||||
|
|
||||||
REPO_TOOL_GETTING_REPOS = 'repo_tool->getting_repos'
|
REPO_TOOL_GETTING_REPOS = 'repo_tool->getting_repos'
|
||||||
|
|
||||||
|
DEPLOY_STARTED = 'deploy->started'
|
||||||
DEPLOY_CREATING_VENV = 'deploy->create_venv_to_deploy_openstack'
|
DEPLOY_CREATING_VENV = 'deploy->create_venv_to_deploy_openstack'
|
||||||
DEPLOY_BUILDING_OPENSTACK_IN_VENV = 'deploy->building_openstack_in_venv'
|
DEPLOY_BUILDING_OPENSTACK_IN_VENV = 'deploy->building_openstack_in_venv'
|
||||||
DEPLOY_BUILDING_IMAGE = 'deploy->building_images_with_openstack'
|
DEPLOY_BUILDING_IMAGE = 'deploy->building_images_with_openstack'
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
import abc
|
import abc
|
||||||
|
|
||||||
|
from rally import consts
|
||||||
|
from rally import db
|
||||||
from rally import exceptions
|
from rally import exceptions
|
||||||
from rally import utils
|
from rally import utils
|
||||||
|
|
||||||
@ -49,11 +51,14 @@ class EngineFactory(object):
|
|||||||
__metaclass__ = abc.ABCMeta
|
__metaclass__ = abc.ABCMeta
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_engine(name, config):
|
def get_engine(name, uuid, config):
|
||||||
"""Returns instance of deploy engine with corresponding name."""
|
"""Returns instance of deploy engine with corresponding name."""
|
||||||
for engine in utils.itersubclasses(EngineFactory):
|
for engine in utils.itersubclasses(EngineFactory):
|
||||||
if name == engine.__name__:
|
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)
|
raise exceptions.NoSuchEngine(engine_name=name)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -69,8 +74,16 @@ class EngineFactory(object):
|
|||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
"""Cleanup OpenStack deployment."""
|
"""Cleanup OpenStack deployment."""
|
||||||
|
|
||||||
|
def update_status(self, status):
|
||||||
|
db.task_update(self.task_uuid, {'status': status})
|
||||||
|
|
||||||
def __enter__(self):
|
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):
|
def __exit__(self, type, value, traceback):
|
||||||
|
self.update_status(consts.TaskStatus.CLEANUP)
|
||||||
self.cleanup()
|
self.cleanup()
|
||||||
|
self.update_status(consts.TaskStatus.FINISHED)
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
|
|
||||||
"""Test for deploy engines."""
|
"""Test for deploy engines."""
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import uuid
|
||||||
|
|
||||||
from rally import deploy
|
from rally import deploy
|
||||||
from rally import exceptions
|
from rally import exceptions
|
||||||
from rally import test
|
from rally import test
|
||||||
@ -26,11 +29,15 @@ class EngineFactoryTestCase(test.NoDBTestCase):
|
|||||||
|
|
||||||
def test_get_engine_not_found(self):
|
def test_get_engine_not_found(self):
|
||||||
self.assertRaises(exceptions.NoSuchEngine,
|
self.assertRaises(exceptions.NoSuchEngine,
|
||||||
deploy.EngineFactory.get_engine,
|
deploy.EngineFactory.get_engine, uuid.uuid4(),
|
||||||
"non_existing_engine", None)
|
"non_existing_engine", None)
|
||||||
|
|
||||||
def _create_fake_engines(self):
|
def _create_fake_engines(self):
|
||||||
class EngineMixIn(object):
|
class EngineMixIn(object):
|
||||||
|
|
||||||
|
def __init__(self, config):
|
||||||
|
pass
|
||||||
|
|
||||||
def deploy(self):
|
def deploy(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -38,23 +45,23 @@ class EngineFactoryTestCase(test.NoDBTestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
class EngineFake1(EngineMixIn, deploy.EngineFactory):
|
class EngineFake1(EngineMixIn, deploy.EngineFactory):
|
||||||
def __init__(self, config):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class EngineFake2(EngineMixIn, deploy.EngineFactory):
|
class EngineFake2(EngineMixIn, deploy.EngineFactory):
|
||||||
def __init__(self, config):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class EngineFake3(EngineFake2):
|
class EngineFake3(EngineFake2):
|
||||||
def __init__(self, config):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return [EngineFake1, EngineFake2, EngineFake3]
|
return [EngineFake1, EngineFake2, EngineFake3]
|
||||||
|
|
||||||
def test_get_engine(self):
|
def test_get_engine(self):
|
||||||
engines = self._create_fake_engines()
|
engines = self._create_fake_engines()
|
||||||
|
with mock.patch('rally.deploy.engine.db'):
|
||||||
for e in engines:
|
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
|
# TODO(boris-42): make it work through assertIsInstance
|
||||||
self.assertEqual(str(type(engine_inst)), str(e))
|
self.assertEqual(str(type(engine_inst)), str(e))
|
||||||
|
|
||||||
@ -80,7 +87,9 @@ class EngineFactoryTestCase(test.NoDBTestCase):
|
|||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
self.cleanuped = True
|
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.deployed)
|
||||||
|
|
||||||
self.assertTrue(deployment.cleanuped)
|
self.assertTrue(deployment.cleanuped)
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
|
|
||||||
"""Test fake deploy engines."""
|
"""Test fake deploy engines."""
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import uuid
|
||||||
|
|
||||||
from rally import deploy
|
from rally import deploy
|
||||||
from rally.deploy.engines import fake_engine
|
from rally.deploy.engines import fake_engine
|
||||||
from rally import test
|
from rally import test
|
||||||
@ -40,5 +43,7 @@ class TestFakeDeployEngine(test.NoDBTestCase):
|
|||||||
fake_engine.FakeEngine({}).cleanup()
|
fake_engine.FakeEngine({}).cleanup()
|
||||||
|
|
||||||
def test_fake_engine_is_in_factory(self):
|
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)
|
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…
x
Reference in New Issue
Block a user