def delete_resource(self, resource_id): with self.facade.writer() as session: # We are going to delete the resource; the on delete will set the # resource_id of the attached metrics to NULL, we just have to mark # their status as 'delete' session.query(Metric).filter( Metric.resource_id == resource_id).update({"status": "delete"}) if session.query(Resource).filter( Resource.id == resource_id).delete() == 0: raise indexer.NoSuchResource(resource_id)
def update_resource(self, resource_type, resource_id, ended_at=_marker, metrics=_marker, append_metrics=False, create_revision=True, **kwargs): resource_cls = self._resource_type_to_class(resource_type) resource_history_cls = self._resource_type_to_class( resource_type, "history") with self.facade.writer() as session: try: # NOTE(sileht): We use FOR UPDATE that is not galera friendly, # but they are no other way to cleanly patch a resource and # store the history that safe when two concurrent calls are # done. q = session.query(resource_cls).filter( resource_cls.id == resource_id).with_for_update() r = q.first() if r is None: raise indexer.NoSuchResource(resource_id) if create_revision: # Build history rh = resource_history_cls() for col in sqlalchemy.inspect(resource_cls).columns: setattr(rh, col.name, getattr(r, col.name)) now = utils.utcnow() rh.revision_end = now session.add(rh) r.revision_start = now # Update the resource if ended_at is not _marker: # NOTE(jd) MySQL does not honor checks. I hate it. engine = session.connection() if engine.dialect.name == "mysql": if r.started_at is not None and ended_at is not None: if r.started_at > ended_at: raise indexer.ResourceValueError( resource_type, "ended_at", ended_at) r.ended_at = ended_at if kwargs: for attribute, value in six.iteritems(kwargs): if hasattr(r, attribute): setattr(r, attribute, value) else: raise indexer.ResourceAttributeError( r.type, attribute) if metrics is not _marker: if not append_metrics: session.query(Metric).filter( Metric.resource_id == resource_id, Metric.status == 'active').update( {"resource_id": None}) self._set_metrics_for_resource(session, r, metrics) session.flush() except exception.DBConstraintError as e: if e.check_name == "ck_started_before_ended": raise indexer.ResourceValueError(resource_type, "ended_at", ended_at) raise # NOTE(jd) Force load of metrics – do it outside the session! r.metrics return r