Add usage of namedtuples for run and tests status
To get possibility to change status in one place, add consts.py with enum usage. Closes-Bug: #1404866 Change-Id: I6a7873bc2de919ed4cc99dcfe8e3e1febda606c0
This commit is contained in:
parent
db8d83701a
commit
ff9a20a192
|
@ -0,0 +1,43 @@
|
||||||
|
# Copyright 2016 Mirantis, Inc.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
|
||||||
|
import collections
|
||||||
|
|
||||||
|
|
||||||
|
def Enum(*values, **kwargs):
|
||||||
|
names = kwargs.get('names')
|
||||||
|
if names:
|
||||||
|
return collections.namedtuple('Enum', names)(*values)
|
||||||
|
return collections.namedtuple('Enum', values)(*values)
|
||||||
|
|
||||||
|
TESTRUN_STATUSES = Enum(
|
||||||
|
'stopped',
|
||||||
|
'restarted',
|
||||||
|
'finished',
|
||||||
|
'running'
|
||||||
|
)
|
||||||
|
|
||||||
|
TEST_STATUSES = Enum(
|
||||||
|
'stopped',
|
||||||
|
'restarted',
|
||||||
|
'finished',
|
||||||
|
'running',
|
||||||
|
'error',
|
||||||
|
'skipped',
|
||||||
|
'success',
|
||||||
|
'failure',
|
||||||
|
'wait_running',
|
||||||
|
'disabled'
|
||||||
|
)
|
|
@ -22,6 +22,7 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
|
||||||
|
from fuel_plugin import consts
|
||||||
from fuel_plugin.ostf_adapter.logger import ResultsLogger
|
from fuel_plugin.ostf_adapter.logger import ResultsLogger
|
||||||
from fuel_plugin.ostf_adapter.nose_plugin import nose_storage_plugin
|
from fuel_plugin.ostf_adapter.nose_plugin import nose_storage_plugin
|
||||||
from fuel_plugin.ostf_adapter.nose_plugin import nose_test_runner
|
from fuel_plugin.ostf_adapter.nose_plugin import nose_test_runner
|
||||||
|
@ -114,7 +115,7 @@ class NoseDriver(object):
|
||||||
except Exception:
|
except Exception:
|
||||||
LOG.exception('Test run ID: %s', test_run_id)
|
LOG.exception('Test run ID: %s', test_run_id)
|
||||||
finally:
|
finally:
|
||||||
updated_data = {'status': 'finished',
|
updated_data = {'status': consts.TESTRUN_STATUSES.finished,
|
||||||
'pid': None}
|
'pid': None}
|
||||||
|
|
||||||
models.TestRun.update_test_run(
|
models.TestRun.update_test_run(
|
||||||
|
|
|
@ -22,6 +22,7 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
|
||||||
|
from fuel_plugin import consts
|
||||||
from fuel_plugin.ostf_adapter.nose_plugin import nose_utils
|
from fuel_plugin.ostf_adapter.nose_plugin import nose_utils
|
||||||
from fuel_plugin.ostf_adapter.storage import models
|
from fuel_plugin.ostf_adapter.storage import models
|
||||||
|
|
||||||
|
@ -72,7 +73,7 @@ class StoragePlugin(plugins.Plugin):
|
||||||
test_id,
|
test_id,
|
||||||
data
|
data
|
||||||
)
|
)
|
||||||
if data['status'] != 'running':
|
if data['status'] != consts.TEST_STATUSES.running:
|
||||||
test_name = nose_utils.get_description(test)["title"]
|
test_name = nose_utils.get_description(test)["title"]
|
||||||
self.results_log.log_results(
|
self.results_log.log_results(
|
||||||
test_id,
|
test_id,
|
||||||
|
@ -93,11 +94,11 @@ class StoragePlugin(plugins.Plugin):
|
||||||
if err:
|
if err:
|
||||||
exc_type, exc_value, exc_traceback = err
|
exc_type, exc_value, exc_traceback = err
|
||||||
|
|
||||||
if not status == 'error':
|
if not status == consts.TEST_STATUSES.error:
|
||||||
data['step'], data['message'] = \
|
data['step'], data['message'] = \
|
||||||
nose_utils.format_failure_message(exc_value)
|
nose_utils.format_failure_message(exc_value)
|
||||||
|
|
||||||
if status != 'skipped':
|
if status != consts.TEST_STATUSES.skipped:
|
||||||
data['traceback'] = nose_utils.format_exception(err)
|
data['traceback'] = nose_utils.format_exception(err)
|
||||||
|
|
||||||
tests_to_update = nose_utils.get_tests_to_update(test)
|
tests_to_update = nose_utils.get_tests_to_update(test)
|
||||||
|
@ -107,26 +108,30 @@ class StoragePlugin(plugins.Plugin):
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
|
|
||||||
def addSuccess(self, test, capt=None):
|
def addSuccess(self, test, capt=None):
|
||||||
self._add_message(test, status='success')
|
self._add_message(test, status=consts.TEST_STATUSES.success)
|
||||||
|
|
||||||
def addFailure(self, test, err):
|
def addFailure(self, test, err):
|
||||||
LOG.error('%s', test.id(), exc_info=err)
|
LOG.error('%s', test.id(), exc_info=err)
|
||||||
self._add_message(test, err=err, status='failure')
|
self._add_message(
|
||||||
|
test, err=err, status=consts.TEST_STATUSES.failure)
|
||||||
|
|
||||||
def addError(self, test, err):
|
def addError(self, test, err):
|
||||||
if err[0] is AssertionError:
|
if err[0] is AssertionError:
|
||||||
LOG.error('%s', test.id(), exc_info=err)
|
LOG.error('%s', test.id(), exc_info=err)
|
||||||
self._add_message(test, err=err, status='failure')
|
self._add_message(
|
||||||
|
test, err=err, status=consts.TEST_STATUSES.failure)
|
||||||
elif issubclass(err[0], plugins.skip.SkipTest):
|
elif issubclass(err[0], plugins.skip.SkipTest):
|
||||||
LOG.warning('%s is skipped', test.id())
|
LOG.warning('%s is skipped', test.id())
|
||||||
self._add_message(test, err=err, status='skipped')
|
self._add_message(
|
||||||
|
test, err=err, status=consts.TEST_STATUSES.skipped)
|
||||||
else:
|
else:
|
||||||
LOG.error('%s', test.id(), exc_info=err)
|
LOG.error('%s', test.id(), exc_info=err)
|
||||||
self._add_message(test, err=err, status='error')
|
self._add_message(
|
||||||
|
test, err=err, status=consts.TEST_STATUSES.error)
|
||||||
|
|
||||||
def beforeTest(self, test):
|
def beforeTest(self, test):
|
||||||
self._start_time = time.time()
|
self._start_time = time.time()
|
||||||
self._add_message(test, status='running')
|
self._add_message(test, status=consts.TEST_STATUSES.running)
|
||||||
|
|
||||||
def describeTest(self, test):
|
def describeTest(self, test):
|
||||||
return test.test._testMethodDoc
|
return test.test._testMethodDoc
|
||||||
|
|
|
@ -22,6 +22,7 @@ from sqlalchemy.ext.associationproxy import association_proxy
|
||||||
from sqlalchemy.ext.declarative import declarative_base
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
from sqlalchemy.orm import joinedload, relationship, object_mapper
|
from sqlalchemy.orm import joinedload, relationship, object_mapper
|
||||||
|
|
||||||
|
from fuel_plugin import consts
|
||||||
from fuel_plugin.ostf_adapter import nose_plugin
|
from fuel_plugin.ostf_adapter import nose_plugin
|
||||||
from fuel_plugin.ostf_adapter.storage import engine
|
from fuel_plugin.ostf_adapter.storage import engine
|
||||||
from fuel_plugin.ostf_adapter.storage import fields
|
from fuel_plugin.ostf_adapter.storage import fields
|
||||||
|
@ -115,17 +116,6 @@ class Test(BASE):
|
||||||
|
|
||||||
__tablename__ = 'tests'
|
__tablename__ = 'tests'
|
||||||
|
|
||||||
STATES = (
|
|
||||||
'wait_running',
|
|
||||||
'running',
|
|
||||||
'failure',
|
|
||||||
'success',
|
|
||||||
'error',
|
|
||||||
'stopped',
|
|
||||||
'disabled',
|
|
||||||
'skipped'
|
|
||||||
)
|
|
||||||
|
|
||||||
id = sa.Column(sa.Integer(), primary_key=True)
|
id = sa.Column(sa.Integer(), primary_key=True)
|
||||||
name = sa.Column(sa.String(512))
|
name = sa.Column(sa.String(512))
|
||||||
title = sa.Column(sa.String(512))
|
title = sa.Column(sa.String(512))
|
||||||
|
@ -133,7 +123,7 @@ class Test(BASE):
|
||||||
duration = sa.Column(sa.String(512))
|
duration = sa.Column(sa.String(512))
|
||||||
message = sa.Column(sa.Text())
|
message = sa.Column(sa.Text())
|
||||||
traceback = sa.Column(sa.Text())
|
traceback = sa.Column(sa.Text())
|
||||||
status = sa.Column(sa.Enum(*STATES, name='test_states'))
|
status = sa.Column(sa.Enum(consts.TEST_STATUSES, name='test_states'))
|
||||||
step = sa.Column(sa.Integer())
|
step = sa.Column(sa.Integer())
|
||||||
time_taken = sa.Column(sa.Float())
|
time_taken = sa.Column(sa.Float())
|
||||||
meta = sa.Column(fields.JsonField())
|
meta = sa.Column(fields.JsonField())
|
||||||
|
@ -178,15 +168,19 @@ class Test(BASE):
|
||||||
update(data, synchronize_session='fetch')
|
update(data, synchronize_session='fetch')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def update_running_tests(cls, session, test_run_id, status='stopped'):
|
def update_running_tests(cls, session, test_run_id,
|
||||||
|
status=consts.TEST_STATUSES.stopped):
|
||||||
session.query(cls). \
|
session.query(cls). \
|
||||||
filter(cls.test_run_id == test_run_id,
|
filter(cls.test_run_id == test_run_id,
|
||||||
cls.status.in_(('running', 'wait_running'))). \
|
cls.status.in_(
|
||||||
|
(consts.TEST_STATUSES.running,
|
||||||
|
consts.TEST_STATUSES.wait_running))). \
|
||||||
update({'status': status}, synchronize_session='fetch')
|
update({'status': status}, synchronize_session='fetch')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def update_test_run_tests(cls, session, test_run_id,
|
def update_test_run_tests(cls, session, test_run_id,
|
||||||
tests_names, status='wait_running'):
|
tests_names,
|
||||||
|
status=consts.TEST_STATUSES.wait_running):
|
||||||
session.query(cls). \
|
session.query(cls). \
|
||||||
filter(cls.name.in_(tests_names),
|
filter(cls.name.in_(tests_names),
|
||||||
cls.test_run_id == test_run_id). \
|
cls.test_run_id == test_run_id). \
|
||||||
|
@ -205,9 +199,9 @@ class Test(BASE):
|
||||||
setattr(new_test, column.key, getattr(self, column.key))
|
setattr(new_test, column.key, getattr(self, column.key))
|
||||||
new_test.test_run_id = test_run.id
|
new_test.test_run_id = test_run.id
|
||||||
if predefined_tests and new_test.name not in predefined_tests:
|
if predefined_tests and new_test.name not in predefined_tests:
|
||||||
new_test.status = 'disabled'
|
new_test.status = consts.TEST_STATUSES.disabled
|
||||||
else:
|
else:
|
||||||
new_test.status = 'wait_running'
|
new_test.status = consts.TEST_STATUSES.wait_running
|
||||||
return new_test
|
return new_test
|
||||||
|
|
||||||
|
|
||||||
|
@ -215,14 +209,10 @@ class TestRun(BASE):
|
||||||
|
|
||||||
__tablename__ = 'test_runs'
|
__tablename__ = 'test_runs'
|
||||||
|
|
||||||
STATES = (
|
|
||||||
'running',
|
|
||||||
'finished'
|
|
||||||
)
|
|
||||||
|
|
||||||
id = sa.Column(sa.Integer(), primary_key=True)
|
id = sa.Column(sa.Integer(), primary_key=True)
|
||||||
cluster_id = sa.Column(sa.Integer(), nullable=False)
|
cluster_id = sa.Column(sa.Integer(), nullable=False)
|
||||||
status = sa.Column(sa.Enum(*STATES, name='test_run_states'),
|
status = sa.Column(sa.Enum(consts.TESTRUN_STATUSES,
|
||||||
|
name='test_run_states'),
|
||||||
nullable=False)
|
nullable=False)
|
||||||
meta = sa.Column(fields.JsonField())
|
meta = sa.Column(fields.JsonField())
|
||||||
started_at = sa.Column(sa.DateTime, default=datetime.datetime.utcnow)
|
started_at = sa.Column(sa.DateTime, default=datetime.datetime.utcnow)
|
||||||
|
@ -262,10 +252,10 @@ class TestRun(BASE):
|
||||||
@property
|
@property
|
||||||
def enabled_tests(self):
|
def enabled_tests(self):
|
||||||
return [test.name for test
|
return [test.name for test
|
||||||
in self.tests if test.status != 'disabled']
|
in self.tests if test.status != consts.TEST_STATUSES.disabled]
|
||||||
|
|
||||||
def is_finished(self):
|
def is_finished(self):
|
||||||
return self.status == 'finished'
|
return self.status == consts.TESTRUN_STATUSES.finished
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def frontend(self):
|
def frontend(self):
|
||||||
|
@ -284,7 +274,8 @@ class TestRun(BASE):
|
||||||
return test_run_data
|
return test_run_data
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def add_test_run(cls, session, test_set, cluster_id, status='running',
|
def add_test_run(cls, session, test_set, cluster_id,
|
||||||
|
status=consts.TESTRUN_STATUSES.running,
|
||||||
tests=None):
|
tests=None):
|
||||||
"""Creates new test_run object with given data
|
"""Creates new test_run object with given data
|
||||||
and makes copy of tests that will be bound
|
and makes copy of tests that will be bound
|
||||||
|
@ -350,7 +341,7 @@ class TestRun(BASE):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def update_test_run(cls, session, test_run_id, updated_data):
|
def update_test_run(cls, session, test_run_id, updated_data):
|
||||||
if updated_data.get('status') in ['finished']:
|
if updated_data.get('status') in [consts.TESTRUN_STATUSES.finished]:
|
||||||
updated_data['ended_at'] = datetime.datetime.utcnow()
|
updated_data['ended_at'] = datetime.datetime.utcnow()
|
||||||
|
|
||||||
session.query(cls). \
|
session.query(cls). \
|
||||||
|
@ -392,7 +383,7 @@ class TestRun(BASE):
|
||||||
self.cluster_id):
|
self.cluster_id):
|
||||||
plugin = nose_plugin.get_plugin(self.test_set.driver)
|
plugin = nose_plugin.get_plugin(self.test_set.driver)
|
||||||
|
|
||||||
self.update('running')
|
self.update(consts.TEST_STATUSES.running)
|
||||||
if tests:
|
if tests:
|
||||||
Test.update_test_run_tests(
|
Test.update_test_run_tests(
|
||||||
session, self.id, tests)
|
session, self.id, tests)
|
||||||
|
@ -409,5 +400,5 @@ class TestRun(BASE):
|
||||||
killed = plugin.kill(self)
|
killed = plugin.kill(self)
|
||||||
if killed:
|
if killed:
|
||||||
Test.update_running_tests(
|
Test.update_running_tests(
|
||||||
session, self.id, status='stopped')
|
session, self.id, status=consts.TEST_STATUSES.stopped)
|
||||||
return self.frontend
|
return self.frontend
|
||||||
|
|
|
@ -29,6 +29,7 @@ from pecan import rest
|
||||||
from sqlalchemy import func
|
from sqlalchemy import func
|
||||||
from sqlalchemy.orm import joinedload
|
from sqlalchemy.orm import joinedload
|
||||||
|
|
||||||
|
from fuel_plugin import consts
|
||||||
from fuel_plugin.ostf_adapter import mixins
|
from fuel_plugin.ostf_adapter import mixins
|
||||||
from fuel_plugin.ostf_adapter.storage import models
|
from fuel_plugin.ostf_adapter.storage import models
|
||||||
|
|
||||||
|
@ -190,9 +191,9 @@ class TestrunsController(BaseRestController):
|
||||||
|
|
||||||
test_run = models.TestRun.get_test_run(request.session,
|
test_run = models.TestRun.get_test_run(request.session,
|
||||||
test_run['id'])
|
test_run['id'])
|
||||||
if status == 'stopped':
|
if status == consts.TESTRUN_STATUSES.stopped:
|
||||||
data.append(test_run.stop(request.session))
|
data.append(test_run.stop(request.session))
|
||||||
elif status == 'restarted':
|
elif status == consts.TESTRUN_STATUSES.restarted:
|
||||||
data.append(test_run.restart(request.session,
|
data.append(test_run.restart(request.session,
|
||||||
cfg.CONF.adapter.dbpath,
|
cfg.CONF.adapter.dbpath,
|
||||||
ostf_os_access_creds,
|
ostf_os_access_creds,
|
||||||
|
|
Loading…
Reference in New Issue