def update(self,
               context,
               resource,
               fix_ownership=False,
               force_update=False,
               **update_attr_val):
        """Persist updates to AIM resource to the database.

        Values of identity attributes of parameter 'resource' are used
        to determine the database object to update; no other attributes
        from 'resource' are used during the update. Param 'update_attr_val'
        specifies the values of the attributes to update.
        If the object does not exist in the database, no changes are
        made to the database.
        """
        self._validate_resource_class(resource)
        with context.store.begin(subtransactions=True):
            db_obj = self._query_db_obj(context.store, resource)
            if db_obj:
                old_resource = self._make_resource(context, resource, db_obj)
                old_monitored = getattr(db_obj, 'monitored', None)
                new_monitored = update_attr_val.get('monitored')
                if (fix_ownership and old_monitored is not None
                        and old_monitored != new_monitored):
                    raise exc.InvalidMonitoredStateUpdate(object=resource)
                attr_val = {
                    k: v
                    for k, v in update_attr_val.iteritems()
                    if k in resource.other_attributes.keys()
                }
                if attr_val:
                    old_resource_copy = copy.deepcopy(old_resource)
                    for k, v in attr_val.iteritems():
                        setattr(old_resource, k, v)
                    if old_resource.user_equal(
                            old_resource_copy) and not force_update:
                        # Nothing to do here
                        return old_resource
                elif resource.identity_attributes:
                    # force update
                    id_attr_0 = resource.identity_attributes.keys()[0]
                    attr_val = {id_attr_0: getattr(resource, id_attr_0)}
                context.store.from_attr(db_obj, type(resource), attr_val)
                context.store.add(db_obj)
                if self._should_set_pending(db_obj, old_monitored,
                                            new_monitored):
                    # NOTE(ivar): we shouldn't change status in the AIM manager
                    # as this goes against the "AIM as a schema" principles.
                    # However, we need to do this at least for cases where
                    # we take ownership of the objects, which should be removed
                    # soon as it's causing most of our bugs.
                    self.set_resource_sync_pending(context, resource)
                return self.get(context, resource)
    def create(self, context, resource, overwrite=False, fix_ownership=False):
        """Persist AIM resource to the database.

        If 'overwrite' is True, and an object exists in the database
        with the same identity attribute values, then that object will
        be over-written with the specified resource. Otherwise an
        integrity constraint violation is raised.
        """
        self._validate_resource_class(resource)
        with context.store.begin(subtransactions=True):
            old_db_obj = None
            old_monitored = None
            new_monitored = None
            if overwrite:
                old_db_obj = self._query_db_obj(context.store, resource)
                if old_db_obj:
                    old_monitored = getattr(old_db_obj, 'monitored', None)
                    new_monitored = getattr(resource, 'monitored', None)
                    if (fix_ownership and old_monitored is not None
                            and old_monitored != new_monitored):
                        raise exc.InvalidMonitoredStateUpdate(object=resource)
                    attr_val = context.store.extract_attributes(
                        resource, "other")
                    old_resource = self._make_resource(context, resource,
                                                       old_db_obj)
                    if old_resource.user_equal(resource):
                        # No need to update. Return old_resource for
                        # updated DB attributes
                        return old_resource
                    context.store.from_attr(old_db_obj, type(resource),
                                            attr_val)
            db_obj = old_db_obj or context.store.make_db_obj(resource)
            context.store.add(db_obj)
            if self._should_set_pending(old_db_obj, old_monitored,
                                        new_monitored):
                # NOTE(ivar): we shouldn't change status in the AIM manager
                # as this goes against the "AIM as a schema" principles.
                # However, we need to do this at least for cases where
                # we take ownership of the objects, which should be removed
                # soon as it's causing most of our bugs.
                self.set_resource_sync_pending(context, resource)
            return self.get(context, resource)