def _read_watch_event(self, buffer, offset): client = self.client watch, offset = Watch.deserialize(buffer, offset) path = watch.path if self.log_debug: log.debug('Received EVENT: %s', watch) watchers = [] if watch.type in (CREATED_EVENT, CHANGED_EVENT): watchers.extend(client._data_watchers.pop(path, [])) elif watch.type == DELETED_EVENT: watchers.extend(client._data_watchers.pop(path, [])) watchers.extend(client._child_watchers.pop(path, [])) elif watch.type == CHILD_EVENT: watchers.extend(client._child_watchers.pop(path, [])) else: log.warn('Received unknown event %r', watch.type) return # Strip the chroot if needed path = client.unchroot(path) ev = WatchedEvent(EVENT_TYPE_MAP[watch.type], client._state, path) # Last check to ignore watches if we've been stopped if client._stopped.is_set(): return # Dump the watchers to the watch thread for watch in watchers: client.handler.dispatch_callback(Callback('watch', watch, (ev, )))
def _submit_task(self, task): """ If node does not exist in ZK, create node. Set data watch on that node. :type task: zoom.agent.task.task.Task """ try: task_path = zk_path_join(self._configuration.task_path, task.host) if self._zoo_keeper.exists(task_path): # if the node exists, check if it is done e = WatchedEvent(None, None, task_path) self._on_update(e) else: logging.info("Creating task node for path {0}: {1}".format( task_path, task)) try: self._zoo_keeper.create(task_path, value=task.to_json()) except NodeExistsError: pass self._zoo_keeper.get(task_path, watch=self._on_update) except NoNodeError: pass
def _verify_wait_success(zoo_keeper_client: KazooClient): get_args, _ = zoo_keeper_client.get.call_args path, node_watcher = get_args assert path == SOME_PATH zk_node_evt = WatchedEvent(path=SOME_PATH, type=EventType.CHANGED, state=KeeperState.CONNECTED_RO) node_watcher(zk_node_evt)
def mock_delete(path: str): if not mock_exists(path): raise NoNodeError(f"{path} not found") # Recursive delete in any form for node_path, watchers in nodes.items(): if node_path.startswith(path) and path != node_path: assert False, NOT_SUPPORTED_YET watchers = nodes.pop(path) for watcher in watchers: event = WatchedEvent(EventType.DELETED, path, KazooState.CONNECTED) watcher(event)
def _watch_children(self, event): # Called when a child node is deleted if event.type == EventType.DELETED: # Remove child watcher from our records del self._child_watchers[event.path] # remove datawatchers? return # Get children and set a child watch for the next event of this path children = self._zk.retry(self._zk.get_children, event.path, watch=self._watch_children) # Update our records self._child_watchers[event.path] = children # If no children, there is nothing to do; no watchers to set if len(children) == 0: return # Find location in stack for children level = len(event.path.strip('/').split('/')) child_depth_marker = self._stack[level] for child in children: path = "{0}/{1}".format(event.path, child) if child_depth_marker == '?' or child == child_depth_marker: # Set child_watcher for each child if path not in self._child_watchers: we = WatchedEvent(None, None, path) self._watch_children(we) elif child_depth_marker == '!': # Set data_watcher for each child if path not in self._data_watchers: we = WatchedEvent(None, None, path) self._watch_data(we)
def __init__(self, zk_hosts, def_path='/env/?/sd/!'): c_retry = KazooRetry(-1, max_delay=60) self._zk = KazooClient(','.join(zk_hosts), read_only=True, connection_retry=c_retry) self._zk.start(timeout=10) self._child_watchers = {} self._data_watchers = {} # Note about "stack": the stack is a ZK path of where to find service definitions. It solves the problem of a # tree watcher watching an entire tree. A node is only watched if it adhears to the stack pattern. A "?" means # "watch children of whatever is here" (this must be the environment). A "!" means "watch data of whatever is # here" (this must be the service defs). Anything else is a constant, so it will only watch the children of that # specific node if it exists. self._stack = tuple(def_path.strip('/').split('/')) we = WatchedEvent(None, None, '/' + self._stack[0]) self._watch_children(we)