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)