def setUp(self): cfg.CONF.set_override("enable_authentication", False, enforce_type=True) # To use in-memory SQLite DB cfg.CONF.set_override("connection", "sqlite://", group="database", enforce_type=True) cfg.CONF.set_override("sqlite_db", "", group="database", enforce_type=True) super(DbTestCase, self).setUp() self.dbapi = dbapi.get_instance() global _DB_CACHE if not _DB_CACHE: _DB_CACHE = Database(sqla_api, migration, sql_connection=CONF.database.connection, sqlite_db=CONF.database.sqlite_db, sqlite_clean_db='clean.sqlite') self.useFixture(_DB_CACHE)
def create_test_action_desc(**kwargs): """Create test action description entry in DB and return ActionDescription. Function to be used to create test ActionDescription objects in the DB. :param kwargs: kwargs with overriding values for service's attributes. :returns: Test ActionDescription DB object. """ action_desc = get_test_action_desc(**kwargs) dbapi = db_api.get_instance() return dbapi.create_action_description(action_desc)
def create_test_strategy(**kwargs): """Create test strategy entry in DB and return Strategy DB object. Function to be used to create test Strategy objects in the database. :param kwargs: kwargs with overriding values for strategy's attributes. :returns: Test Strategy DB object. """ strategy = get_test_strategy(**kwargs) dbapi = db_api.get_instance() return dbapi.create_strategy(strategy)
def create_test_scoring_engine(**kwargs): """Create test scoring engine in DB and return ScoringEngine DB object. Function to be used to create test ScoringEngine objects in the database. :param kwargs: kwargs with overriding values for SE'sattributes. :returns: Test ScoringEngine DB object. """ scoring_engine = get_test_scoring_engine(**kwargs) dbapi = db_api.get_instance() return dbapi.create_scoring_engine(scoring_engine)
def create_test_goal(**kwargs): """Create test goal entry in DB and return Goal DB object. Function to be used to create test Goal objects in the database. :param kwargs: kwargs which override default goal values of its attributes. :returns: Test Goal DB object. """ goal = get_test_goal(**kwargs) dbapi = db_api.get_instance() return dbapi.create_goal(goal)
def create_test_scoring_engine(**kwargs): """Create test scoring engine in DB and return ScoringEngine DB object. Function to be used to create test ScoringEngine objects in the database. :param kwargs: kwargs with overriding values for SE'sattributes. :returns: Test ScoringEngine DB object. """ scoring_engine = get_test_scoring_engine(**kwargs) dbapi = db_api.get_instance() return dbapi.create_scoring_engine(scoring_engine)
def create_test_goal(**kwargs): """Create test goal entry in DB and return Goal DB object. Function to be used to create test Goal objects in the database. :param kwargs: kwargs which override default goal values of its attributes. :returns: Test Goal DB object. """ goal = get_test_goal(**kwargs) dbapi = db_api.get_instance() return dbapi.create_goal(goal)
def create_test_service(**kwargs): """Create test service entry in DB and return Service DB object. Function to be used to create test Service objects in the database. :param kwargs: kwargs with overriding values for service's attributes. :returns: Test Service DB object. """ service = get_test_service(**kwargs) dbapi = db_api.get_instance() return dbapi.create_service(service)
def create_test_strategy(**kwargs): """Create test strategy entry in DB and return Strategy DB object. Function to be used to create test Strategy objects in the database. :param kwargs: kwargs with overriding values for strategy's attributes. :returns: Test Strategy DB object. """ strategy = get_test_strategy(**kwargs) dbapi = db_api.get_instance() return dbapi.create_strategy(strategy)
def _load_relationships(model, db_data): rel_data = {} relationships = db_api.get_instance()._get_relationships(model) for name, relationship in relationships.items(): related_model = relationship.argument if not db_data.get(name): rel_data[name] = None else: rel_data[name] = related_model(**db_data.get(name)) return rel_data
def create_test_action_plan(**kwargs): """Create test action plan entry in DB and return Action Plan DB object. Function to be used to create test Action objects in the database. :param kwargs: kwargsargs with overriding values for action's attributes. :returns: Test Action DB object. """ action = get_test_action_plan(**kwargs) # Let DB generate ID if it isn't specified explicitly if 'id' not in kwargs: del action['id'] dbapi = db_api.get_instance() return dbapi.create_action_plan(action)
def create_test_audit(**kwargs): """Create test audit entry in DB and return Audit DB object. Function to be used to create test Audit objects in the database. :param kwargs: kwargsargs with overriding values for audit's attributes. :returns: Test Audit DB object. """ audit = get_test_audit(**kwargs) # Let DB generate ID if it isn't specified explicitly if 'id' not in kwargs: del audit['id'] dbapi = db_api.get_instance() return dbapi.create_audit(audit)
def create_test_efficacy_indicator(**kwargs): """Create and return a test efficacy indicator entry in DB. Function to be used to create test EfficacyIndicator objects in the DB. :param kwargs: kwargs for overriding the values of the attributes :returns: Test EfficacyIndicator DB object. """ efficacy_indicator = get_test_efficacy_indicator(**kwargs) # Let DB generate ID if it isn't specified explicitly if 'id' not in kwargs: del efficacy_indicator['id'] dbapi = db_api.get_instance() return dbapi.create_efficacy_indicator(efficacy_indicator)
def create_test_audit(**kwargs): """Create test audit entry in DB and return Audit DB object. Function to be used to create test Audit objects in the database. :param kwargs: kwargsargs with overriding values for audit's attributes. :returns: Test Audit DB object. """ audit = get_test_audit(**kwargs) # Let DB generate ID if it isn't specified explicitly if 'id' not in kwargs: del audit['id'] dbapi = db_api.get_instance() return dbapi.create_audit(audit)
def create_test_action_plan(**kwargs): """Create test action plan entry in DB and return Action Plan DB object. Function to be used to create test Action objects in the database. :param kwargs: kwargsargs with overriding values for action's attributes. :returns: Test Action DB object. """ action = get_test_action_plan(**kwargs) # Let DB generate ID if it isn't specified explicitly if 'id' not in kwargs: del action['id'] dbapi = db_api.get_instance() return dbapi.create_action_plan(action)
def create_test_efficacy_indicator(**kwargs): """Create and return a test efficacy indicator entry in DB. Function to be used to create test EfficacyIndicator objects in the DB. :param kwargs: kwargs for overriding the values of the attributes :returns: Test EfficacyIndicator DB object. """ efficacy_indicator = get_test_efficacy_indicator(**kwargs) # Let DB generate ID if it isn't specified explicitly if 'id' not in kwargs: del efficacy_indicator['id'] dbapi = db_api.get_instance() return dbapi.create_efficacy_indicator(efficacy_indicator)
def setUp(self): cfg.CONF.set_override("enable_authentication", False, enforce_type=True) super(DbTestCase, self).setUp() self.dbapi = dbapi.get_instance() global _DB_CACHE if not _DB_CACHE: _DB_CACHE = Database(sqla_api, migration, sql_connection=CONF.database.connection, sqlite_db=CONF.database.sqlite_db, sqlite_clean_db='clean.sqlite') self.useFixture(_DB_CACHE)
def setUp(self): cfg.CONF.set_override("enable_authentication", False) # To use in-memory SQLite DB cfg.CONF.set_override("connection", "sqlite://", group="database") super(DbTestCase, self).setUp() self.dbapi = dbapi.get_instance() global _DB_CACHE if not _DB_CACHE: _DB_CACHE = Database(sqla_api, migration, sql_connection=CONF.database.connection) self.useFixture(_DB_CACHE) self._id_gen = utils.id_generator()
class ActionPlan(base.WatcherPersistentObject, base.WatcherObject, base.WatcherObjectDictCompat): # Version 1.0: Initial version # Version 1.1: Added 'audit' and 'strategy' object field # Version 1.2: audit_id is not nullable anymore # Version 2.0: Removed 'first_action_id' object field VERSION = '2.0' dbapi = db_api.get_instance() fields = { 'id': wfields.IntegerField(), 'uuid': wfields.UUIDField(), 'audit_id': wfields.IntegerField(), 'strategy_id': wfields.IntegerField(), 'state': wfields.StringField(nullable=True), 'global_efficacy': wfields.FlexibleDictField(nullable=True), 'audit': wfields.ObjectField('Audit', nullable=True), 'strategy': wfields.ObjectField('Strategy', nullable=True), } object_fields = { 'audit': (objects.Audit, 'audit_id'), 'strategy': (objects.Strategy, 'strategy_id'), } # Proxified field so we can keep the previous value after an update _state = None _old_state = None # NOTE(v-francoise): The way oslo.versionedobjects works is by using a # __new__ that will automatically create the attributes referenced in # fields. These attributes are properties that raise an exception if no # value has been assigned, which means that they store the actual field # value in an "_obj_%(field)s" attribute. So because we want to proxify a # value that is already proxified, we have to do what you see below. @property def _obj_state(self): return self._state @property def _obj_old_state(self): return self._old_state @property def old_state(self): return self._old_state @_obj_old_state.setter def _obj_old_state(self, value): self._old_state = value @_obj_state.setter def _obj_state(self, value): if self._old_state is None and self._state is None: self._state = value else: self._old_state, self._state = self._state, value @base.remotable_classmethod def get(cls, context, action_plan_id, eager=False): """Find a action_plan based on its id or uuid and return a Action object. :param action_plan_id: the id *or* uuid of a action_plan. :param eager: Load object fields if True (Default: False) :returns: a :class:`Action` object. """ if utils.is_int_like(action_plan_id): return cls.get_by_id(context, action_plan_id, eager=eager) elif utils.is_uuid_like(action_plan_id): return cls.get_by_uuid(context, action_plan_id, eager=eager) else: raise exception.InvalidIdentity(identity=action_plan_id) @base.remotable_classmethod def get_by_id(cls, context, action_plan_id, eager=False): """Find a action_plan based on its integer id and return a ActionPlan object. :param action_plan_id: the id of a action_plan. :param eager: Load object fields if True (Default: False) :returns: a :class:`ActionPlan` object. """ db_action_plan = cls.dbapi.get_action_plan_by_id(context, action_plan_id, eager=eager) action_plan = cls._from_db_object(cls(context), db_action_plan, eager=eager) return action_plan @base.remotable_classmethod def get_by_uuid(cls, context, uuid, eager=False): """Find a action_plan based on uuid and return a :class:`ActionPlan` object. :param uuid: the uuid of a action_plan. :param context: Security context :param eager: Load object fields if True (Default: False) :returns: a :class:`ActionPlan` object. """ db_action_plan = cls.dbapi.get_action_plan_by_uuid(context, uuid, eager=eager) action_plan = cls._from_db_object(cls(context), db_action_plan, eager=eager) return action_plan @base.remotable_classmethod def list(cls, context, limit=None, marker=None, filters=None, sort_key=None, sort_dir=None, eager=False): """Return a list of ActionPlan objects. :param context: Security context. :param limit: maximum number of resources to return in a single result. :param marker: pagination marker for large data sets. :param filters: Filters to apply. Defaults to None. :param sort_key: column to sort results by. :param sort_dir: direction to sort. "asc" or "desc". :param eager: Load object fields if True (Default: False) :returns: a list of :class:`ActionPlan` object. """ db_action_plans = cls.dbapi.get_action_plan_list(context, limit=limit, marker=marker, filters=filters, sort_key=sort_key, sort_dir=sort_dir, eager=eager) return [ cls._from_db_object(cls(context), obj, eager=eager) for obj in db_action_plans ] @base.remotable def create(self): """Create an :class:`ActionPlan` record in the DB. :returns: An :class:`ActionPlan` object. """ values = self.obj_get_changes() db_action_plan = self.dbapi.create_action_plan(values) # Note(v-francoise): Always load eagerly upon creation so we can send # notifications containing information about the related relationships self._from_db_object(self, db_action_plan, eager=True) def _notify(): notifications.action_plan.send_create(self._context, self) _notify() @base.remotable def destroy(self): """Delete the action plan from the DB""" related_efficacy_indicators = objects.EfficacyIndicator.list( context=self._context, filters={"action_plan_uuid": self.uuid}) # Cascade soft_delete of related efficacy indicators for related_efficacy_indicator in related_efficacy_indicators: related_efficacy_indicator.destroy() self.dbapi.destroy_action_plan(self.uuid) self.obj_reset_changes() @base.remotable def save(self): """Save updates to this Action plan. Updates will be made column by column based on the result of self.what_changed(). """ updates = self.obj_get_changes() db_obj = self.dbapi.update_action_plan(self.uuid, updates) obj = self._from_db_object(self.__class__(self._context), db_obj, eager=False) self.obj_refresh(obj) def _notify(): notifications.action_plan.send_update(self._context, self, old_state=self.old_state) _notify() self.obj_reset_changes() @base.remotable def refresh(self, eager=False): """Loads updates for this Action plan. Loads a action_plan with the same uuid from the database and checks for updated attributes. Updates are applied from the loaded action_plan column by column, if there are any updates. :param eager: Load object fields if True (Default: False) """ current = self.get_by_uuid(self._context, uuid=self.uuid, eager=eager) self.obj_refresh(current) @base.remotable def soft_delete(self): """Soft Delete the Action plan from the DB""" related_actions = objects.Action.list( context=self._context, filters={"action_plan_uuid": self.uuid}) # Cascade soft_delete of related actions for related_action in related_actions: related_action.soft_delete() related_efficacy_indicators = objects.EfficacyIndicator.list( context=self._context, filters={"action_plan_uuid": self.uuid}) # Cascade soft_delete of related efficacy indicators for related_efficacy_indicator in related_efficacy_indicators: related_efficacy_indicator.soft_delete() self.state = State.DELETED self.save() db_obj = self.dbapi.soft_delete_action_plan(self.uuid) obj = self._from_db_object(self.__class__(self._context), db_obj, eager=False) self.obj_refresh(obj) def _notify(): notifications.action_plan.send_delete(self._context, self) _notify()
class Service(base.WatcherObject): dbapi = dbapi.get_instance() fields = { 'id': int, 'name': obj_utils.str_or_none, 'host': obj_utils.str_or_none, 'last_seen_up': obj_utils.datetime_or_str_or_none } @staticmethod def _from_db_object(service, db_service): """Converts a database entity to a formal object.""" for field in service.fields: service[field] = db_service[field] service.obj_reset_changes() return service @staticmethod def _from_db_object_list(db_objects, cls, context): """Converts a list of database entities to a list of formal objects.""" return [Service._from_db_object(cls(context), obj) for obj in db_objects] @classmethod def get(cls, context, service_id): """Find a service based on its id :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Service(context) :param service_id: the id of a service. :returns: a :class:`Service` object. """ if utils.is_int_like(service_id): db_service = cls.dbapi.get_service_by_id(context, service_id) service = Service._from_db_object(cls(context), db_service) return service else: raise exception.InvalidIdentity(identity=service_id) @classmethod def get_by_name(cls, context, name): """Find a service based on name :param name: the name of a service. :param context: Security context :returns: a :class:`Service` object. """ db_service = cls.dbapi.get_service_by_name(context, name) service = cls._from_db_object(cls(context), db_service) return service @classmethod def list(cls, context, limit=None, marker=None, filters=None, sort_key=None, sort_dir=None): """Return a list of :class:`Service` objects. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Service(context) :param filters: dict mapping the filter key to a value. :param limit: maximum number of resources to return in a single result. :param marker: pagination marker for large data sets. :param sort_key: column to sort results by. :param sort_dir: direction to sort. "asc" or "desc". :returns: a list of :class:`Service` object. """ db_services = cls.dbapi.get_service_list( context, filters=filters, limit=limit, marker=marker, sort_key=sort_key, sort_dir=sort_dir) return Service._from_db_object_list(db_services, cls, context) def create(self, context=None): """Create a :class:`Service` record in the DB. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Service(context) """ values = self.obj_get_changes() db_service = self.dbapi.create_service(values) self._from_db_object(self, db_service) def save(self, context=None): """Save updates to this :class:`Service`. Updates will be made column by column based on the result of self.what_changed(). :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Service(context) """ updates = self.obj_get_changes() self.dbapi.update_service(self.id, updates) self.obj_reset_changes() def refresh(self, context=None): """Loads updates for this :class:`Service`. Loads a service with the same id from the database and checks for updated attributes. Updates are applied from the loaded service column by column, if there are any updates. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Service(context) """ current = self.__class__.get(self._context, service_id=self.id) for field in self.fields: if (hasattr(self, base.get_attrname(field)) and self[field] != current[field]): self[field] = current[field] def soft_delete(self, context=None): """Soft Delete the :class:`Service` from the DB. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Service(context) """ self.dbapi.soft_delete_service(self.id)
class EfficacyIndicator(base.WatcherObject): # Version 1.0: Initial version VERSION = '1.0' dbapi = dbapi.get_instance() fields = { 'id': int, 'uuid': obj_utils.str_or_none, 'action_plan_id': obj_utils.int_or_none, 'name': obj_utils.str_or_none, 'description': obj_utils.str_or_none, 'unit': obj_utils.str_or_none, 'value': obj_utils.numeric_or_none, } @staticmethod def _from_db_object(efficacy_indicator, db_efficacy_indicator): """Converts a database entity to a formal object.""" for field in efficacy_indicator.fields: efficacy_indicator[field] = db_efficacy_indicator[field] efficacy_indicator.obj_reset_changes() return efficacy_indicator @staticmethod def _from_db_object_list(db_objects, cls, context): """Converts a list of database entities to a list of formal objects.""" return [ EfficacyIndicator._from_db_object(cls(context), obj) for obj in db_objects ] @classmethod def get(cls, context, efficacy_indicator_id): """Find an efficacy indicator object given its ID or UUID :param efficacy_indicator_id: the ID or UUID of an efficacy indicator. :returns: a :class:`EfficacyIndicator` object. """ if utils.is_int_like(efficacy_indicator_id): return cls.get_by_id(context, efficacy_indicator_id) elif utils.is_uuid_like(efficacy_indicator_id): return cls.get_by_uuid(context, efficacy_indicator_id) else: raise exception.InvalidIdentity(identity=efficacy_indicator_id) @classmethod def get_by_id(cls, context, efficacy_indicator_id): """Find an efficacy indicator given its integer ID :param efficacy_indicator_id: the id of an efficacy indicator. :returns: a :class:`EfficacyIndicator` object. """ db_efficacy_indicator = cls.dbapi.get_efficacy_indicator_by_id( context, efficacy_indicator_id) efficacy_indicator = EfficacyIndicator._from_db_object( cls(context), db_efficacy_indicator) return efficacy_indicator @classmethod def get_by_uuid(cls, context, uuid): """Find an efficacy indicator given its UUID :param uuid: the uuid of an efficacy indicator. :param context: Security context :returns: a :class:`EfficacyIndicator` object. """ db_efficacy_indicator = cls.dbapi.get_efficacy_indicator_by_uuid( context, uuid) efficacy_indicator = EfficacyIndicator._from_db_object( cls(context), db_efficacy_indicator) return efficacy_indicator @classmethod def list(cls, context, limit=None, marker=None, filters=None, sort_key=None, sort_dir=None): """Return a list of EfficacyIndicator objects. :param context: Security context. :param limit: maximum number of resources to return in a single result. :param marker: pagination marker for large data sets. :param filters: Filters to apply. Defaults to None. :param sort_key: column to sort results by. :param sort_dir: direction to sort. "asc" or "desc". :returns: a list of :class:`EfficacyIndicator` object. """ db_efficacy_indicators = cls.dbapi.get_efficacy_indicator_list( context, limit=limit, marker=marker, filters=filters, sort_key=sort_key, sort_dir=sort_dir) return EfficacyIndicator._from_db_object_list(db_efficacy_indicators, cls, context) def create(self, context=None): """Create a EfficacyIndicator record in the DB. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: EfficacyIndicator(context) """ values = self.obj_get_changes() db_efficacy_indicator = self.dbapi.create_efficacy_indicator(values) self._from_db_object(self, db_efficacy_indicator) def destroy(self, context=None): """Delete the EfficacyIndicator from the DB. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: EfficacyIndicator(context) """ self.dbapi.destroy_efficacy_indicator(self.uuid) self.obj_reset_changes() def save(self, context=None): """Save updates to this EfficacyIndicator. Updates will be made column by column based on the result of self.what_changed(). :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: EfficacyIndicator(context) """ updates = self.obj_get_changes() self.dbapi.update_efficacy_indicator(self.uuid, updates) self.obj_reset_changes() def refresh(self, context=None): """Loads updates for this EfficacyIndicator. Loads an efficacy indicator with the same uuid from the database and checks for updated attributes. Updates are applied to the loaded efficacy indicator column by column, if there are any updates. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: EfficacyIndicator(context) """ current = self.__class__.get_by_uuid(self._context, uuid=self.uuid) for field in self.fields: if (hasattr(self, base.get_attrname(field)) and self[field] != current[field]): self[field] = current[field] def soft_delete(self, context=None): """Soft Delete the efficacy indicator from the DB. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Audit(context) """ self.dbapi.soft_delete_efficacy_indicator(self.uuid)
class Goal(base.WatcherPersistentObject, base.WatcherObject, base.WatcherObjectDictCompat): # Version 1.0: Initial version VERSION = '1.0' dbapi = db_api.get_instance() fields = { 'id': wfields.IntegerField(), 'uuid': wfields.UUIDField(), 'name': wfields.StringField(), 'display_name': wfields.StringField(), 'efficacy_specification': wfields.FlexibleListOfDictField(), } @base.remotable_classmethod def get(cls, context, goal_id): """Find a goal based on its id or uuid :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Goal(context) :param goal_id: the id *or* uuid of a goal. :returns: a :class:`Goal` object. """ if utils.is_int_like(goal_id): return cls.get_by_id(context, goal_id) elif utils.is_uuid_like(goal_id): return cls.get_by_uuid(context, goal_id) else: raise exception.InvalidIdentity(identity=goal_id) @base.remotable_classmethod def get_by_id(cls, context, goal_id): """Find a goal based on its integer id :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Goal(context) :param goal_id: the id *or* uuid of a goal. :returns: a :class:`Goal` object. """ db_goal = cls.dbapi.get_goal_by_id(context, goal_id) goal = cls._from_db_object(cls(context), db_goal) return goal @base.remotable_classmethod def get_by_uuid(cls, context, uuid): """Find a goal based on uuid :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Goal(context) :param uuid: the uuid of a goal. :returns: a :class:`Goal` object. """ db_goal = cls.dbapi.get_goal_by_uuid(context, uuid) goal = cls._from_db_object(cls(context), db_goal) return goal @base.remotable_classmethod def get_by_name(cls, context, name): """Find a goal based on name :param name: the name of a goal. :param context: Security context :returns: a :class:`Goal` object. """ db_goal = cls.dbapi.get_goal_by_name(context, name) goal = cls._from_db_object(cls(context), db_goal) return goal @base.remotable_classmethod def list(cls, context, limit=None, marker=None, filters=None, sort_key=None, sort_dir=None): """Return a list of :class:`Goal` objects. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Goal(context) :param filters: dict mapping the filter key to a value. :param limit: maximum number of resources to return in a single result. :param marker: pagination marker for large data sets. :param sort_key: column to sort results by. :param sort_dir: direction to sort. "asc" or "desc". :returns: a list of :class:`Goal` object. """ db_goals = cls.dbapi.get_goal_list( context, filters=filters, limit=limit, marker=marker, sort_key=sort_key, sort_dir=sort_dir) return [cls._from_db_object(cls(context), obj) for obj in db_goals] @base.remotable def create(self): """Create a :class:`Goal` record in the DB""" values = self.obj_get_changes() db_goal = self.dbapi.create_goal(values) self._from_db_object(self, db_goal) def destroy(self): """Delete the :class:`Goal` from the DB""" self.dbapi.destroy_goal(self.id) self.obj_reset_changes() @base.remotable def save(self): """Save updates to this :class:`Goal`. Updates will be made column by column based on the result of self.what_changed(). """ updates = self.obj_get_changes() db_obj = self.dbapi.update_goal(self.uuid, updates) obj = self._from_db_object(self, db_obj, eager=False) self.obj_refresh(obj) self.obj_reset_changes() @base.remotable def refresh(self): """Loads updates for this :class:`Goal`. Loads a goal with the same uuid from the database and checks for updated attributes. Updates are applied from the loaded goal column by column, if there are any updates. """ current = self.get_by_uuid(self._context, uuid=self.uuid) self.obj_refresh(current) @base.remotable def soft_delete(self): """Soft Delete the :class:`Goal` from the DB""" db_obj = self.dbapi.soft_delete_goal(self.uuid) obj = self._from_db_object( self.__class__(self._context), db_obj, eager=False) self.obj_refresh(obj)
class ActionDescription(base.WatcherPersistentObject, base.WatcherObject, base.WatcherObjectDictCompat): # Version 1.0: Initial version VERSION = '1.0' dbapi = db_api.get_instance() fields = { 'id': wfields.IntegerField(), 'action_type': wfields.StringField(), 'description': wfields.StringField(), } @base.remotable_classmethod def get(cls, context, action_id): """Find a action description based on its id :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object :param action_id: the id of a action description. :returns: a :class:`ActionDescription` object. """ if utils.is_int_like(action_id): db_action = cls.dbapi.get_action_description_by_id( context, action_id) action = ActionDescription._from_db_object(cls(context), db_action) return action else: raise exception.InvalidIdentity(identity=action_id) @base.remotable_classmethod def get_by_type(cls, context, action_type): """Find a action description based on action type :param action_type: the action type of a action description. :param context: Security context :returns: a :class:`ActionDescription` object. """ db_action = cls.dbapi.get_action_description_by_type( context, action_type) action = cls._from_db_object(cls(context), db_action) return action @base.remotable_classmethod def list(cls, context, limit=None, marker=None, filters=None, sort_key=None, sort_dir=None): """Return a list of :class:`ActionDescription` objects. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: ActionDescription(context) :param filters: dict mapping the filter key to a value. :param limit: maximum number of resources to return in a single result. :param marker: pagination marker for large data sets. :param sort_key: column to sort results by. :param sort_dir: direction to sort. "asc" or "desc". :returns: a list of :class:`ActionDescription` object. """ db_actions = cls.dbapi.get_action_description_list( context, filters=filters, limit=limit, marker=marker, sort_key=sort_key, sort_dir=sort_dir) return [cls._from_db_object(cls(context), obj) for obj in db_actions] @base.remotable def create(self): """Create a :class:`ActionDescription` record in the DB.""" values = self.obj_get_changes() db_action = self.dbapi.create_action_description(values) self._from_db_object(self, db_action) @base.remotable def save(self): """Save updates to this :class:`ActionDescription`. Updates will be made column by column based on the result of self.what_changed(). """ updates = self.obj_get_changes() db_obj = self.dbapi.update_action_description(self.id, updates) obj = self._from_db_object(self, db_obj, eager=False) self.obj_refresh(obj) self.obj_reset_changes() def refresh(self): """Loads updates for this :class:`ActionDescription`. Loads a action description with the same id from the database and checks for updated attributes. Updates are applied from the loaded action description column by column, if there are any updates. """ current = self.get(self._context, action_id=self.id) for field in self.fields: if (hasattr(self, base.get_attrname(field)) and self[field] != current[field]): self[field] = current[field] def soft_delete(self): """Soft Delete the :class:`ActionDescription` from the DB.""" db_obj = self.dbapi.soft_delete_action_description(self.id) obj = self._from_db_object( self.__class__(self._context), db_obj, eager=False) self.obj_refresh(obj)
class Action(base.WatcherPersistentObject, base.WatcherObject, base.WatcherObjectDictCompat): # Version 1.0: Initial version # Version 1.1: Added 'action_plan' object field # Version 2.0: Removed 'next' object field, Added 'parents' object field VERSION = '2.0' dbapi = db_api.get_instance() fields = { 'id': wfields.IntegerField(), 'uuid': wfields.UUIDField(), 'action_plan_id': wfields.IntegerField(), 'action_type': wfields.StringField(nullable=True), 'input_parameters': wfields.DictField(nullable=True), 'state': wfields.StringField(nullable=True), 'parents': wfields.ListOfStringsField(nullable=True), 'action_plan': wfields.ObjectField('ActionPlan', nullable=True), } object_fields = { 'action_plan': (objects.ActionPlan, 'action_plan_id'), } @base.remotable_classmethod def get(cls, context, action_id, eager=False): """Find a action based on its id or uuid and return a Action object. :param action_id: the id *or* uuid of a action. :param eager: Load object fields if True (Default: False) :returns: a :class:`Action` object. """ if utils.is_int_like(action_id): return cls.get_by_id(context, action_id, eager=eager) elif utils.is_uuid_like(action_id): return cls.get_by_uuid(context, action_id, eager=eager) else: raise exception.InvalidIdentity(identity=action_id) @base.remotable_classmethod def get_by_id(cls, context, action_id, eager=False): """Find a action based on its integer id and return a Action object. :param action_id: the id of a action. :param eager: Load object fields if True (Default: False) :returns: a :class:`Action` object. """ db_action = cls.dbapi.get_action_by_id(context, action_id, eager=eager) action = cls._from_db_object(cls(context), db_action, eager=eager) return action @base.remotable_classmethod def get_by_uuid(cls, context, uuid, eager=False): """Find a action based on uuid and return a :class:`Action` object. :param uuid: the uuid of a action. :param context: Security context :param eager: Load object fields if True (Default: False) :returns: a :class:`Action` object. """ db_action = cls.dbapi.get_action_by_uuid(context, uuid, eager=eager) action = cls._from_db_object(cls(context), db_action, eager=eager) return action @base.remotable_classmethod def list(cls, context, limit=None, marker=None, filters=None, sort_key=None, sort_dir=None, eager=False): """Return a list of Action objects. :param context: Security context. :param limit: maximum number of resources to return in a single result. :param marker: pagination marker for large data sets. :param filters: Filters to apply. Defaults to None. :param sort_key: column to sort results by. :param sort_dir: direction to sort. "asc" or "desc". :param eager: Load object fields if True (Default: False) :returns: a list of :class:`Action` object. """ db_actions = cls.dbapi.get_action_list(context, limit=limit, marker=marker, filters=filters, sort_key=sort_key, sort_dir=sort_dir, eager=eager) return [cls._from_db_object(cls(context), obj, eager=eager) for obj in db_actions] @base.remotable def create(self): """Create an :class:`Action` record in the DB. :returns: An :class:`Action` object. """ values = self.obj_get_changes() db_action = self.dbapi.create_action(values) # Note(v-francoise): Always load eagerly upon creation so we can send # notifications containing information about the related relationships self._from_db_object(self, db_action, eager=True) notifications.action.send_create(self.obj_context, self) def destroy(self): """Delete the Action from the DB""" self.dbapi.destroy_action(self.uuid) self.obj_reset_changes() @base.remotable def save(self): """Save updates to this Action. Updates will be made column by column based on the result of self.what_changed(). """ updates = self.obj_get_changes() db_obj = self.dbapi.update_action(self.uuid, updates) obj = self._from_db_object(self, db_obj, eager=False) self.obj_refresh(obj) notifications.action.send_update(self.obj_context, self) self.obj_reset_changes() @base.remotable def refresh(self, eager=False): """Loads updates for this Action. Loads a action with the same uuid from the database and checks for updated attributes. Updates are applied from the loaded action column by column, if there are any updates. :param eager: Load object fields if True (Default: False) """ current = self.get_by_uuid(self._context, uuid=self.uuid, eager=eager) self.obj_refresh(current) @base.remotable def soft_delete(self): """Soft Delete the Audit from the DB""" self.state = State.DELETED self.save() db_obj = self.dbapi.soft_delete_action(self.uuid) obj = self._from_db_object( self.__class__(self._context), db_obj, eager=False) self.obj_refresh(obj) notifications.action.send_delete(self.obj_context, self)
class Strategy(base.WatcherPersistentObject, base.WatcherObject, base.WatcherObjectDictCompat): # Version 1.0: Initial version # Version 1.1: Added Goal object field VERSION = '1.1' dbapi = db_api.get_instance() fields = { 'id': wfields.IntegerField(), 'uuid': wfields.UUIDField(), 'name': wfields.StringField(), 'display_name': wfields.StringField(), 'goal_id': wfields.IntegerField(), 'parameters_spec': wfields.FlexibleDictField(nullable=True), 'goal': wfields.ObjectField('Goal', nullable=True), } object_fields = {'goal': (objects.Goal, 'goal_id')} @base.remotable_classmethod def get(cls, context, strategy_id, eager=False): """Find a strategy based on its id or uuid :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Strategy(context) :param strategy_id: the id *or* uuid of a strategy. :param eager: Load object fields if True (Default: False) :returns: A :class:`Strategy` object. """ if utils.is_int_like(strategy_id): return cls.get_by_id(context, strategy_id, eager=eager) elif utils.is_uuid_like(strategy_id): return cls.get_by_uuid(context, strategy_id, eager=eager) else: raise exception.InvalidIdentity(identity=strategy_id) @base.remotable_classmethod def get_by_id(cls, context, strategy_id, eager=False): """Find a strategy based on its integer id :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Strategy(context) :param strategy_id: the id of a strategy. :param eager: Load object fields if True (Default: False) :returns: A :class:`Strategy` object. """ db_strategy = cls.dbapi.get_strategy_by_id(context, strategy_id, eager=eager) strategy = cls._from_db_object(cls(context), db_strategy, eager=eager) return strategy @base.remotable_classmethod def get_by_uuid(cls, context, uuid, eager=False): """Find a strategy based on uuid :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Strategy(context) :param uuid: the uuid of a strategy. :param eager: Load object fields if True (Default: False) :returns: A :class:`Strategy` object. """ db_strategy = cls.dbapi.get_strategy_by_uuid(context, uuid, eager=eager) strategy = cls._from_db_object(cls(context), db_strategy, eager=eager) return strategy @base.remotable_classmethod def get_by_name(cls, context, name, eager=False): """Find a strategy based on name :param context: Security context :param name: the name of a strategy. :param eager: Load object fields if True (Default: False) :returns: A :class:`Strategy` object. """ db_strategy = cls.dbapi.get_strategy_by_name(context, name, eager=eager) strategy = cls._from_db_object(cls(context), db_strategy, eager=eager) return strategy @base.remotable_classmethod def list(cls, context, limit=None, marker=None, filters=None, sort_key=None, sort_dir=None, eager=False): """Return a list of :class:`Strategy` objects. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Strategy(context) :param limit: maximum number of resources to return in a single result. :param marker: pagination marker for large data sets. :param filters: dict mapping the filter key to a value. :param sort_key: column to sort results by. :param sort_dir: direction to sort. "asc" or "desc`". :param eager: Load object fields if True (Default: False) :returns: a list of :class:`Strategy` object. """ db_strategies = cls.dbapi.get_strategy_list(context, filters=filters, limit=limit, marker=marker, sort_key=sort_key, sort_dir=sort_dir) return [ cls._from_db_object(cls(context), obj, eager=eager) for obj in db_strategies ] @base.remotable def create(self, context=None): """Create a :class:`Strategy` record in the DB. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Strategy(context) :returns: A :class:`Strategy` object. """ values = self.obj_get_changes() db_strategy = self.dbapi.create_strategy(values) # Note(v-francoise): Always load eagerly upon creation so we can send # notifications containing information about the related relationships self._from_db_object(self, db_strategy, eager=True) def destroy(self, context=None): """Delete the :class:`Strategy` from the DB. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Strategy(context) """ self.dbapi.destroy_strategy(self.id) self.obj_reset_changes() @base.remotable def save(self, context=None): """Save updates to this :class:`Strategy`. Updates will be made column by column based on the result of self.what_changed(). :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Strategy(context) """ updates = self.obj_get_changes() self.dbapi.update_strategy(self.id, updates) self.obj_reset_changes() @base.remotable def refresh(self, context=None, eager=False): """Loads updates for this :class:`Strategy`. Loads a strategy with the same uuid from the database and checks for updated attributes. Updates are applied from the loaded strategy column by column, if there are any updates. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Strategy(context) :param eager: Load object fields if True (Default: False) """ current = self.__class__.get_by_id(self._context, strategy_id=self.id, eager=eager) for field in self.fields: if (hasattr(self, base.get_attrname(field)) and self[field] != current[field]): self[field] = current[field] @base.remotable def soft_delete(self, context=None): """Soft Delete the :class:`Strategy` from the DB. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Strategy(context) """ self.dbapi.soft_delete_strategy(self.id)
def setUp(self): super(SqlAlchemyCustomTypesTestCase, self).setUp() self.dbapi = dbapi.get_instance()
def setUp(self): super(SqlAlchemyCustomTypesTestCase, self).setUp() self.dbapi = dbapi.get_instance()
class AuditTemplate(base.WatcherObject): # Version 1.0: Initial version VERSION = '1.0' dbapi = dbapi.get_instance() fields = { 'id': int, 'uuid': obj_utils.str_or_none, 'name': obj_utils.str_or_none, 'description': obj_utils.str_or_none, 'goal_id': obj_utils.int_or_none, 'strategy_id': obj_utils.int_or_none, 'extra': obj_utils.dict_or_none, 'version': obj_utils.str_or_none, 'scope': obj_utils.list_or_none, } @staticmethod def _from_db_object(audit_template, db_audit_template): """Converts a database entity to a formal object.""" for field in audit_template.fields: audit_template[field] = db_audit_template[field] audit_template.obj_reset_changes() return audit_template @staticmethod def _from_db_object_list(db_objects, cls, context): """Converts a list of database entities to a list of formal objects.""" return [ AuditTemplate._from_db_object(cls(context), obj) for obj in db_objects ] @classmethod def get(cls, context, audit_template_id): """Find an audit template based on its id or uuid :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: AuditTemplate(context) :param audit_template_id: the id *or* uuid of a audit_template. :returns: a :class:`AuditTemplate` object. """ if utils.is_int_like(audit_template_id): return cls.get_by_id(context, audit_template_id) elif utils.is_uuid_like(audit_template_id): return cls.get_by_uuid(context, audit_template_id) else: raise exception.InvalidIdentity(identity=audit_template_id) @classmethod def get_by_id(cls, context, audit_template_id): """Find an audit template based on its integer id :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: AuditTemplate(context) :param audit_template_id: the id of a audit_template. :returns: a :class:`AuditTemplate` object. """ db_audit_template = cls.dbapi.get_audit_template_by_id( context, audit_template_id) audit_template = AuditTemplate._from_db_object(cls(context), db_audit_template) return audit_template @classmethod def get_by_uuid(cls, context, uuid): """Find an audit template based on uuid :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: AuditTemplate(context) :param uuid: the uuid of a audit_template. :returns: a :class:`AuditTemplate` object. """ db_audit_template = cls.dbapi.get_audit_template_by_uuid(context, uuid) audit_template = AuditTemplate._from_db_object(cls(context), db_audit_template) return audit_template @classmethod def get_by_name(cls, context, name): """Find an audit template based on name :param name: the logical name of a audit_template. :param context: Security context :returns: a :class:`AuditTemplate` object. """ db_audit_template = cls.dbapi.get_audit_template_by_name(context, name) audit_template = AuditTemplate._from_db_object(cls(context), db_audit_template) return audit_template @classmethod def list(cls, context, filters=None, limit=None, marker=None, sort_key=None, sort_dir=None): """Return a list of :class:`AuditTemplate` objects. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: AuditTemplate(context) :param filters: dict mapping the filter key to a value. :param limit: maximum number of resources to return in a single result. :param marker: pagination marker for large data sets. :param sort_key: column to sort results by. :param sort_dir: direction to sort. "asc" or "desc". :returns: a list of :class:`AuditTemplate` object. """ db_audit_templates = cls.dbapi.get_audit_template_list( context, filters=filters, limit=limit, marker=marker, sort_key=sort_key, sort_dir=sort_dir) return AuditTemplate._from_db_object_list(db_audit_templates, cls, context) def create(self, context=None): """Create a :class:`AuditTemplate` record in the DB. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: AuditTemplate(context) """ values = self.obj_get_changes() db_audit_template = self.dbapi.create_audit_template(values) self._from_db_object(self, db_audit_template) def destroy(self, context=None): """Delete the :class:`AuditTemplate` from the DB. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: AuditTemplate(context) """ self.dbapi.destroy_audit_template(self.uuid) self.obj_reset_changes() def save(self, context=None): """Save updates to this :class:`AuditTemplate`. Updates will be made column by column based on the result of self.what_changed(). :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: AuditTemplate(context) """ updates = self.obj_get_changes() self.dbapi.update_audit_template(self.uuid, updates) self.obj_reset_changes() def refresh(self, context=None): """Loads updates for this :class:`AuditTemplate`. Loads a audit_template with the same uuid from the database and checks for updated attributes. Updates are applied from the loaded audit_template column by column, if there are any updates. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: AuditTemplate(context) """ current = self.__class__.get_by_uuid(self._context, uuid=self.uuid) for field in self.fields: if (hasattr(self, base.get_attrname(field)) and self[field] != current[field]): self[field] = current[field] def soft_delete(self, context=None): """soft Delete the :class:`AuditTemplate` from the DB. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: AuditTemplate(context) """ self.dbapi.soft_delete_audit_template(self.uuid)
class ActionPlan(base.WatcherObject): # Version 1.0: Initial version VERSION = '1.0' dbapi = dbapi.get_instance() fields = { 'id': int, 'uuid': obj_utils.str_or_none, 'audit_id': obj_utils.int_or_none, 'first_action_id': obj_utils.int_or_none, 'state': obj_utils.str_or_none, } @staticmethod def _from_db_object(action_plan, db_action_plan): """Converts a database entity to a formal object.""" for field in action_plan.fields: action_plan[field] = db_action_plan[field] action_plan.obj_reset_changes() return action_plan @staticmethod def _from_db_object_list(db_objects, cls, context): """Converts a list of database entities to a list of formal objects.""" return [ActionPlan._from_db_object( cls(context), obj) for obj in db_objects] @classmethod def get(cls, context, action_plan_id): """Find a action_plan based on its id or uuid and return a Action object. :param action_plan_id: the id *or* uuid of a action_plan. :returns: a :class:`Action` object. """ if utils.is_int_like(action_plan_id): return cls.get_by_id(context, action_plan_id) elif utils.is_uuid_like(action_plan_id): return cls.get_by_uuid(context, action_plan_id) else: raise exception.InvalidIdentity(identity=action_plan_id) @classmethod def get_by_id(cls, context, action_plan_id): """Find a action_plan based on its integer id and return a Action object. :param action_plan_id: the id of a action_plan. :returns: a :class:`Action` object. """ db_action_plan = cls.dbapi.get_action_plan_by_id( context, action_plan_id) action_plan = ActionPlan._from_db_object( cls(context), db_action_plan) return action_plan @classmethod def get_by_uuid(cls, context, uuid): """Find a action_plan based on uuid and return a :class:`Action` object. :param uuid: the uuid of a action_plan. :param context: Security context :returns: a :class:`Action` object. """ db_action_plan = cls.dbapi.get_action_plan_by_uuid(context, uuid) action_plan = ActionPlan._from_db_object(cls(context), db_action_plan) return action_plan @classmethod def list(cls, context, limit=None, marker=None, filters=None, sort_key=None, sort_dir=None): """Return a list of Action objects. :param context: Security context. :param limit: maximum number of resources to return in a single result. :param marker: pagination marker for large data sets. :param filters: Filters to apply. Defaults to None. :param sort_key: column to sort results by. :param sort_dir: direction to sort. "asc" or "desc". :returns: a list of :class:`ActionPlan` object. """ db_action_plans = cls.dbapi.get_action_plan_list(context, limit=limit, marker=marker, filters=filters, sort_key=sort_key, sort_dir=sort_dir) return ActionPlan._from_db_object_list(db_action_plans, cls, context) def create(self, context=None): """Create a Action record in the DB. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Action(context) """ values = self.obj_get_changes() db_action_plan = self.dbapi.create_action_plan(values) self._from_db_object(self, db_action_plan) def destroy(self, context=None): """Delete the Action from the DB. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Action(context) """ self.dbapi.destroy_action_plan(self.uuid) self.obj_reset_changes() def save(self, context=None): """Save updates to this Action plan. Updates will be made column by column based on the result of self.what_changed(). :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Action(context) """ updates = self.obj_get_changes() self.dbapi.update_action_plan(self.uuid, updates) self.obj_reset_changes() def refresh(self, context=None): """Loads updates for this Action plan. Loads a action_plan with the same uuid from the database and checks for updated attributes. Updates are applied from the loaded action_plan column by column, if there are any updates. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Action(context) """ current = self.__class__.get_by_uuid(self._context, uuid=self.uuid) for field in self.fields: if (hasattr(self, base.get_attrname(field)) and self[field] != current[field]): self[field] = current[field] def soft_delete(self, context=None): """soft Delete the Action plan from the DB. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Audit(context) """ related_actions = action_objects.Action.list( context=self._context, filters={"action_plan_uuid": self.uuid}) # Cascade soft_delete of related actions for related_action in related_actions: related_action.soft_delete() self.dbapi.soft_delete_action_plan(self.uuid) self.state = State.DELETED self.save()
class Audit(base.WatcherPersistentObject, base.WatcherObject, base.WatcherObjectDictCompat): # Version 1.0: Initial version # Version 1.1: Added 'goal' and 'strategy' object field # Version 1.2 Added 'auto_trigger' boolean field VERSION = '1.2' dbapi = db_api.get_instance() fields = { 'id': wfields.IntegerField(), 'uuid': wfields.UUIDField(), 'audit_type': wfields.StringField(), 'state': wfields.StringField(), 'parameters': wfields.FlexibleDictField(nullable=True), 'interval': wfields.IntegerField(nullable=True), 'scope': wfields.FlexibleListOfDictField(nullable=True), 'goal_id': wfields.IntegerField(), 'strategy_id': wfields.IntegerField(nullable=True), 'auto_trigger': wfields.BooleanField(), 'goal': wfields.ObjectField('Goal', nullable=True), 'strategy': wfields.ObjectField('Strategy', nullable=True), } object_fields = { 'goal': (objects.Goal, 'goal_id'), 'strategy': (objects.Strategy, 'strategy_id'), } # Proxified field so we can keep the previous value after an update _state = None _old_state = None # NOTE(v-francoise): The way oslo.versionedobjects works is by using a # __new__ that will automatically create the attributes referenced in # fields. These attributes are properties that raise an exception if no # value has been assigned, which means that they store the actual field # value in an "_obj_%(field)s" attribute. So because we want to proxify a # value that is already proxified, we have to do what you see below. @property def _obj_state(self): return self._state @property def _obj_old_state(self): return self._old_state @property def old_state(self): return self._old_state @_obj_old_state.setter def _obj_old_state(self, value): self._old_state = value @_obj_state.setter def _obj_state(self, value): if self._old_state is None and self._state is None: self._state = value else: self._old_state, self._state = self._state, value @base.remotable_classmethod def get(cls, context, audit_id, eager=False): """Find a audit based on its id or uuid and return a Audit object. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Audit(context) :param audit_id: the id *or* uuid of a audit. :param eager: Load object fields if True (Default: False) :returns: a :class:`Audit` object. """ if utils.is_int_like(audit_id): return cls.get_by_id(context, audit_id, eager=eager) elif utils.is_uuid_like(audit_id): return cls.get_by_uuid(context, audit_id, eager=eager) else: raise exception.InvalidIdentity(identity=audit_id) @base.remotable_classmethod def get_by_id(cls, context, audit_id, eager=False): """Find a audit based on its integer id and return a Audit object. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Audit(context) :param audit_id: the id of a audit. :param eager: Load object fields if True (Default: False) :returns: a :class:`Audit` object. """ db_audit = cls.dbapi.get_audit_by_id(context, audit_id, eager=eager) audit = cls._from_db_object(cls(context), db_audit, eager=eager) return audit @base.remotable_classmethod def get_by_uuid(cls, context, uuid, eager=False): """Find a audit based on uuid and return a :class:`Audit` object. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Audit(context) :param uuid: the uuid of a audit. :param eager: Load object fields if True (Default: False) :returns: a :class:`Audit` object. """ db_audit = cls.dbapi.get_audit_by_uuid(context, uuid, eager=eager) audit = cls._from_db_object(cls(context), db_audit, eager=eager) return audit @base.remotable_classmethod def list(cls, context, limit=None, marker=None, filters=None, sort_key=None, sort_dir=None, eager=False): """Return a list of Audit objects. :param context: Security context. NOTE: This should only be used internally by the indirection_api. Unfortunately, RPC requires context as the first argument, even though we don't use it. A context should be set when instantiating the object, e.g.: Audit(context) :param limit: maximum number of resources to return in a single result. :param marker: pagination marker for large data sets. :param filters: Filters to apply. Defaults to None. :param sort_key: column to sort results by. :param sort_dir: direction to sort. "asc" or "desc". :param eager: Load object fields if True (Default: False) :returns: a list of :class:`Audit` object. """ db_audits = cls.dbapi.get_audit_list(context, limit=limit, marker=marker, filters=filters, sort_key=sort_key, sort_dir=sort_dir, eager=eager) return [cls._from_db_object(cls(context), obj, eager=eager) for obj in db_audits] @base.remotable def create(self): """Create an :class:`Audit` record in the DB. :returns: An :class:`Audit` object. """ values = self.obj_get_changes() db_audit = self.dbapi.create_audit(values) # Note(v-francoise): Always load eagerly upon creation so we can send # notifications containing information about the related relationships self._from_db_object(self, db_audit, eager=True) def _notify(): notifications.audit.send_create(self._context, self) _notify() @base.remotable def destroy(self): """Delete the Audit from the DB.""" self.dbapi.destroy_audit(self.uuid) self.obj_reset_changes() @base.remotable def save(self): """Save updates to this Audit. Updates will be made column by column based on the result of self.what_changed(). """ updates = self.obj_get_changes() db_obj = self.dbapi.update_audit(self.uuid, updates) obj = self._from_db_object( self.__class__(self._context), db_obj, eager=False) self.obj_refresh(obj) def _notify(): notifications.audit.send_update( self._context, self, old_state=self.old_state) _notify() self.obj_reset_changes() @base.remotable def refresh(self, eager=False): """Loads updates for this Audit. Loads a audit with the same uuid from the database and checks for updated attributes. Updates are applied from the loaded audit column by column, if there are any updates. :param eager: Load object fields if True (Default: False) """ current = self.get_by_uuid(self._context, uuid=self.uuid, eager=eager) self.obj_refresh(current) @base.remotable def soft_delete(self): """Soft Delete the Audit from the DB.""" self.state = State.DELETED self.save() db_obj = self.dbapi.soft_delete_audit(self.uuid) obj = self._from_db_object( self.__class__(self._context), db_obj, eager=False) self.obj_refresh(obj) def _notify(): notifications.audit.send_delete(self._context, self) _notify()