Esempio n. 1
0
    def _getCircuitState(self):
        # check if zookeeper circuit state node initialized
        if not self.zookeeper.exists('/circuit'):
            #print 'no circuit has been established in zookeeper'
            #print 'initialize empty circuit state in zookeeper'
            self.zookeeper.create('/circuit')

        # get circuit states
        authenticators = self.zookeeper.get_children('/circuit')

        for auth in authenticators:
            # transaction guarantees that
            # if /circuit/authenticator exists
            # then all three its children exist


            # return type is a tuple
            next_ip = self.zookeeper.get('/circuit/{0}/next_ip'.format(auth))[0]
            next_ips = self.zookeeper.get('/circuit/{0}/next_ips'.format(auth))[0]
            next_auth = self.zookeeper.get('/circuit/{0}/next_auth'.format(auth))[0]

            # set watchers
            watchers.DataWatch(self.zookeeper, '/circuit/{0}/next_ip'.format(auth), self._nextIpWatcher)
            watchers.DataWatch(self.zookeeper, '/circuit/{0}/next_ips'.format(auth), self._nextIpsWatcher)
            watchers.DataWatch(self.zookeeper, '/circuit/{0}/next_auth'.format(auth), self._nextAuthWatcher)

            self.circuitStates[auth] = dict([
                                                    ('next_ip', next_ip),
                                                    ('next_ips', next_ips),
                                                    ('next_auth', next_auth)
                                                    ])
Esempio n. 2
0
    def test_data_watch(self):
        updates = collections.deque()
        ev = Event()

        def notify_me(data, stat):
            updates.append((data, stat))
            ev.set()

        k_watchers.DataWatch(self.client, "/b", func=notify_me)
        with start_close(self.client) as c:
            self.assertTrue(ev.wait(WAIT_TIME))
            ev.clear()
            c.ensure_path("/b")
            self.assertTrue(ev.wait(WAIT_TIME))
            ev.clear()
            c.set("/b", b"1")
            self.assertTrue(ev.wait(WAIT_TIME))
            ev.clear()
            c.set("/b", b"2")
            self.assertTrue(ev.wait(WAIT_TIME))
            ev.clear()

        self.assertEqual(4, len(updates))

        ev.clear()
        with start_close(self.client) as c:
            c.delete("/b")
            self.assertTrue(ev.wait(WAIT_TIME))

        self.assertEqual(5, len(updates))
Esempio n. 3
0
    def __init__(self, zk, path, callback=None, watch_children=True):
        """Initialize the Watcher object and begin watching a path.

        The initialization of a Watcher object automatically registers a
        data watch in Zookeeper on the path specificed. Any and all
        callbacks supplied during this initialization are executed as soon
        as the data is returned by Zookeeper.

        Optionally, a subsequent child watch is created on the children
        of the supplied path and again these callbacks are executed
        any time Zookeeper tells us that the children have changed
        in any way.

        args:
            zk: A kazoo.client.KazooClient object
            path: The path in Zookeeper to watch
            callback: A function to call when the path data changes
            wach_children: Whether or not to watch the children
        """
        # Set our local variables
        self._zk = zk
        self._path = path
        self._watch_children = watch_children

        # Get a lock handler
        self._run_lock = self._zk.handler.lock_object()

        # Create local caches of the 'data' and the 'children' data
        self._children = []
        self._data = None
        self._stat = None

        # Keep track of our Watcher objects in Kazoo with local references
        self._current_data_watch = None
        self._current_children_watch = None

        # Array to hold any callback functions we're supposed to notify when
        # anything changes on this path
        self._callbacks = []
        if callback:
            self._callbacks.append(callback)

        # Quick copy of the data last used when executing callbacks -- used
        # to prevent duplicate callback executions due to multiple watches.
        self._last_callback_executed_with = None

        # if self._state is False, then even on a data change, our callbacks
        # do not run.
        self._state = True

        # Start up our DataWatch. This can be started on any path regardless of
        # whether it exists or not. ChildrenWatch objects though must be
        # started on only existing-paths -- so we do not create that object
        # here, but instead do it from with the self._update() method.
        log.debug('[%s] Registering DataWatch (%s)' %
                  (self._path, self._current_data_watch))
        self._current_data_watch = watchers.DataWatch(
            client=self._zk,
            path=self._path,
            func=self._update)
Esempio n. 4
0
    def _circuitNodeWatcher(self, children):
        #print '/circuit children updates'
        #print 'children = ' + str(children)
        for auth in children:
            if auth not in self.circuitStates:
                # return type is a tuple
                next_ip = self.zookeeper.get('/circuit/{0}/next_ip'.format(auth))[0]
                next_ips = self.zookeeper.get('/circuit/{0}/next_ips'.format(auth))[0]
                next_auth = self.zookeeper.get('/circuit/{0}/next_auth'.format(auth))[0]

                # set watchers
                watchers.DataWatch(self.zookeeper, '/circuit/{0}/next_ip'.format(auth), self._nextIpWatcher)
                watchers.DataWatch(self.zookeeper, '/circuit/{0}/next_ips'.format(auth), self._nextIpsWatcher)
                watchers.DataWatch(self.zookeeper, '/circuit/{0}/next_auth'.format(auth), self._nextAuthWatcher)

                self.circuitStates[auth] = dict([
                                                        ('next_ip', next_ip),
                                                        ('next_ips', next_ips),
                                                        ('next_auth', next_auth)
                                                        ])
                # register at local service table
                register_service(auth, next_ip, next_auth)
        return
Esempio n. 5
0
    def flush(self, client, path=None):
        # This uses the linearity guarantee of zookeeper (and associated
        # libraries) to create a temporary node, wait until a watcher notifies
        # it's created, then yield back for more work, and then at the end of
        # that work delete the created node. This ensures that the operations
        # done in the yield of this context manager will be applied and all
        # watchers will have fired before this context manager exits.
        if not path:
            path = FLUSH_PATH_TPL % uuidutils.generate_uuid()
        created = threading.Event()
        deleted = threading.Event()

        def on_created(data, stat):
            if stat is not None:
                created.set()
                return False  # cause this watcher to cease to exist

        def on_deleted(data, stat):
            if stat is None:
                deleted.set()
                return False  # cause this watcher to cease to exist

        watchers.DataWatch(client, path, func=on_created)
        client.create(path, makepath=True)
        if not created.wait(test_utils.WAIT_TIMEOUT):
            raise RuntimeError("Could not receive creation of %s in"
                               " the alloted timeout of %s seconds" %
                               (path, test_utils.WAIT_TIMEOUT))
        try:
            yield
        finally:
            watchers.DataWatch(client, path, func=on_deleted)
            client.delete(path, recursive=True)
            if not deleted.wait(test_utils.WAIT_TIMEOUT):
                raise RuntimeError("Could not receive deletion of %s in"
                                   " the alloted timeout of %s seconds" %
                                   (path, test_utils.WAIT_TIMEOUT))
Esempio n. 6
0
    def test_data_watch_not_triggered(self):
        ev = Event()
        updates = []

        def notify_me(data, stat):
            if stat:
                updates.append((data, stat))
                ev.set()

        k_watchers.DataWatch(self.client, "/b", func=notify_me)
        with start_close(self.client) as c:
            with c.transaction() as txn:
                txn.create("/b")
                txn.check("/c", version=0)
            self.assertEqual(0, len(updates))
            self.assertFalse(txn.committed)
            with c.transaction() as txn:
                txn.create("/b")
                txn.check("/b", version=0)
            self.assertTrue(txn.committed)
            self.assertTrue(ev.wait(WAIT_TIME))
            self.assertEqual(1, len(updates))