Source code for watcher.db.sqlalchemy.api

# -*- encoding: utf-8 -*-
#
# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# 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.

"""SQLAlchemy storage backend."""

import collections
import datetime
import operator

from oslo_config import cfg
from oslo_db import exception as db_exc
from oslo_db.sqlalchemy import session as db_session
from oslo_db.sqlalchemy import utils as db_utils
from oslo_utils import timeutils
from sqlalchemy.inspection import inspect
from sqlalchemy.orm import exc
from sqlalchemy.orm import joinedload

from watcher._i18n import _
from watcher.common import exception
from watcher.common import utils
from watcher.db import api
from watcher.db.sqlalchemy import models
from watcher import objects

CONF = cfg.CONF

_FACADE = None


def _create_facade_lazily():
    global _FACADE
    if _FACADE is None:
        _FACADE = db_session.EngineFacade.from_config(CONF)
    return _FACADE


def get_engine():
    facade = _create_facade_lazily()
    return facade.get_engine()


def get_session(**kwargs):
    facade = _create_facade_lazily()
    return facade.get_session(**kwargs)


def get_backend():
    """The backend is this module itself."""
    return Connection()


def model_query(model, *args, **kwargs):
    """Query helper for simpler session usage.

    :param session: if present, the session to use
    """
    session = kwargs.get('session') or get_session()
    query = session.query(model, *args)
    return query


def add_identity_filter(query, value):
    """Adds an identity filter to a query.

    Filters results by ID, if supplied value is a valid integer.
    Otherwise attempts to filter results by UUID.

    :param query: Initial query to add filter to.
    :param value: Value for filtering results by.
    :return: Modified query.
    """
    if utils.is_int_like(value):
        return query.filter_by(id=value)
    elif utils.is_uuid_like(value):
        return query.filter_by(uuid=value)
    else:
        raise exception.InvalidIdentity(identity=value)


def _paginate_query(model, limit=None, marker=None, sort_key=None,
                    sort_dir=None, query=None):
    if not query:
        query = model_query(model)
    sort_keys = ['id']
    if sort_key and sort_key not in sort_keys:
        sort_keys.insert(0, sort_key)
    query = db_utils.paginate_query(query, model, limit, sort_keys,
                                    marker=marker, sort_dir=sort_dir)
    return query.all()


[docs]class JoinMap(utils.Struct): """Mapping for the Join-based queries"""
NaturalJoinFilter = collections.namedtuple( 'NaturalJoinFilter', ['join_fieldname', 'join_model'])
[docs]class Connection(api.BaseConnection): """SqlAlchemy connection.""" valid_operators = { "": operator.eq, "eq": operator.eq, "neq": operator.ne, "gt": operator.gt, "gte": operator.ge, "lt": operator.lt, "lte": operator.le, "in": lambda field, choices: field.in_(choices), "notin": lambda field, choices: field.notin_(choices), } def __init__(self): super(Connection, self).__init__() def __add_simple_filter(self, query, model, fieldname, value, operator_): field = getattr(model, fieldname) if (fieldname != 'deleted' and value and field.type.python_type is datetime.datetime): if not isinstance(value, datetime.datetime): value = timeutils.parse_isotime(value) return query.filter(self.valid_operators[operator_](field, value)) def __add_join_filter(self, query, model, fieldname, value, operator_): query = query.join(model) return self.__add_simple_filter(query, model, fieldname, value, operator_) def __decompose_filter(self, raw_fieldname): """Decompose a filter name into its 2 subparts A filter can take 2 forms: - "<FIELDNAME>" which is a syntactic sugar for "<FIELDNAME>__eq" - "<FIELDNAME>__<OPERATOR>" where <OPERATOR> is the comparison operator to be used. Available operators are: - eq - neq - gt - gte - lt - lte - in - notin """ separator = '__' fieldname, separator, operator_ = raw_fieldname.partition(separator) if operator_ and operator_ not in self.valid_operators: raise exception.InvalidOperator( operator=operator_, valid_operators=self.valid_operators) return fieldname, operator_ def _add_filters(self, query, model, filters=None, plain_fields=None, join_fieldmap=None): """Generic way to add filters to a Watcher model Each filter key provided by the `filters` parameter will be decomposed into 2 pieces: the field name and the comparison operator - "": By default, the "eq" is applied if no operator is provided - "eq", which stands for "equal" : e.g. {"state__eq": "PENDING"} will result in the "WHERE state = 'PENDING'" clause. - "neq", which stands for "not equal" : e.g. {"state__neq": "PENDING"} will result in the "WHERE state != 'PENDING'" clause. - "gt", which stands for "greater than" : e.g. {"created_at__gt": "2016-06-06T10:33:22.063176"} will result in the "WHERE created_at > '2016-06-06T10:33:22.063176'" clause. - "gte", which stands for "greater than or equal to" : e.g. {"created_at__gte": "2016-06-06T10:33:22.063176"} will result in the "WHERE created_at >= '2016-06-06T10:33:22.063176'" clause. - "lt", which stands for "less than" : e.g. {"created_at__lt": "2016-06-06T10:33:22.063176"} will result in the "WHERE created_at < '2016-06-06T10:33:22.063176'" clause. - "lte", which stands for "less than or equal to" : e.g. {"created_at__lte": "2016-06-06T10:33:22.063176"} will result in the "WHERE created_at <= '2016-06-06T10:33:22.063176'" clause. - "in": e.g. {"state__in": ('SUCCEEDED', 'FAILED')} will result in the "WHERE state IN ('SUCCEEDED', 'FAILED')" clause. :param query: a :py:class:`sqlalchemy.orm.query.Query` instance :param model: the model class the filters should relate to :param filters: dict with the following structure {"fieldname": value} :param plain_fields: a :py:class:`sqlalchemy.orm.query.Query` instance :param join_fieldmap: a :py:class:`sqlalchemy.orm.query.Query` instance """ soft_delete_mixin_fields = ['deleted', 'deleted_at'] timestamp_mixin_fields = ['created_at', 'updated_at'] filters = filters or {} # Special case for 'deleted' because it is a non-boolean flag if 'deleted' in filters: deleted_filter = filters.pop('deleted') op = 'eq' if not bool(deleted_filter) else 'neq' filters['deleted__%s' % op] = 0 plain_fields = tuple( (list(plain_fields) or []) + soft_delete_mixin_fields + timestamp_mixin_fields) join_fieldmap = join_fieldmap or {} for raw_fieldname, value in filters.items(): fieldname, operator_ = self.__decompose_filter(raw_fieldname) if fieldname in plain_fields: query = self.__add_simple_filter( query, model, fieldname, value, operator_) elif fieldname in join_fieldmap: join_field, join_model = join_fieldmap[fieldname] query = self.__add_join_filter( query, join_model, join_field, value, operator_) return query @staticmethod def _get_relationships(model): return inspect(model).relationships @staticmethod def _set_eager_options(model, query): relationships = inspect(model).relationships for relationship in relationships: if not relationship.uselist: # We have a One-to-X relationship query = query.options(joinedload(relationship.key)) return query def _create(self, model, values): obj = model() cleaned_values = {k: v for k, v in values.items() if k not in self._get_relationships(model)} obj.update(cleaned_values) obj.save() return obj def _get(self, context, model, fieldname, value, eager): query = model_query(model) if eager: query = self._set_eager_options(model, query) query = query.filter(getattr(model, fieldname) == value) if not context.show_deleted: query = query.filter(model.deleted_at.is_(None)) try: obj = query.one() except exc.NoResultFound: raise exception.ResourceNotFound(name=model.__name__, id=value) return obj @staticmethod def _update(model, id_, values): session = get_session() with session.begin(): query = model_query(model, session=session) query = add_identity_filter(query, id_) try: ref = query.with_lockmode('update').one() except exc.NoResultFound: raise exception.ResourceNotFound(name=model.__name__, id=id_) ref.update(values) return ref @staticmethod def _soft_delete(model, id_): session = get_session() with session.begin(): query = model_query(model, session=session) query = add_identity_filter(query, id_) try: row = query.one() except exc.NoResultFound: raise exception.ResourceNotFound(name=model.__name__, id=id_) row.soft_delete(session) return row @staticmethod def _destroy(model, id_): session = get_session() with session.begin(): query = model_query(model, session=session) query = add_identity_filter(query, id_) try: query.one() except exc.NoResultFound: raise exception.ResourceNotFound(name=model.__name__, id=id_) query.delete() def _add_goals_filters(self, query, filters): if filters is None: filters = {} plain_fields = ['uuid', 'name', 'display_name'] return self._add_filters( query=query, model=models.Goal, filters=filters, plain_fields=plain_fields) def _add_strategies_filters(self, query, filters): plain_fields = ['uuid', 'name', 'display_name', 'goal_id'] join_fieldmap = JoinMap( goal_uuid=NaturalJoinFilter( join_fieldname="uuid", join_model=models.Goal), goal_name=NaturalJoinFilter( join_fieldname="name", join_model=models.Goal)) return self._add_filters( query=query, model=models.Strategy, filters=filters, plain_fields=plain_fields, join_fieldmap=join_fieldmap) def _add_audit_templates_filters(self, query, filters): if filters is None: filters = {} plain_fields = ['uuid', 'name', 'goal_id', 'strategy_id'] join_fieldmap = JoinMap( goal_uuid=NaturalJoinFilter( join_fieldname="uuid", join_model=models.Goal), goal_name=NaturalJoinFilter( join_fieldname="name", join_model=models.Goal), strategy_uuid=NaturalJoinFilter( join_fieldname="uuid", join_model=models.Strategy), strategy_name=NaturalJoinFilter( join_fieldname="name", join_model=models.Strategy), ) return self._add_filters( query=query, model=models.AuditTemplate, filters=filters, plain_fields=plain_fields, join_fieldmap=join_fieldmap) def _add_audits_filters(self, query, filters): if filters is None: filters = {} plain_fields = ['uuid', 'audit_type', 'state', 'goal_id', 'strategy_id'] join_fieldmap = { 'goal_uuid': ("uuid", models.Goal), 'goal_name': ("name", models.Goal), 'strategy_uuid': ("uuid", models.Strategy), 'strategy_name': ("name", models.Strategy), } return self._add_filters( query=query, model=models.Audit, filters=filters, plain_fields=plain_fields, join_fieldmap=join_fieldmap) def _add_action_plans_filters(self, query, filters): if filters is None: filters = {} plain_fields = ['uuid', 'state', 'audit_id', 'strategy_id'] join_fieldmap = JoinMap( audit_uuid=NaturalJoinFilter( join_fieldname="uuid", join_model=models.Audit), strategy_uuid=NaturalJoinFilter( join_fieldname="uuid", join_model=models.Strategy), strategy_name=NaturalJoinFilter( join_fieldname="name", join_model=models.Strategy), ) return self._add_filters( query=query, model=models.ActionPlan, filters=filters, plain_fields=plain_fields, join_fieldmap=join_fieldmap) def _add_actions_filters(self, query, filters): if filters is None: filters = {} plain_fields = ['uuid', 'state', 'action_plan_id'] join_fieldmap = { 'action_plan_uuid': ("uuid", models.ActionPlan), } query = self._add_filters( query=query, model=models.Action, filters=filters, plain_fields=plain_fields, join_fieldmap=join_fieldmap) if 'audit_uuid' in filters: stmt = model_query(models.ActionPlan).join( models.Audit, models.Audit.id == models.ActionPlan.audit_id)\ .filter_by(uuid=filters['audit_uuid']).subquery() query = query.filter_by(action_plan_id=stmt.c.id) return query def _add_efficacy_indicators_filters(self, query, filters): if filters is None: filters = {} plain_fields = ['uuid', 'name', 'unit', 'schema', 'action_plan_id'] join_fieldmap = JoinMap( action_plan_uuid=NaturalJoinFilter( join_fieldname="uuid", join_model=models.ActionPlan), ) return self._add_filters( query=query, model=models.EfficacyIndicator, filters=filters, plain_fields=plain_fields, join_fieldmap=join_fieldmap) # ### GOALS ### #
[docs] def get_goal_list(self, context, filters=None, limit=None, marker=None, sort_key=None, sort_dir=None, eager=False): query = model_query(models.Goal) if eager: query = self._set_eager_options(models.Goal, query) query = self._add_goals_filters(query, filters) if not context.show_deleted: query = query.filter_by(deleted_at=None) return _paginate_query(models.Goal, limit, marker, sort_key, sort_dir, query)
[docs] def create_goal(self, values): # ensure defaults are present for new goals if not values.get('uuid'): values['uuid'] = utils.generate_uuid() try: goal = self._create(models.Goal, values) except db_exc.DBDuplicateEntry: raise exception.GoalAlreadyExists(uuid=values['uuid']) return goal
def _get_goal(self, context, fieldname, value, eager): try: return self._get(context, model=models.Goal, fieldname=fieldname, value=value, eager=eager) except exception.ResourceNotFound: raise exception.GoalNotFound(goal=value)
[docs] def get_goal_by_id(self, context, goal_id, eager=False): return self._get_goal( context, fieldname="id", value=goal_id, eager=eager)
[docs] def get_goal_by_uuid(self, context, goal_uuid, eager=False): return self._get_goal( context, fieldname="uuid", value=goal_uuid, eager=eager)
[docs] def get_goal_by_name(self, context, goal_name, eager=False): return self._get_goal( context, fieldname="name", value=goal_name, eager=eager)
[docs] def destroy_goal(self, goal_id): try: return self._destroy(models.Goal, goal_id) except exception.ResourceNotFound: raise exception.GoalNotFound(goal=goal_id)
[docs] def update_goal(self, goal_id, values): if 'uuid' in values: raise exception.Invalid( message=_("Cannot overwrite UUID for an existing Goal.")) try: return self._update(models.Goal, goal_id, values) except exception.ResourceNotFound: raise exception.GoalNotFound(goal=goal_id)
[docs] def soft_delete_goal(self, goal_id): try: return self._soft_delete(models.Goal, goal_id) except exception.ResourceNotFound: raise exception.GoalNotFound(goal=goal_id)
# ### STRATEGIES ### #
[docs] def get_strategy_list(self, context, filters=None, limit=None, marker=None, sort_key=None, sort_dir=None, eager=True): query = model_query(models.Strategy) if eager: query = self._set_eager_options(models.Strategy, query) query = self._add_strategies_filters(query, filters) if not context.show_deleted: query = query.filter_by(deleted_at=None) return _paginate_query(models.Strategy, limit, marker, sort_key, sort_dir, query)
[docs] def create_strategy(self, values): # ensure defaults are present for new strategies if not values.get('uuid'): values['uuid'] = utils.generate_uuid() try: strategy = self._create(models.Strategy, values) except db_exc.DBDuplicateEntry: raise exception.StrategyAlreadyExists(uuid=values['uuid']) return strategy
def _get_strategy(self, context, fieldname, value, eager): try: return self._get(context, model=models.Strategy, fieldname=fieldname, value=value, eager=eager) except exception.ResourceNotFound: raise exception.StrategyNotFound(strategy=value)
[docs] def get_strategy_by_id(self, context, strategy_id, eager=False): return self._get_strategy( context, fieldname="id", value=strategy_id, eager=eager)
[docs] def get_strategy_by_uuid(self, context, strategy_uuid, eager=False): return self._get_strategy( context, fieldname="uuid", value=strategy_uuid, eager=eager)
[docs] def get_strategy_by_name(self, context, strategy_name, eager=False): return self._get_strategy( context, fieldname="name", value=strategy_name, eager=eager)
[docs] def destroy_strategy(self, strategy_id): try: return self._destroy(models.Strategy, strategy_id) except exception.ResourceNotFound: raise exception.StrategyNotFound(strategy=strategy_id)
[docs] def update_strategy(self, strategy_id, values): if 'uuid' in values: raise exception.Invalid( message=_("Cannot overwrite UUID for an existing Strategy.")) try: return self._update(models.Strategy, strategy_id, values) except exception.ResourceNotFound: raise exception.StrategyNotFound(strategy=strategy_id)
[docs] def soft_delete_strategy(self, strategy_id): try: return self._soft_delete(models.Strategy, strategy_id) except exception.ResourceNotFound: raise exception.StrategyNotFound(strategy=strategy_id)
# ### AUDIT TEMPLATES ### #
[docs] def get_audit_template_list(self, context, filters=None, limit=None, marker=None, sort_key=None, sort_dir=None, eager=False): query = model_query(models.AuditTemplate) if eager: query = self._set_eager_options(models.AuditTemplate, query) query = self._add_audit_templates_filters(query, filters) if not context.show_deleted: query = query.filter_by(deleted_at=None) return _paginate_query(models.AuditTemplate, limit, marker, sort_key, sort_dir, query)
[docs] def create_audit_template(self, values): # ensure defaults are present for new audit_templates if not values.get('uuid'): values['uuid'] = utils.generate_uuid() query = model_query(models.AuditTemplate) query = query.filter_by(name=values.get('name'), deleted_at=None) if len(query.all()) > 0: raise exception.AuditTemplateAlreadyExists( audit_template=values['name']) try: audit_template = self._create(models.AuditTemplate, values) except db_exc.DBDuplicateEntry: raise exception.AuditTemplateAlreadyExists( audit_template=values['name']) return audit_template
def _get_audit_template(self, context, fieldname, value, eager): try: return self._get(context, model=models.AuditTemplate, fieldname=fieldname, value=value, eager=eager) except exception.ResourceNotFound: raise exception.AuditTemplateNotFound(audit_template=value)
[docs] def get_audit_template_by_id(self, context, audit_template_id, eager=False): return self._get_audit_template( context, fieldname="id", value=audit_template_id, eager=eager)
[docs] def get_audit_template_by_uuid(self, context, audit_template_uuid, eager=False): return self._get_audit_template( context, fieldname="uuid", value=audit_template_uuid, eager=eager)
[docs] def get_audit_template_by_name(self, context, audit_template_name, eager=False): return self._get_audit_template( context, fieldname="name", value=audit_template_name, eager=eager)
[docs] def destroy_audit_template(self, audit_template_id): try: return self._destroy(models.AuditTemplate, audit_template_id) except exception.ResourceNotFound: raise exception.AuditTemplateNotFound( audit_template=audit_template_id)
[docs] def update_audit_template(self, audit_template_id, values): if 'uuid' in values: raise exception.Invalid( message=_("Cannot overwrite UUID for an existing " "Audit Template.")) try: return self._update( models.AuditTemplate, audit_template_id, values) except exception.ResourceNotFound: raise exception.AuditTemplateNotFound( audit_template=audit_template_id)
[docs] def soft_delete_audit_template(self, audit_template_id): try: return self._soft_delete(models.AuditTemplate, audit_template_id) except exception.ResourceNotFound: raise exception.AuditTemplateNotFound( audit_template=audit_template_id)
# ### AUDITS ### #
[docs] def get_audit_list(self, context, filters=None, limit=None, marker=None, sort_key=None, sort_dir=None, eager=False): query = model_query(models.Audit) if eager: query = self._set_eager_options(models.Audit, query) query = self._add_audits_filters(query, filters) if not context.show_deleted: query = query.filter( ~(models.Audit.state == objects.audit.State.DELETED)) return _paginate_query(models.Audit, limit, marker, sort_key, sort_dir, query)
[docs] def create_audit(self, values): # ensure defaults are present for new audits if not values.get('uuid'): values['uuid'] = utils.generate_uuid() if values.get('state') is None: values['state'] = objects.audit.State.PENDING try: audit = self._create(models.Audit, values) except db_exc.DBDuplicateEntry: raise exception.AuditAlreadyExists(uuid=values['uuid']) return audit
def _get_audit(self, context, fieldname, value, eager): try: return self._get(context, model=models.Audit, fieldname=fieldname, value=value, eager=eager) except exception.ResourceNotFound: raise exception.AuditNotFound(audit=value)
[docs] def get_audit_by_id(self, context, audit_id, eager=False): return self._get_audit( context, fieldname="id", value=audit_id, eager=eager)
[docs] def get_audit_by_uuid(self, context, audit_uuid, eager=False): return self._get_audit( context, fieldname="uuid", value=audit_uuid, eager=eager)
[docs] def destroy_audit(self, audit_id): def is_audit_referenced(session, audit_id): """Checks whether the audit is referenced by action_plan(s).""" query = model_query(models.ActionPlan, session=session) query = self._add_action_plans_filters( query, {'audit_id': audit_id}) return query.count() != 0 session = get_session() with session.begin(): query = model_query(models.Audit, session=session) query = add_identity_filter(query, audit_id) try: audit_ref = query.one() except exc.NoResultFound: raise exception.AuditNotFound(audit=audit_id) if is_audit_referenced(session, audit_ref['id']): raise exception.AuditReferenced(audit=audit_id) query.delete()
[docs] def update_audit(self, audit_id, values): if 'uuid' in values: raise exception.Invalid( message=_("Cannot overwrite UUID for an existing " "Audit.")) try: return self._update(models.Audit, audit_id, values) except exception.ResourceNotFound: raise exception.AuditNotFound(audit=audit_id)
[docs] def soft_delete_audit(self, audit_id): try: return self._soft_delete(models.Audit, audit_id) except exception.ResourceNotFound: raise exception.AuditNotFound(audit=audit_id)
# ### ACTIONS ### #
[docs] def get_action_list(self, context, filters=None, limit=None, marker=None, sort_key=None, sort_dir=None, eager=False): query = model_query(models.Action) if eager: query = self._set_eager_options(models.Action, query) query = self._add_actions_filters(query, filters) if not context.show_deleted: query = query.filter( ~(models.Action.state == objects.action.State.DELETED)) return _paginate_query(models.Action, limit, marker, sort_key, sort_dir, query)
[docs] def create_action(self, values): # ensure defaults are present for new actions if not values.get('uuid'): values['uuid'] = utils.generate_uuid() try: action = self._create(models.Action, values) except db_exc.DBDuplicateEntry: raise exception.ActionAlreadyExists(uuid=values['uuid']) return action
def _get_action(self, context, fieldname, value, eager): try: return self._get(context, model=models.Action, fieldname=fieldname, value=value, eager=eager) except exception.ResourceNotFound: raise exception.ActionNotFound(action=value)
[docs] def get_action_by_id(self, context, action_id, eager=False): return self._get_action( context, fieldname="id", value=action_id, eager=eager)
[docs] def get_action_by_uuid(self, context, action_uuid, eager=False): return self._get_action( context, fieldname="uuid", value=action_uuid, eager=eager)
[docs] def destroy_action(self, action_id): session = get_session() with session.begin(): query = model_query(models.Action, session=session) query = add_identity_filter(query, action_id) count = query.delete() if count != 1: raise exception.ActionNotFound(action_id)
[docs] def update_action(self, action_id, values): # NOTE(dtantsur): this can lead to very strange errors if 'uuid' in values: raise exception.Invalid( message=_("Cannot overwrite UUID for an existing Action.")) return self._do_update_action(action_id, values)
@staticmethod def _do_update_action(action_id, values): session = get_session() with session.begin(): query = model_query(models.Action, session=session) query = add_identity_filter(query, action_id) try: ref = query.with_lockmode('update').one() except exc.NoResultFound: raise exception.ActionNotFound(action=action_id) ref.update(values) return ref
[docs] def soft_delete_action(self, action_id): try: return self._soft_delete(models.Action, action_id) except exception.ResourceNotFound: raise exception.ActionNotFound(action=action_id)
# ### ACTION PLANS ### #
[docs] def get_action_plan_list( self, context, filters=None, limit=None, marker=None, sort_key=None, sort_dir=None, eager=False): query = model_query(models.ActionPlan) if eager: query = self._set_eager_options(models.ActionPlan, query) query = self._add_action_plans_filters(query, filters) if not context.show_deleted: query = query.filter( ~(models.ActionPlan.state == objects.action_plan.State.DELETED)) return _paginate_query(models.ActionPlan, limit, marker, sort_key, sort_dir, query)
[docs] def create_action_plan(self, values): # ensure defaults are present for new audits if not values.get('uuid'): values['uuid'] = utils.generate_uuid() try: action_plan = self._create(models.ActionPlan, values) except db_exc.DBDuplicateEntry: raise exception.ActionPlanAlreadyExists(uuid=values['uuid']) return action_plan
def _get_action_plan(self, context, fieldname, value, eager): try: return self._get(context, model=models.ActionPlan, fieldname=fieldname, value=value, eager=eager) except exception.ResourceNotFound: raise exception.ActionPlanNotFound(action_plan=value)
[docs] def get_action_plan_by_id(self, context, action_plan_id, eager=False): return self._get_action_plan( context, fieldname="id", value=action_plan_id, eager=eager)
[docs] def get_action_plan_by_uuid(self, context, action_plan_uuid, eager=False): return self._get_action_plan( context, fieldname="uuid", value=action_plan_uuid, eager=eager)
[docs] def destroy_action_plan(self, action_plan_id): def is_action_plan_referenced(session, action_plan_id): """Checks whether the action_plan is referenced by action(s).""" query = model_query(models.Action, session=session) query = self._add_actions_filters( query, {'action_plan_id': action_plan_id}) return query.count() != 0 session = get_session() with session.begin(): query = model_query(models.ActionPlan, session=session) query = add_identity_filter(query, action_plan_id) try: action_plan_ref = query.one() except exc.NoResultFound: raise exception.ActionPlanNotFound(action_plan=action_plan_id) if is_action_plan_referenced(session, action_plan_ref['id']): raise exception.ActionPlanReferenced( action_plan=action_plan_id) query.delete()
[docs] def update_action_plan(self, action_plan_id, values): if 'uuid' in values: raise exception.Invalid( message=_("Cannot overwrite UUID for an existing " "Action Plan.")) return self._do_update_action_plan(action_plan_id, values)
@staticmethod def _do_update_action_plan(action_plan_id, values): session = get_session() with session.begin(): query = model_query(models.ActionPlan, session=session) query = add_identity_filter(query, action_plan_id) try: ref = query.with_lockmode('update').one() except exc.NoResultFound: raise exception.ActionPlanNotFound(action_plan=action_plan_id) ref.update(values) return ref
[docs] def soft_delete_action_plan(self, action_plan_id): try: return self._soft_delete(models.ActionPlan, action_plan_id) except exception.ResourceNotFound: raise exception.ActionPlanNotFound(action_plan=action_plan_id)
# ### EFFICACY INDICATORS ### #
[docs] def get_efficacy_indicator_list(self, context, filters=None, limit=None, marker=None, sort_key=None, sort_dir=None, eager=False): query = model_query(models.EfficacyIndicator) if eager: query = self._set_eager_options(models.EfficacyIndicator, query) query = self._add_efficacy_indicators_filters(query, filters) if not context.show_deleted: query = query.filter_by(deleted_at=None) return _paginate_query(models.EfficacyIndicator, limit, marker, sort_key, sort_dir, query)
[docs] def create_efficacy_indicator(self, values): # ensure defaults are present for new efficacy indicators if not values.get('uuid'): values['uuid'] = utils.generate_uuid() try: efficacy_indicator = self._create(models.EfficacyIndicator, values) except db_exc.DBDuplicateEntry: raise exception.EfficacyIndicatorAlreadyExists(uuid=values['uuid']) return efficacy_indicator
def _get_efficacy_indicator(self, context, fieldname, value, eager): try: return self._get(context, model=models.EfficacyIndicator, fieldname=fieldname, value=value, eager=eager) except exception.ResourceNotFound: raise exception.EfficacyIndicatorNotFound(efficacy_indicator=value)
[docs] def get_efficacy_indicator_by_id(self, context, efficacy_indicator_id, eager=False): return self._get_efficacy_indicator( context, fieldname="id", value=efficacy_indicator_id, eager=eager)
[docs] def get_efficacy_indicator_by_uuid(self, context, efficacy_indicator_uuid, eager=False): return self._get_efficacy_indicator( context, fieldname="uuid", value=efficacy_indicator_uuid, eager=eager)
[docs] def get_efficacy_indicator_by_name(self, context, efficacy_indicator_name, eager=False): return self._get_efficacy_indicator( context, fieldname="name", value=efficacy_indicator_name, eager=eager)
[docs] def update_efficacy_indicator(self, efficacy_indicator_id, values): if 'uuid' in values: raise exception.Invalid( message=_("Cannot overwrite UUID for an existing " "efficacy indicator.")) try: return self._update( models.EfficacyIndicator, efficacy_indicator_id, values) except exception.ResourceNotFound: raise exception.EfficacyIndicatorNotFound( efficacy_indicator=efficacy_indicator_id)
[docs] def soft_delete_efficacy_indicator(self, efficacy_indicator_id): try: return self._soft_delete( models.EfficacyIndicator, efficacy_indicator_id) except exception.ResourceNotFound: raise exception.EfficacyIndicatorNotFound( efficacy_indicator=efficacy_indicator_id)
[docs] def destroy_efficacy_indicator(self, efficacy_indicator_id): try: return self._destroy( models.EfficacyIndicator, efficacy_indicator_id) except exception.ResourceNotFound: raise exception.EfficacyIndicatorNotFound( efficacy_indicator=efficacy_indicator_id)
# ### SCORING ENGINES ### # def _add_scoring_engine_filters(self, query, filters): if filters is None: filters = {} plain_fields = ['id', 'description'] return self._add_filters( query=query, model=models.ScoringEngine, filters=filters, plain_fields=plain_fields)
[docs] def get_scoring_engine_list( self, context, columns=None, filters=None, limit=None, marker=None, sort_key=None, sort_dir=None, eager=False): query = model_query(models.ScoringEngine) if eager: query = self._set_eager_options(models.ScoringEngine, query) query = self._add_scoring_engine_filters(query, filters) if not context.show_deleted: query = query.filter_by(deleted_at=None) return _paginate_query(models.ScoringEngine, limit, marker, sort_key, sort_dir, query)
[docs] def create_scoring_engine(self, values): # ensure defaults are present for new scoring engines if not values.get('uuid'): values['uuid'] = utils.generate_uuid() try: scoring_engine = self._create(models.ScoringEngine, values) except db_exc.DBDuplicateEntry: raise exception.ScoringEngineAlreadyExists(uuid=values['uuid']) return scoring_engine
def _get_scoring_engine(self, context, fieldname, value, eager): try: return self._get(context, model=models.ScoringEngine, fieldname=fieldname, value=value, eager=eager) except exception.ResourceNotFound: raise exception.ScoringEngineNotFound(scoring_engine=value)
[docs] def get_scoring_engine_by_id(self, context, scoring_engine_id, eager=False): return self._get_scoring_engine( context, fieldname="id", value=scoring_engine_id, eager=eager)
[docs] def get_scoring_engine_by_uuid(self, context, scoring_engine_uuid, eager=False): return self._get_scoring_engine( context, fieldname="uuid", value=scoring_engine_uuid, eager=eager)
[docs] def get_scoring_engine_by_name(self, context, scoring_engine_name, eager=False): return self._get_scoring_engine( context, fieldname="name", value=scoring_engine_name, eager=eager)
[docs] def destroy_scoring_engine(self, scoring_engine_id): try: return self._destroy(models.ScoringEngine, scoring_engine_id) except exception.ResourceNotFound: raise exception.ScoringEngineNotFound( scoring_engine=scoring_engine_id)
[docs] def update_scoring_engine(self, scoring_engine_id, values): if 'uuid' in values: raise exception.Invalid( message=_("Cannot overwrite UUID for an existing " "Scoring Engine.")) try: return self._update( models.ScoringEngine, scoring_engine_id, values) except exception.ResourceNotFound: raise exception.ScoringEngineNotFound( scoring_engine=scoring_engine_id)
[docs] def soft_delete_scoring_engine(self, scoring_engine_id): try: return self._soft_delete( models.ScoringEngine, scoring_engine_id) except exception.ResourceNotFound: raise exception.ScoringEngineNotFound( scoring_engine=scoring_engine_id)
# ### SERVICES ### # def _add_services_filters(self, query, filters): if not filters: filters = {} plain_fields = ['id', 'name', 'host'] return self._add_filters( query=query, model=models.Service, filters=filters, plain_fields=plain_fields)
[docs] def get_service_list(self, context, filters=None, limit=None, marker=None, sort_key=None, sort_dir=None, eager=False): query = model_query(models.Service) if eager: query = self._set_eager_options(models.Service, query) query = self._add_services_filters(query, filters) if not context.show_deleted: query = query.filter_by(deleted_at=None) return _paginate_query(models.Service, limit, marker, sort_key, sort_dir, query)
[docs] def create_service(self, values): try: service = self._create(models.Service, values) except db_exc.DBDuplicateEntry: raise exception.ServiceAlreadyExists(name=values['name'], host=values['host']) return service
def _get_service(self, context, fieldname, value, eager): try: return self._get(context, model=models.Service, fieldname=fieldname, value=value, eager=eager) except exception.ResourceNotFound: raise exception.ServiceNotFound(service=value)
[docs] def get_service_by_id(self, context, service_id, eager=False): return self._get_service( context, fieldname="id", value=service_id, eager=eager)
[docs] def get_service_by_name(self, context, service_name, eager=False): return self._get_service( context, fieldname="name", value=service_name, eager=eager)
[docs] def destroy_service(self, service_id): try: return self._destroy(models.Service, service_id) except exception.ResourceNotFound: raise exception.ServiceNotFound(service=service_id)
[docs] def update_service(self, service_id, values): try: return self._update(models.Service, service_id, values) except exception.ResourceNotFound: raise exception.ServiceNotFound(service=service_id)
[docs] def soft_delete_service(self, service_id): try: return self._soft_delete(models.Service, service_id) except exception.ResourceNotFound: raise exception.ServiceNotFound(service=service_id)