Ejemplo n.º 1
0
class TestSet(BASE):

    __tablename__ = 'test_sets'

    id = sa.Column(sa.String(128), primary_key=True)
    description = sa.Column(sa.String(256))
    test_path = sa.Column(sa.String(256))
    driver = sa.Column(sa.String(128))
    additional_arguments = sa.Column(fields.ListField())
    cleanup_path = sa.Column(sa.String(128))
    meta = sa.Column(fields.JsonField())
    deployment_tags = sa.Column(ARRAY(sa.String(64)))

    tests = relationship('Test',
                         backref='test_set',
                         order_by='Test.name',
                         cascade='delete')

    @property
    def frontend(self):
        return {'id': self.id, 'name': self.description}

    @classmethod
    def get_test_set(cls, session, test_set):
        return session.query(cls)\
            .filter_by(id=test_set)\
            .first()
Ejemplo n.º 2
0
class TestSet(BASE):

    __tablename__ = 'test_sets'

    id = sa.Column(sa.String(128), primary_key=True)
    description = sa.Column(sa.String(256))
    test_path = sa.Column(sa.String(256))
    driver = sa.Column(sa.String(128))
    additional_arguments = sa.Column(fields.ListField())
    cleanup_path = sa.Column(sa.String(128))
    meta = sa.Column(fields.JsonField())
    deployment_tags = sa.Column(ARRAY(sa.String(64)))
    test_runs_ordering_priority = sa.Column(sa.Integer)

    # list of test sets that cannot be executed simultaneously
    # with current test set
    exclusive_testsets = sa.Column(ARRAY(sa.String(128)))

    available_since_release = sa.Column(sa.String(64), default="")

    tests = relationship('Test',
                         backref='test_set',
                         order_by='Test.name',
                         cascade='delete')

    @property
    def frontend(self):
        return {'id': self.id, 'name': self.description}

    @classmethod
    def get_test_set(cls, session, test_set):
        return session.query(cls)\
            .filter_by(id=test_set)\
            .first()
Ejemplo n.º 3
0
def upgrade():
    ### commands auto generated by Alembic - please adjust! ###
    op.add_column(
        'test_runs',
        sa.Column('test_set_id', sa.String(length=128), nullable=True))
    op.add_column('test_runs',
                  sa.Column('meta', fields.JsonField(), nullable=True))
    op.add_column('test_runs',
                  sa.Column('cluster_id', sa.Integer(), nullable=False))
    op.drop_column('test_runs', u'type')
    op.drop_column('test_runs', u'stats')
    op.drop_column('test_runs', u'external_id')
    op.drop_column('test_runs', u'data')
    op.alter_column('test_runs',
                    'status',
                    existing_type=sa.VARCHAR(length=128),
                    nullable=False)
    op.add_column(
        'test_sets',
        sa.Column('cleanup_path', sa.String(length=128), nullable=True))
    op.add_column('test_sets',
                  sa.Column('meta', fields.JsonField(), nullable=True))
    op.add_column('test_sets',
                  sa.Column('driver', sa.String(length=128), nullable=True))
    op.add_column(
        'test_sets',
        sa.Column('additional_arguments', fields.ListField(), nullable=True))
    op.add_column('test_sets',
                  sa.Column('test_path', sa.String(length=256), nullable=True))
    op.drop_column('test_sets', u'data')
    op.add_column('tests', sa.Column('description', sa.Text(), nullable=True))
    op.add_column('tests', sa.Column('traceback', sa.Text(), nullable=True))
    op.add_column('tests', sa.Column('step', sa.Integer(), nullable=True))
    op.add_column('tests', sa.Column('meta', fields.JsonField(),
                                     nullable=True))
    op.add_column('tests',
                  sa.Column('duration', sa.String(length=512), nullable=True))
    op.add_column('tests', sa.Column('message', sa.Text(), nullable=True))
    op.add_column('tests', sa.Column('time_taken', sa.Float(), nullable=True))
    op.drop_column('tests', u'taken')
    op.drop_column('tests', u'data')
Ejemplo n.º 4
0
class TestRun(BASE):

    __tablename__ = 'test_runs'

    STATES = ('running', 'finished')

    id = sa.Column(sa.Integer(), primary_key=True)
    cluster_id = sa.Column(sa.Integer(), nullable=False)
    status = sa.Column(sa.Enum(*STATES, name='test_run_states'),
                       nullable=False)
    meta = sa.Column(fields.JsonField())
    started_at = sa.Column(sa.DateTime, default=datetime.datetime.utcnow)
    ended_at = sa.Column(sa.DateTime)
    pid = sa.Column(sa.Integer)

    test_set_id = sa.Column(sa.String(128))
    cluster_id = sa.Column(sa.Integer)

    __table_args__ = (sa.ForeignKeyConstraint(['test_set_id', 'cluster_id'], [
        'cluster_testing_pattern.test_set_id',
        'cluster_testing_pattern.cluster_id'
    ],
                                              ondelete='CASCADE'), {})

    cluster_testing_pattern = relationship('ClusterTestingPattern')
    test_set = association_proxy('cluster_testing_pattern', 'test_set')

    tests = relationship('Test',
                         backref='test_run',
                         order_by='Test.name',
                         cascade='delete')

    def update(self, status):
        self.status = status
        if status == 'finished':
            self.ended_at = datetime.datetime.utcnow()

    @property
    def enabled_tests(self):
        return [test.name for test in self.tests if test.status != 'disabled']

    def is_finished(self):
        return self.status == 'finished'

    @property
    def frontend(self):
        test_run_data = {
            'id': self.id,
            'testset': self.test_set_id,
            'meta': self.meta,
            'cluster_id': self.cluster_id,
            'status': self.status,
            'started_at': self.started_at,
            'ended_at': self.ended_at,
            'tests': []
        }
        if self.tests:
            test_run_data['tests'] = [test.frontend for test in self.tests]
        return test_run_data

    @classmethod
    def add_test_run(cls,
                     session,
                     test_set,
                     cluster_id,
                     status='running',
                     tests=None):
        """Creates new test_run object with given data
        and makes copy of tests that will be bound
        with this test_run. Copying is performed by
        copy_test method of Test class.
        """
        predefined_tests = tests or []
        tests_names = session.query(ClusterTestingPattern.tests)\
            .filter_by(test_set_id=test_set, cluster_id=cluster_id)\
            .scalar()

        tests = session.query(Test)\
            .filter(Test.name.in_(tests_names))\
            .filter_by(test_set_id=test_set)\
            .filter_by(test_run_id=None)

        test_run = cls(test_set_id=test_set,
                       cluster_id=cluster_id,
                       status=status)
        session.add(test_run)

        for test in tests:
            new_test = test.copy_test(test_run, predefined_tests)
            session.add(new_test)
            test_run.tests.append(new_test)
        session.flush()

        return test_run

    @classmethod
    def get_last_test_run(cls, session, test_set, cluster_id):
        test_run = session.query(cls). \
            filter_by(cluster_id=cluster_id, test_set_id=test_set). \
            order_by(desc(cls.id)).first()
        return test_run

    @classmethod
    def get_test_results(cls):
        session = engine.get_session()
        test_runs = session.query(cls). \
            options(joinedload('tests')). \
            order_by(desc(cls.id))
        session.commit()
        session.close()
        return test_runs

    @classmethod
    def get_test_run(cls, session, test_run_id, joined=False):
        if not joined:
            test_run = session.query(cls). \
                filter_by(id=test_run_id).first()
        else:
            test_run = session.query(cls). \
                options(joinedload('tests')). \
                filter_by(id=test_run_id).first()
        return test_run

    @classmethod
    def update_test_run(cls, session, test_run_id, updated_data):
        if updated_data.get('status') in ['finished']:
            updated_data['ended_at'] = datetime.datetime.utcnow()

        session.query(cls). \
            filter(cls.id == test_run_id). \
            update(updated_data, synchronize_session='fetch')

    @classmethod
    def is_last_running(cls, session, test_set, cluster_id):
        """Checks whether there one can perform creation of new
        test_run by testing of existing of test_run object
        with given data or test_run with 'finished' status.
        """
        test_run = cls.get_last_test_run(session, test_set, cluster_id)
        return not bool(test_run) or test_run.is_finished()

    @classmethod
    def start(cls, session, test_set, metadata, tests, dbpath, token=None):
        plugin = nose_plugin.get_plugin(test_set.driver)
        if cls.is_last_running(session, test_set.id, metadata['cluster_id']):

            test_run = cls.add_test_run(session,
                                        test_set.id,
                                        metadata['cluster_id'],
                                        tests=tests)

            plugin.run(test_run,
                       test_set,
                       dbpath,
                       metadata.get('ostf_os_access_creds'),
                       token=token)

            return test_run.frontend
        return {}

    def restart(self,
                session,
                dbpath,
                ostf_os_access_creds,
                tests=None,
                token=None):
        """Restart test run with
            if tests given they will be enabled
        """
        if TestRun.is_last_running(session, self.test_set_id, self.cluster_id):
            plugin = nose_plugin.get_plugin(self.test_set.driver)

            self.update('running')
            if tests:
                Test.update_test_run_tests(session, self.id, tests)

            plugin.run(self,
                       self.test_set,
                       dbpath,
                       ostf_os_access_creds,
                       tests,
                       token=token)
            return self.frontend
        return {}

    def stop(self, session):
        """Stop test run if running
        """
        plugin = nose_plugin.get_plugin(self.test_set.driver)
        killed = plugin.kill(self)
        if killed:
            Test.update_running_tests(session, self.id, status='stopped')
        return self.frontend
Ejemplo n.º 5
0
class Test(BASE):

    __tablename__ = 'tests'

    STATES = ('wait_running', 'running', 'failure', 'success', 'error',
              'stopped', 'disabled', 'skipped')

    id = sa.Column(sa.Integer(), primary_key=True)
    name = sa.Column(sa.String(512))
    title = sa.Column(sa.String(512))
    description = sa.Column(sa.Text())
    duration = sa.Column(sa.String(512))
    message = sa.Column(sa.Text())
    traceback = sa.Column(sa.Text())
    status = sa.Column(sa.Enum(*STATES, name='test_states'))
    step = sa.Column(sa.Integer())
    time_taken = sa.Column(sa.Float())
    meta = sa.Column(fields.JsonField())
    deployment_tags = sa.Column(ARRAY(sa.String(64)))
    available_since_release = sa.Column(sa.String(64), default="")

    test_run_id = sa.Column(sa.Integer(),
                            sa.ForeignKey('test_runs.id', ondelete='CASCADE'))

    test_set_id = sa.Column(sa.String(length=128),
                            sa.ForeignKey('test_sets.id', ondelete='CASCADE'))

    @property
    def frontend(self):
        return {
            'id': self.name,
            'testset': self.test_set_id,
            'name': self.title,
            'description': self.description,
            'duration': self.duration,
            'message': self.message,
            'step': self.step,
            'status': self.status,
            'taken': self.time_taken
        }

    @classmethod
    def add_result(cls, session, test_run_id, test_name, data):
        session.query(cls).\
            filter(cls.name == test_name,
                   cls.test_run_id == test_run_id).\
            update(data, synchronize_session='fetch')

    @classmethod
    def update_running_tests(cls, session, test_run_id, status='stopped'):
        session.query(cls). \
            filter(cls.test_run_id == test_run_id,
                   cls.status.in_(('running', 'wait_running'))). \
            update({'status': status}, synchronize_session='fetch')

    @classmethod
    def update_test_run_tests(cls,
                              session,
                              test_run_id,
                              tests_names,
                              status='wait_running'):
        session.query(cls). \
            filter(cls.name.in_(tests_names),
                   cls.test_run_id == test_run_id). \
            update({'status': status, 'time_taken': None},
                   synchronize_session='fetch')

    def copy_test(self, test_run, predefined_tests):
        """Performs copying of tests for newly created
        test_run.
        """
        new_test = self.__class__()
        mapper = object_mapper(self)
        primary_keys = set([col.key for col in mapper.primary_key])
        for column in mapper.iterate_properties:
            if column.key not in primary_keys:
                setattr(new_test, column.key, getattr(self, column.key))
        new_test.test_run_id = test_run.id
        if predefined_tests and new_test.name not in predefined_tests:
            new_test.status = 'disabled'
        else:
            new_test.status = 'wait_running'
        return new_test
Ejemplo n.º 6
0
def upgrade():
    op.create_table(
        'cluster_state',
        sa.Column('id', sa.Integer(), autoincrement=False, nullable=False),
        sa.Column('deployment_tags', postgresql.ARRAY(sa.String(length=64)),
                  nullable=True),
        sa.PrimaryKeyConstraint('id')
    )
    op.create_table(
        'test_sets',
        sa.Column('id', sa.String(length=128), nullable=False),
        sa.Column('description', sa.String(length=256), nullable=True),
        sa.Column('test_path', sa.String(length=256), nullable=True),
        sa.Column('driver', sa.String(length=128), nullable=True),
        sa.Column('additional_arguments', fields.ListField(), nullable=True),
        sa.Column('cleanup_path', sa.String(length=128), nullable=True),
        sa.Column('meta', fields.JsonField(), nullable=True),
        sa.Column('deployment_tags', postgresql.ARRAY(sa.String(length=64)),
                  nullable=True),
        sa.Column('test_runs_ordering_priority', sa.Integer(), nullable=True),
        sa.PrimaryKeyConstraint('id')
    )
    op.create_table(
        'cluster_testing_pattern',
        sa.Column('cluster_id', sa.Integer(), nullable=False),
        sa.Column('test_set_id', sa.String(length=128), nullable=False),
        sa.Column('tests', postgresql.ARRAY(sa.String(length=512)),
                  nullable=True),
        sa.ForeignKeyConstraint(['cluster_id'], ['cluster_state.id'], ),
        sa.ForeignKeyConstraint(['test_set_id'], ['test_sets.id'], ),
        sa.PrimaryKeyConstraint('cluster_id', 'test_set_id')
    )
    op.create_table(
        'test_runs',
        sa.Column('id', sa.Integer(), nullable=False),
        sa.Column('status',
                  sa.Enum('running', 'finished', name='test_run_states'),
                  nullable=False),
        sa.Column('meta', fields.JsonField(), nullable=True),
        sa.Column('started_at', sa.DateTime(), nullable=True),
        sa.Column('ended_at', sa.DateTime(), nullable=True),
        sa.Column('test_set_id', sa.String(length=128), nullable=True),
        sa.Column('cluster_id', sa.Integer(), nullable=True),
        sa.ForeignKeyConstraint(['test_set_id', 'cluster_id'],
                                ['cluster_testing_pattern.test_set_id',
                                 'cluster_testing_pattern.cluster_id'],
                                ondelete='CASCADE'),
        sa.PrimaryKeyConstraint('id')
    )
    op.create_table(
        'tests',
        sa.Column('id', sa.Integer(), nullable=False),
        sa.Column('name', sa.String(length=512), nullable=True),
        sa.Column('title', sa.String(length=512), nullable=True),
        sa.Column('description', sa.Text(), nullable=True),
        sa.Column('duration', sa.String(length=512), nullable=True),
        sa.Column('message', sa.Text(), nullable=True),
        sa.Column('traceback', sa.Text(), nullable=True),
        sa.Column('status', sa.Enum('wait_running', 'running', 'failure',
                                    'success', 'error', 'stopped',
                                    'disabled', 'skipped', name='test_states'),
                  nullable=True),
        sa.Column('step', sa.Integer(), nullable=True),
        sa.Column('time_taken', sa.Float(), nullable=True),
        sa.Column('meta', fields.JsonField(), nullable=True),
        sa.Column('deployment_tags', postgresql.ARRAY(sa.String(length=64)),
                  nullable=True),
        sa.Column('test_run_id', sa.Integer(), nullable=True),
        sa.Column('test_set_id', sa.String(length=128), nullable=True),
        sa.ForeignKeyConstraint(['test_run_id'], ['test_runs.id'],
                                ondelete='CASCADE'),
        sa.ForeignKeyConstraint(['test_set_id'], ['test_sets.id'],
                                ondelete='CASCADE'),
        sa.PrimaryKeyConstraint('id')
    )
Ejemplo n.º 7
0
class TestRun(BASE):

    __tablename__ = 'test_runs'

    STATES = ('running', 'finished')

    id = sa.Column(sa.Integer(), primary_key=True)
    cluster_id = sa.Column(sa.Integer(), nullable=False)
    status = sa.Column(sa.Enum(*STATES, name='test_run_states'),
                       nullable=False)
    meta = sa.Column(fields.JsonField())
    started_at = sa.Column(sa.DateTime, default=datetime.utcnow)
    ended_at = sa.Column(sa.DateTime)
    test_set_id = sa.Column(sa.String(128), sa.ForeignKey('test_sets.id'))

    test_set = relationship('TestSet', backref='test_runs')
    tests = relationship('Test', backref='test_run', order_by='Test.name')

    def update(self, session, status):
        self.status = status
        if status == 'finished':
            self.ended_at = datetime.utcnow()
        session.add(self)

    @property
    def enabled_tests(self):
        return [test.name for test in self.tests if test.status != 'disabled']

    def is_finished(self):
        return self.status == 'finished'

    @property
    def frontend(self):
        test_run_data = {
            'id': self.id,
            'testset': self.test_set_id,
            'meta': self.meta,
            'cluster_id': self.cluster_id,
            'status': self.status,
            'started_at': self.started_at,
            'ended_at': self.ended_at,
            'tests': []
        }
        if self.tests:
            test_run_data['tests'] = [test.frontend for test in self.tests]
        return test_run_data

    @classmethod
    def add_test_run(cls,
                     session,
                     test_set,
                     cluster_id,
                     status='running',
                     tests=None):
        predefined_tests = tests or []
        tests = session.query(Test).filter_by(test_set_id=test_set,
                                              test_run_id=None)
        test_run = cls(test_set_id=test_set,
                       cluster_id=cluster_id,
                       status=status)
        session.add(test_run)
        for test in tests:
            session.add(test.copy_test(test_run, predefined_tests))
        return test_run

    @classmethod
    def get_last_test_run(cls, session, test_set, cluster_id):
        test_run = session.query(cls). \
            filter_by(cluster_id=cluster_id, test_set_id=test_set). \
            order_by(desc(cls.id)).first()
        return test_run

    @classmethod
    def get_test_results(cls):
        session = engine.get_session()
        test_runs = session.query(cls). \
            options(joinedload('tests')). \
            order_by(desc(cls.id))
        session.commit()
        session.close()
        return test_runs

    @classmethod
    def get_test_run(cls, session, test_run_id, joined=False):
        if not joined:
            test_run = session.query(cls). \
                filter_by(id=test_run_id).first()
        else:
            test_run = session.query(cls). \
                options(joinedload('tests')). \
                filter_by(id=test_run_id).first()
        return test_run

    @classmethod
    def update_test_run(cls, session, test_run_id, status=None):
        updated_data = {}
        if status:
            updated_data['status'] = status
        if status in ['finished']:
            updated_data['ended_at'] = datetime.utcnow()
        session.query(cls). \
            filter(cls.id == test_run_id). \
            update(updated_data, synchronize_session=False)

    @classmethod
    def is_last_running(cls, session, test_set, cluster_id):
        test_run = cls.get_last_test_run(session, test_set, cluster_id)
        return not bool(test_run) or test_run.is_finished()

    @classmethod
    def start(cls, session, test_set, metadata, tests):
        plugin = nose_plugin.get_plugin(test_set.driver)
        if cls.is_last_running(session, test_set.id, metadata['cluster_id']):
            test_run = cls.add_test_run(session,
                                        test_set.id,
                                        metadata['cluster_id'],
                                        tests=tests)
            plugin.run(test_run, test_set)
            return test_run.frontend
        return {}

    def restart(self, session, tests=None):
        """Restart test run with
            if tests given they will be enabled
        """
        if TestRun.is_last_running(session, self.test_set_id, self.cluster_id):
            plugin = nose_plugin.get_plugin(self.test_set.driver)
            self.update(session, 'running')
            if tests:
                Test.update_test_run_tests(session, self.id, tests)
            plugin.run(self, self.test_set, tests)
            return self.frontend
        return {}

    def stop(self, session):
        """Stop test run if running
        """
        plugin = nose_plugin.get_plugin(self.test_set.driver)
        killed = plugin.kill(self.id,
                             self.cluster_id,
                             cleanup=self.test_set.cleanup_path)
        if killed:
            Test.update_running_tests(session, self.id, status='stopped')
        return self.frontend