def claim(self, job, who, expiry=None): if expiry is None: # On the lua side none doesn't translate to nil so we have # do to this string conversion to make sure that we can tell # the difference. ms_expiry = "none" else: ms_expiry = int(expiry * 1000.0) if ms_expiry <= 0: raise ValueError("Provided expiry (when converted to" " milliseconds) must be greater" " than zero instead of %s" % (expiry)) script = self._get_script('claim') with _translate_failures(): raw_who = self._encode_owner(who) raw_result = script( keys=[job.owner_key, self.listings_key, job.last_modified_key], args=[ raw_who, job.key, # NOTE(harlowja): we need to send this # in as a blob (even if it's not # set/used), since the format can not # currently be created in lua... self._dumps(timeutils.utcnow()), ms_expiry ]) result = self._loads(raw_result) status = result['status'] if status != self.SCRIPT_STATUS_OK: reason = result.get('reason') if reason == self.SCRIPT_UNKNOWN_JOB: raise exc.NotFound("Job %s not found to be" " claimed" % (job.uuid)) elif reason == self.SCRIPT_ALREADY_CLAIMED: raw_owner = result.get('owner') if raw_owner: owner = self._decode_owner(raw_owner) raise exc.UnclaimableJob("Job %s already" " claimed by %s" % (job.uuid, owner)) else: raise exc.UnclaimableJob("Job %s already" " claimed" % (job.uuid)) else: raise exc.JobFailure("Failure to claim job %s," " unknown internal error (reason=%s)" % (job.uuid, reason))
def _unclaimable_try_find_owner(cause): try: owner = self.find_owner(job) except Exception: owner = None if owner: msg = "Job %s already claimed by '%s'" % (job.uuid, owner) else: msg = "Job %s already claimed" % (job.uuid) return excp.UnclaimableJob(msg, cause)
def claim(self, job, who): def _unclaimable_try_find_owner(cause): try: owner = self.find_owner(job) except Exception: owner = None if owner: msg = "Job %s already claimed by '%s'" % (job.uuid, owner) else: msg = "Job %s already claimed" % (job.uuid) return excp.UnclaimableJob(msg, cause) _check_who(who) with self._wrap(job.uuid, job.path, "Claiming failure: %s"): # NOTE(harlowja): post as json which will allow for future changes # more easily than a raw string/text. value = jsonutils.dumps({ 'owner': who, }) # Ensure the target job is still existent (at the right version). job_data, job_stat = self._client.get(job.path) txn = self._client.transaction() # This will abort (and not create the lock) if the job has been # removed (somehow...) or updated by someone else to a different # version... txn.check(job.path, version=job_stat.version) txn.create(job.lock_path, value=misc.binary_encode(value), ephemeral=True) try: kazoo_utils.checked_commit(txn) except k_exceptions.NodeExistsError as e: raise _unclaimable_try_find_owner(e) except kazoo_utils.KazooTransactionException as e: if len(e.failures) < 2: raise else: if isinstance(e.failures[0], k_exceptions.NoNodeError): raise excp.NotFound( "Job %s not found to be claimed" % job.uuid, e.failures[0]) if isinstance(e.failures[1], k_exceptions.NodeExistsError): raise _unclaimable_try_find_owner(e.failures[1]) else: raise excp.UnclaimableJob( "Job %s claim failed due to transaction" " not succeeding" % (job.uuid), e)
def claim(self, job, who): _check_who(who) job_path, lock_path = _get_paths(self.path, job.uuid) with self._wrap(job.uuid, "Claiming failure: %s"): # NOTE(harlowja): post as json which will allow for future changes # more easily than a raw string/text. value = jsonutils.dumps({ 'owner': who, }) try: self._client.create(lock_path, value=misc.binary_encode(value), ephemeral=True) except k_exceptions.NodeExistsException: # Try to see if we can find who the owner really is... try: owner = self.find_owner(job) except Exception: owner = None if owner: msg = "Job %s already claimed by '%s'" % (job.uuid, owner) else: msg = "Job %s already claimed" % (job.uuid) raise excp.UnclaimableJob(msg)