Beispiel #1
0
    def test_register_default(self):
        called = {
            'default': 0,
        }

        def _default(o):
            called['default'] += 1
            return str(o)

        zag_json.register(default=_default)

        zag_json.dumps({'a': object(), 'c': object()})
        self.assertEqual(2, called['default'])
Beispiel #2
0
 def register_entity(self, entity):
     entity_type = entity.kind
     if entity_type == c_base.Conductor.ENTITY_KIND:
         entity_path = k_paths.join(self.entity_path, entity_type)
         try:
             self._client.ensure_path(entity_path)
             self._client.create(k_paths.join(entity_path, entity.name),
                                 value=misc.binary_encode(
                                     zag_json.dumps(entity.to_dict())),
                                 ephemeral=True)
         except k_exceptions.NodeExistsError:
             pass
         except self._client.handler.timeout_exception:
             excp.raise_with_cause(
                 excp.JobFailure,
                 "Can not register entity %s under %s, operation"
                 " timed out" % (entity.name, entity_path))
         except k_exceptions.SessionExpiredError:
             excp.raise_with_cause(
                 excp.JobFailure,
                 "Can not register entity %s under %s, session"
                 " expired" % (entity.name, entity_path))
         except k_exceptions.KazooException:
             excp.raise_with_cause(
                 excp.JobFailure,
                 "Can not register entity %s under %s, internal"
                 " error" % (entity.name, entity_path))
     else:
         raise excp.NotImplementedError(
             "Not implemented for other entity type '%s'" % entity_type)
Beispiel #3
0
 def _do_job_posting(self, name, job_uuid, job_posting, book, details,
                     job_priority):
     raw_job_posting = misc.binary_encode(zag_json.dumps(job_posting))
     with self._wrap(job_uuid,
                     None,
                     fail_msg_tpl="Posting failure: %s",
                     ensure_known=False):
         job_path = self._client.create(self._job_base,
                                        value=raw_job_posting,
                                        sequence=True,
                                        ephemeral=False)
         job = ZookeeperJob(self,
                            name,
                            self._client,
                            job_path,
                            backend=self._persistence,
                            book=book,
                            details=details,
                            uuid=job_uuid,
                            book_data=job_posting.get('book'),
                            priority=job_priority)
         with self._job_cond:
             self._known_jobs[job_path] = job
             self._job_cond.notify_all()
         self._try_emit(base.POSTED, details={'job': job})
         return job
Beispiel #4
0
 def _change_owner(self, new_owner):
     children = self.client.storage.get_children("/zag", only_direct=False)
     altered = 0
     for p, data in six.iteritems(children):
         if p.endswith(".lock"):
             self.client.set(
                 p, misc.binary_encode(zag_json.dumps({'owner':
                                                       new_owner})))
             altered += 1
     return altered
Beispiel #5
0
    def test_register_dumps_loads(self):
        called = {
            'dumps': 0,
            'loads': 0,
        }

        def _dumps(*args, **kwargs):
            called['dumps'] += 1

        def _loads(*args, **kwargs):
            called['loads'] += 1

        zag_json.register(dumps=_dumps, loads=_loads)

        zag_json.dumps({})
        self.assertEqual(1, called['dumps'])
        self.assertEqual(0, called['loads'])

        zag_json.loads("{}")
        self.assertEqual(1, called['loads'])
Beispiel #6
0
    def claim(self, job, who):
        def _unclaimable_try_find_owner(cause):
            try:
                owner = self.find_owner(job)
            except Exception:
                owner = None
            if owner:
                message = "Job %s already claimed by '%s'" % (job.uuid, owner)
            else:
                message = "Job %s already claimed" % (job.uuid)
            excp.raise_with_cause(excp.UnclaimableJob, message, cause=cause)

        with self._wrap(job.uuid,
                        job.path,
                        fail_msg_tpl="Claiming failure: %s"):
            # NOTE(harlowja): post as json which will allow for future changes
            # more easily than a raw string/text.
            value = zag_json.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:
                _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):
                        excp.raise_with_cause(
                            excp.NotFound,
                            "Job %s not found to be claimed" % job.uuid,
                            cause=e.failures[0])
                    if isinstance(e.failures[1], k_exceptions.NodeExistsError):
                        _unclaimable_try_find_owner(e.failures[1])
                    else:
                        excp.raise_with_cause(
                            excp.UnclaimableJob,
                            "Job %s claim failed due to transaction"
                            " not succeeding" % (job.uuid),
                            cause=e)
Beispiel #7
0
    def test_posting_owner_lost(self):

        with base.connect_close(self.board):
            with self.flush(self.client):
                j = self.board.post('test', test_utils.test_factory)
            self.assertEqual(states.UNCLAIMED, j.state)
            with self.flush(self.client):
                self.board.claim(j, self.board.name)
            self.assertEqual(states.CLAIMED, j.state)

            # Forcefully delete the owner from the backend storage to make
            # sure the job becomes unclaimed (this may happen if some admin
            # manually deletes the lock).
            paths = list(six.iteritems(self.client.storage.paths))
            for (path, value) in paths:
                if path in self.bad_paths:
                    continue
                if path.endswith('lock'):
                    value['data'] = misc.binary_encode(zag_json.dumps({}))
            self.assertEqual(states.UNCLAIMED, j.state)
Beispiel #8
0
 def test_non_empty_group_single_worker(self, get_coordinator_mock):
     get_coordinator_mock.return_value = self.coordinator
     finder = worker_types.ToozWorkerFinder("blah://", 'me', ['a'])
     self.coordinator.get_groups.return_value = ToozFakeResult(['a'])
     self.coordinator.get_members.return_value = ToozFakeResult(['e'])
     worker_capabilities = {
         'topic': '1-202-555-0198',
         'tasks': ['y', 'z'],
     }
     worker_result = ToozFakeResult(zag_json.dumps(worker_capabilities))
     self.coordinator.get_member_capabilities.return_value = worker_result
     finder.start()
     self.assertEqual(1, finder.available_workers)
     w = finder.get_worker_for_task('y')
     self.assertIsNotNone(w)
     self.assertEqual(w.identity, 'e')
     self.assertTrue(w.performs('z'))
     self.coordinator.get_members.assert_any_call('a')
     finder.clear()
     self.assertEqual(0, finder.available_workers)
Beispiel #9
0
 def trash(self, job, who):
     with self._wrap(job.uuid, job.path, fail_msg_tpl="Trash failure: %s"):
         try:
             owner_data = self._get_owner_and_data(job)
             lock_data, lock_stat, data, data_stat = owner_data
         except k_exceptions.NoNodeError:
             excp.raise_with_cause(
                 excp.NotFound, "Can not trash a job %s"
                 " which we can not determine"
                 " the owner of" % (job.uuid))
         if lock_data.get("owner") != who:
             raise excp.JobFailure("Can not trash a job %s"
                                   " which is not owned by %s" %
                                   (job.uuid, who))
         trash_path = job.path.replace(self.path, self.trash_path)
         value = misc.binary_encode(zag_json.dumps(data))
         txn = self._client.transaction()
         txn.create(trash_path, value=value)
         txn.delete(job.lock_path, version=lock_stat.version)
         txn.delete(job.path, version=data_stat.version)
         kazoo_utils.checked_commit(txn)
Beispiel #10
0
    def test_empty_group_watch_join_triggered(self, get_coordinator_mock):
        join_watchers = []
        leave_watchers = []
        capture_join_watchers = lambda g, cb: join_watchers.append((g, cb))
        capture_leave_watchers = lambda g, cb: leave_watchers.append((g, cb))

        def run_watchers(watchers, event):
            for g, cb in watchers:
                cb(event)

        get_coordinator_mock.return_value = self.coordinator
        finder = worker_types.ToozWorkerFinder("blah://", 'me', ['a'])
        self.coordinator.get_groups.return_value = ToozFakeResult(['a'])
        self.coordinator.get_members.return_value = ToozFakeResult([])
        self.coordinator.watch_join_group.side_effect = capture_join_watchers
        self.coordinator.watch_leave_group.side_effect = capture_leave_watchers
        finder.start()
        self.assertEqual(0, finder.available_workers)
        self.assertEqual(1, len(join_watchers))
        self.assertEqual(1, len(leave_watchers))

        event = coordination.MemberJoinedGroup('a', 'y')
        run_join_watchers = functools.partial(run_watchers, join_watchers,
                                              event)
        self.coordinator.run_watchers.side_effect = run_join_watchers
        worker_capabilities = {
            'topic': '1-202-555-0133',
            'tasks': ['y', 'z'],
        }
        worker_result = ToozFakeResult(zag_json.dumps(worker_capabilities))
        self.coordinator.get_member_capabilities.return_value = worker_result
        finder.notice()
        self.assertTrue(self.coordinator.get_member_capabilities.called)
        self.coordinator.get_member_capabilities.assert_any_call('a', 'y')

        self.assertEqual(1, finder.available_workers)
        w = finder.get_worker_for_task('y')
        self.assertIsNotNone(w)
Beispiel #11
0
 def dumps(topic, tasks):
     return misc.binary_encode(
         zag_json.dumps({
             'topic': topic,
             'tasks': tasks,
         }))
Beispiel #12
0
 def get_worker_capabilities(group_id, member_id):
     return ToozFakeResult(zag_json.dumps(workers[member_id]))
Beispiel #13
0
 def _set_item(self, path, value, transaction):
     with self._path_lock(path):
         item_path = self._join_path(path, 'metadata')
         self._write_to(item_path, zag_json.dumps(value))