def create(self): if self.id is not None: raise exception.ObjectActionError(action='create', reason='already created') if not self.name: raise exception.ObjectActionError(action='create', reason='name is required') if self.name in orc.STANDARDS: raise exception.ResourceClassExists(resource_class=self.name) if not self.name.startswith(orc.CUSTOM_NAMESPACE): raise exception.ObjectActionError(action='create', reason='name must start with ' + orc.CUSTOM_NAMESPACE) updates = {} for field in ['name', 'updated_at', 'created_at']: value = getattr(self, field, None) if value: updates[field] = value # There is the possibility of a race when adding resource classes, as # the ID is generated locally. This loop catches that exception, and # retries until either it succeeds, or a different exception is # encountered. retries = self.RESOURCE_CREATE_RETRY_COUNT while retries: retries -= 1 try: rc = self._create_in_db(self._context, updates) self._from_db_object(self._context, self, rc) break except db_exc.DBDuplicateEntry as e: if 'id' in e.columns: # Race condition for ID creation; try again continue # The duplication is on the other unique column, 'name'. So do # not retry; raise the exception immediately. raise exception.ResourceClassExists(resource_class=self.name) else: # We have no idea how common it will be in practice for the retry # limit to be exceeded. We set it high in the hope that we never # hit this point, but added this log message so we know that this # specific situation occurred. LOG.warning( "Exceeded retry limit on ID generation while " "creating ResourceClass %(name)s", {'name': self.name}) msg = "creating resource class %s" % self.name raise exception.MaxDBRetriesExceeded(action=msg) self._context.rc_cache.clear()
def _save(context, id, name, updates): db_rc = context.session.query( models.ResourceClass).filter_by(id=id).first() db_rc.update(updates) try: db_rc.save(context.session) except db_exc.DBDuplicateEntry: raise exception.ResourceClassExists(resource_class=name)
def _save(context, name, updates): update_list = ["rc.%s = '%s'" % (k, v) for k, v in updates.items()] update_str = ", ".join(update_list) query = """ MATCH (rc:RESOURCE_CLASS {name: '%s'}) WITH rc SET %s RETURN rc """ % (name, update_str) try: result = context.tx.run(query).data() except db.ClientError: raise exception.ResourceClassExists(resource_class=name)