示例#1
0
 def test_serverset_destroy(self):
     testutil.initialize_kazoo_client_manager(ZK_HOSTS)
     client = KazooClientManager().get_client()
     client.start()
     fd, tmp_file = tempfile.mkstemp()
     server_set = ServerSet(ServerSetWithFileTestCase.SERVER_SET_DESTROY_PATH,
                            ZK_HOSTS,
                            waiting_in_secs=0.01)
     server_set.join(ServerSetWithFileTestCase.PORT_1, use_ip=False)
     server_set.join(ServerSetWithFileTestCase.PORT_2, use_ip=False)
     # update the local file manually here, suppose there is a daemon
     with open(tmp_file, 'w') as f:
         f.write(ServerSetWithFileTestCase.END_POINT_1 +
                 "\n" +
                 ServerSetWithFileTestCase.END_POINT_2)
     # Give time to let server set join to do its magic.
     gevent.sleep(1)
     server_set._destroy(ServerSetWithFileTestCase.END_POINT_1)
     # update the local file manually here, suppose there is a daemon
     with open(tmp_file, 'w') as f:
         f.write(ServerSetWithFileTestCase.END_POINT_2)
     gevent.sleep(1)
     children = client.get_children(
         ServerSetWithFileTestCase.SERVER_SET_DESTROY_PATH)
     for child in children:
         self.assertFalse(child.endswith(ServerSetWithFileTestCase.END_POINT_1))
     self.FILE_WATCH._clear_all_watches()
     os.remove(tmp_file)
示例#2
0
 def test_random_host_selector_with_serverset(self):
     testutil.initialize_kazoo_client_manager(ZK_HOSTS)
     kazoo_client = KazooClientManager().get_client()
     kazoo_client.ensure_path(HostSelectorTestCase.SERVER_SET_PATH)
     host_provider = HostsProvider(HostSelectorTestCase.PORT_LIST,
                                   HostSelectorTestCase.SERVER_SET_PATH)
     self.assertTrue(host_provider.initialized)
     self.assertTrue(host_provider.hosts)
     # Since there is no live hosts in the server set, host provider should
     # still use the static host list.
     self.assertEqual(host_provider._current_host_tuple,
                      host_provider._static_host_tuple)
     random_host_selector = RandomHostSelector(
         host_provider, expire_time=0, retry_time=0,
         invalidation_threshold=1.0)
     self.assertTrue(random_host_selector.get_host() in
                     HostSelectorTestCase.PORT_LIST)
     server_set = ServerSet(HostSelectorTestCase.SERVER_SET_PATH, ZK_HOSTS)
     g = server_set.join(HostSelectorTestCase.PORT_LIST[0], use_ip=False)
     g.get()
     no_of_iterations = 100
     # After the first endpoint joins, random host selector should only
     # start to use hosts in the server set.
     returned_hosts = [random_host_selector.get_host()
                       for i in xrange(no_of_iterations)]
     self.assertEqual(len(set(returned_hosts)), 1)
     self.assertEqual(len(host_provider.hosts), 1)
     g = server_set.join(HostSelectorTestCase.PORT_LIST[1], use_ip=False)
     g.get()
     # After the second endpoint joins the server set, random host selector
     # should return both endpoints now.
     returned_hosts = [random_host_selector.get_host()
                       for i in xrange(no_of_iterations)]
     self.assertEqual(len(set(returned_hosts)), 2)
     self.assertEqual(len(host_provider.hosts), 2)
示例#3
0
 def test_serverset_destroy(self):
     testutil.initialize_kazoo_client_manager(ZK_HOSTS)
     client = KazooClientManager().get_client()
     server_set = ServerSet(ServerSetTestCase.SERVER_SET_DESTROY_PATH,
                            ZK_HOSTS,
                            waiting_in_secs=0.01)
     server_set.join(ServerSetTestCase.PORT_1, use_ip=False)
     server_set.join(ServerSetTestCase.PORT_2, use_ip=False)
     # Give time to let server set join to do its magic.
     gevent.sleep(1)
     server_set._destroy(ServerSetTestCase.END_POINT_1)
     gevent.sleep(1)
     children = client.get_children(
         ServerSetTestCase.SERVER_SET_DESTROY_PATH)
     for child in children:
         self.assertFalse(child.endswith(ServerSetTestCase.END_POINT_1))
示例#4
0
    def test_server_set(self):
        """Test various failure scenarios on server set implementation.

        1. When a new server joins the set, the watcher should be notified.
        2. When the underlying zk client disconnects and then recovers,
           the server set should be transparent to server set participants
           and watchers.
        3. When the underlying zk client messes up beyond recovery,
           the underlying client should be replaced, and this should be
           transparent to server set participants and watchers.

        """
        all_children = []
        watcher_triggered = Event()

        def server_set_watcher(children):
            while all_children:
                all_children.pop()
            for child in children:
                all_children.append(child)
            watcher_triggered.set()

        testutil.initialize_kazoo_client_manager(ZK_HOSTS)
        client = KazooClientManager().get_client()
        server_set = ServerSet(ServerSetTestCase.SERVER_SET_PATH,
                               ZK_HOSTS,
                               waiting_in_secs=0.01)
        server_set.join(ServerSetTestCase.PORT_1, use_ip=True).join()
        server_set.monitor(server_set_watcher).join()
        watcher_triggered.wait(1)
        # Now the server set should only contain end point 1
        self.assertEqual(all_children, [ServerSetTestCase.END_POINT_1])
        watcher_triggered.clear()
        server_set.join(ServerSetTestCase.PORT_2, use_ip=True).join()
        watcher_triggered.wait(1)
        all_children.sort()
        # Now the server set should contain both end point 1 and 2
        self.assertEqual(all_children, ServerSetTestCase.END_POINTS)
        # Test recoverable failure
        client.stop()
        watcher_triggered.clear()
        client.start()
        watcher_triggered.wait(1)
        # Server set should remain the same when the client recovers
        all_children.sort()
        self.assertEqual(all_children, ServerSetTestCase.END_POINTS)
        # Test client change
        client.stop()
        watcher_triggered.clear()
        # give the monit greenlet a chance to detect failures
        gevent.sleep(1)
        # Assert the client has been replaced with a new one
        self.assertFalse(KazooClientManager().get_client() is client)
        watcher_triggered.wait(1)
        # Server set should survive the underlying client being swapped out
        all_children.sort()
        self.assertEqual(all_children, ServerSetTestCase.END_POINTS)
示例#5
0
    def test_server_set(self):
        """Test various failure scenarios on server set implementation.

        1. When a new server joins the set, the watcher should be notified.
        2. When the underlying zk client disconnects and then recovers,
           the server set should be transparent to server set participants
           and watchers.
        3. When the underlying zk client messes up beyond recovery,
           the underlying client should be replaced, and this should be
           transparent to server set participants and watchers.

        """
        all_children = []
        watcher_triggered = Event()

        def server_set_watcher(children):
            while all_children:
                all_children.pop()
            for child in children:
                all_children.append(child)
            watcher_triggered.set()

        testutil.initialize_kazoo_client_manager(ZK_HOSTS)
        client = KazooClientManager().get_client()
        server_set = ServerSet(ServerSetTestCase.SERVER_SET_PATH,
                               ZK_HOSTS,
                               waiting_in_secs=0.01)
        server_set.join(ServerSetTestCase.PORT_1, use_ip=True).join()
        server_set.monitor(server_set_watcher).join()
        watcher_triggered.wait(1)
        # Now the server set should only contain end point 1
        self.assertEqual(all_children, [ServerSetTestCase.END_POINT_1])
        watcher_triggered.clear()
        server_set.join(ServerSetTestCase.PORT_2, use_ip=True).join()
        watcher_triggered.wait(1)
        all_children.sort()
        # Now the server set should contain both end point 1 and 2
        self.assertEqual(all_children, ServerSetTestCase.END_POINTS)
        # Test recoverable failure
        client.stop()
        watcher_triggered.clear()
        client.start()
        watcher_triggered.wait(1)
        # Server set should remain the same when the client recovers
        all_children.sort()
        self.assertEqual(all_children, ServerSetTestCase.END_POINTS)
        # Test client change
        client.stop()
        watcher_triggered.clear()
        # give the monit greenlet a chance to detect failures
        gevent.sleep(1)
        # Assert the client has been replaced with a new one
        self.assertFalse(KazooClientManager().get_client() is client)
        watcher_triggered.wait(1)
        # Server set should survive the underlying client being swapped out
        all_children.sort()
        self.assertEqual(all_children, ServerSetTestCase.END_POINTS)
示例#6
0
 def test_serverset_destroy(self):
     testutil.initialize_kazoo_client_manager(ZK_HOSTS)
     client = KazooClientManager().get_client()
     client.start()
     fd, tmp_file = tempfile.mkstemp()
     server_set = ServerSet(
         ServerSetWithFileTestCase.SERVER_SET_DESTROY_PATH,
         ZK_HOSTS,
         waiting_in_secs=0.01)
     server_set.join(ServerSetWithFileTestCase.PORT_1, use_ip=False)
     server_set.join(ServerSetWithFileTestCase.PORT_2, use_ip=False)
     # update the local file manually here, suppose there is a daemon
     with open(tmp_file, 'w') as f:
         f.write(ServerSetWithFileTestCase.END_POINT_1 + "\n" +
                 ServerSetWithFileTestCase.END_POINT_2)
     # Give time to let server set join to do its magic.
     gevent.sleep(1)
     server_set._destroy(ServerSetWithFileTestCase.END_POINT_1)
     # update the local file manually here, suppose there is a daemon
     with open(tmp_file, 'w') as f:
         f.write(ServerSetWithFileTestCase.END_POINT_2)
     gevent.sleep(1)
     children = client.get_children(
         ServerSetWithFileTestCase.SERVER_SET_DESTROY_PATH)
     for child in children:
         self.assertFalse(
             child.endswith(ServerSetWithFileTestCase.END_POINT_1))
     self.FILE_WATCH._clear_all_watches()
     os.remove(tmp_file)
示例#7
0
 def test_random_host_selector_with_serverset(self):
     testutil.initialize_kazoo_client_manager(ZK_HOSTS)
     kazoo_client = KazooClientManager().get_client()
     kazoo_client.ensure_path(HostSelectorTestCase.SERVER_SET_PATH)
     host_provider = HostsProvider(HostSelectorTestCase.PORT_LIST,
                                   HostSelectorTestCase.SERVER_SET_PATH)
     self.assertTrue(host_provider.initialized)
     self.assertTrue(host_provider.hosts)
     # Since there is no live hosts in the server set, host provider should
     # still use the static host list.
     self.assertEqual(host_provider._current_host_tuple,
                      host_provider._static_host_tuple)
     random_host_selector = RandomHostSelector(host_provider,
                                               expire_time=0,
                                               retry_time=0,
                                               invalidation_threshold=1.0)
     self.assertTrue(
         random_host_selector.get_host() in HostSelectorTestCase.PORT_LIST)
     server_set = ServerSet(HostSelectorTestCase.SERVER_SET_PATH, ZK_HOSTS)
     g = server_set.join(HostSelectorTestCase.PORT_LIST[0], use_ip=False)
     g.get()
     no_of_iterations = 100
     # After the first endpoint joins, random host selector should only
     # start to use hosts in the server set.
     returned_hosts = [
         random_host_selector.get_host() for i in xrange(no_of_iterations)
     ]
     self.assertEqual(len(set(returned_hosts)), 1)
     self.assertEqual(len(host_provider.hosts), 1)
     g = server_set.join(HostSelectorTestCase.PORT_LIST[1], use_ip=False)
     g.get()
     # After the second endpoint joins the server set, random host selector
     # should return both endpoints now.
     returned_hosts = [
         random_host_selector.get_host() for i in xrange(no_of_iterations)
     ]
     self.assertEqual(len(set(returned_hosts)), 2)
     self.assertEqual(len(host_provider.hosts), 2)
示例#8
0
def main():
    global args
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("-p",
                        "--port",
                        dest="port",
                        metavar="PORT",
                        required=True,
                        help="The port of the service runnning on")
    parser.add_argument("-s",
                        "--service-name",
                        dest="service_name",
                        metavar="SERVICE_NAME",
                        required=True,
                        help="The name of the service you want to register to")
    parser.add_argument(
        "-e",
        "--environment",
        dest="service_environment",
        metavar="SERVICE_ENVIRONMENT",
        required=True,
        help='The environment service is running on, for example prod, staging'
    )
    parser.add_argument(
        "-z",
        "--zk-hosts-file-path",
        dest="zk_hosts_file",
        metavar="ZKHOSTS",
        required=True,
        help="The path of file which have a list of Zookeeper endpoints "
        "(host:port) which keeps the metaconfig as well as "
        "the config/serversets")
    args = parser.parse_args()

    service_name = args.service_name
    service_environment = args.service_environment
    service_port = int(args.port)

    serverset_full_path = '/discovery/%s/%s' % (service_name,
                                                service_environment)

    zk_hosts = zk_util.parse_zk_hosts_file(args.zk_hosts_file)

    validate_port(service_port)

    ServerSet(serverset_full_path, zk_hosts).join(service_port,
                                                  use_ip=True,
                                                  keep_retrying=True)
    Event().wait()
示例#9
0
def _place_watch(config, zk_path, command,
                 watch_type, max_wait_in_secs=0, alert_disabled=False):
    """
    Place the watch for Config or Serverset giving the information extracted
    from metaconfig.
    """

    # If the ZK path is already added, skip the following steps
    # in order to resolve conflicts.
    if zk_path in _PATH_TO_COMMAND:
        log.warn("Path %s has already been added to PATH_TO_COMMAND" % zk_path)
        return False

    if not _zk_path_exists(ZK_HOSTS, zk_path):
        log.error("zk_path %s does not exist in zk_hosts %s, no watch is set."
                  % (zk_path, ZK_HOSTS))
        # Save the configs that contain the nonexistent zk path for retry
        _CONFIGS_WITH_NONEXISTENT_PATH.append(config)
        return False

    log.info("Creating Zookeeper data watcher for path %s of zk_hosts %s"
             % (zk_path, ZK_HOSTS))

    # Get the local file modification time if the file exists, else set to 0.
    _get_and_set_local_file_modification_time(zk_path, command, watch_type)

    if watch_type is not None and watch_type.lower() == 'serverset':
        watcher = ServerSet(zk_path, ZK_HOSTS)
    else:
        watcher = DataWatcher(zk_path, ZK_HOSTS)
    log.info(
        "Associating command '%s' with watcher of path %s"
        % (command, zk_path)
    )
    _PATH_TO_COMMAND[zk_path] = command
    _PATH_TO_ALERT_DISABLED[zk_path] = alert_disabled
    callback_func = functools.partial(
        _run_command, zk_path, command, max_wait_in_secs, watch_type)
    _PATH_TO_WATCHER[zk_path] = \
        {"watcher": watcher, "func": callback_func, "watch_type": watch_type}

    if watch_type == 'serverset':
        watcher.monitor(callback_func)
    else:
        watcher.watch(callback_func)

    return True
示例#10
0
 def test_serverset_destroy(self):
     testutil.initialize_kazoo_client_manager(ZK_HOSTS)
     client = KazooClientManager().get_client()
     server_set = ServerSet(ServerSetTestCase.SERVER_SET_DESTROY_PATH,
                            ZK_HOSTS,
                            waiting_in_secs=0.01)
     server_set.join(ServerSetTestCase.PORT_1, use_ip=False)
     server_set.join(ServerSetTestCase.PORT_2, use_ip=False)
     # Give time to let server set join to do its magic.
     gevent.sleep(1)
     server_set._destroy(ServerSetTestCase.END_POINT_1)
     gevent.sleep(1)
     children = client.get_children(
         ServerSetTestCase.SERVER_SET_DESTROY_PATH)
     for child in children:
         self.assertFalse(child.endswith(ServerSetTestCase.END_POINT_1))
示例#11
0
def _place_watch(config, zk_path, command,
                 watch_type, max_wait_in_secs=0, alert_disabled=False):
    """
    Place the watch for Config or Serverset giving the information extracted
    from metaconfig.
    """

    # If the ZK path is already added, skip the following steps
    # in order to resolve conflicts.
    if zk_path in _PATH_TO_COMMAND:
        log.warn("Path %s has already been added to PATH_TO_COMMAND" % zk_path)
        return False

    if not _zk_path_exists(ZK_HOSTS, zk_path):
        log.error("zk_path %s does not exist in zk_hosts %s, no watch is set."
                  % (zk_path, ZK_HOSTS))
        # Save the configs that contain the nonexistent zk path for retry
        _CONFIGS_WITH_NONEXISTENT_PATH.append(config)
        return False

    log.info("Creating Zookeeper data watcher for path %s of zk_hosts %s"
             % (zk_path, ZK_HOSTS))

    # Get the local file modification time if the file exists, else set to 0.
    _get_and_set_local_file_modification_time(zk_path, command, watch_type)

    if watch_type is not None and watch_type.lower() == 'serverset':
        watcher = ServerSet(zk_path, ZK_HOSTS)
    else:
        watcher = DataWatcher(zk_path, ZK_HOSTS)
    log.info(
        "Associating command '%s' with watcher of path %s"
        % (command, zk_path)
    )
    _PATH_TO_COMMAND[zk_path] = command
    _PATH_TO_ALERT_DISABLED[zk_path] = alert_disabled

    if watch_type == 'serverset':
        watcher.monitor(functools.partial(
            _run_command, zk_path, command, max_wait_in_secs, watch_type))
    else:
        watcher.watch(functools.partial(
            _run_command, zk_path, command, max_wait_in_secs, watch_type))

    return True
示例#12
0
    def test_server_set(self):
        """Test various failure scenarios on server set implementation.

        1. When a new server joins the set, the watcher should be notified.
           In practice there is a daemon monitoring the server set change in
           zk and update the local file.
        2. When the underlying zk client disconnects and then recovers,
           the server set should be transparent to server set participants
           and watchers.
        3. When the underlying zk client messes up beyond recovery,
           it should be transparent to server set participants and watchers.

        Although when a local file is being watched, now all the code paths
        about the above behaviors got affected, we still want to test all the
        scenarios to make sure nothing breaks when a file is used.

        NOTE: to simulate the behavior in practice, when a server joins or
        leaves, we assume that there is a daemon to make the corresponding
        change to the local file.
        """
        fd, tmp_file = tempfile.mkstemp()
        all_children = []
        watcher_triggered = Event()

        def server_set_watcher(children):
            while all_children:
                all_children.pop()
            for child in children:
                all_children.append(child)
            watcher_triggered.set()

        testutil.initialize_kazoo_client_manager(ZK_HOSTS)
        client = KazooClientManager().get_client()
        server_set = ServerSet(ServerSetWithFileTestCase.SERVER_SET_PATH,
                               ZK_HOSTS,
                               waiting_in_secs=0.01,
                               file_path=tmp_file)
        server_set.join(ServerSetWithFileTestCase.PORT_1, use_ip=False).join()
        # update the local file manually here, suppose there is a daemon
        with open(tmp_file, 'w') as f:
            f.write(ServerSetWithFileTestCase.END_POINT_1)
        gevent.sleep(1)
        server_set.monitor(server_set_watcher).join()
        watcher_triggered.wait(1)
        # Now the server set should only contain end point 1
        self.assertEqual(all_children, [ServerSetWithFileTestCase.END_POINT_1])
        watcher_triggered.clear()
        server_set.join(ServerSetWithFileTestCase.PORT_2, use_ip=False).join()
        # update the local file manually here, suppose there is a daemon
        with open(tmp_file, 'w') as f:
            f.write(ServerSetWithFileTestCase.END_POINT_1 +
                    "\n" +
                    ServerSetWithFileTestCase.END_POINT_2)
        gevent.sleep(1)
        watcher_triggered.wait(1)
        all_children.sort()
        # Now the server set should contain both end point 1 and 2
        self.assertEqual(all_children, ServerSetWithFileTestCase.END_POINTS)
        # Test recoverable failure
        client.stop()
        watcher_triggered.clear()
        client.start()
        watcher_triggered.wait(1)
        # Server set should remain the same when the client recovers
        all_children.sort()
        self.assertEqual(all_children, ServerSetWithFileTestCase.END_POINTS)
        # Test client change
        client.stop()
        watcher_triggered.clear()
        # give the monit greenlet a chance to detect failures
        gevent.sleep(1)
        watcher_triggered.wait(1)
        # Server set should survive the underlying client being swapped out
        all_children.sort()
        self.assertEqual(all_children, ServerSetWithFileTestCase.END_POINTS)

        self.FILE_WATCH._clear_all_watches()
        os.remove(tmp_file)
示例#13
0
    def test_server_set(self):
        """Test various failure scenarios on server set implementation.

        1. When a new server joins the set, the watcher should be notified.
           In practice there is a daemon monitoring the server set change in
           zk and update the local file.
        2. When the underlying zk client disconnects and then recovers,
           the server set should be transparent to server set participants
           and watchers.
        3. When the underlying zk client messes up beyond recovery,
           it should be transparent to server set participants and watchers.

        Although when a local file is being watched, now all the code paths
        about the above behaviors got affected, we still want to test all the
        scenarios to make sure nothing breaks when a file is used.

        NOTE: to simulate the behavior in practice, when a server joins or
        leaves, we assume that there is a daemon to make the corresponding
        change to the local file.
        """
        fd, tmp_file = tempfile.mkstemp()
        all_children = []
        watcher_triggered = Event()

        def server_set_watcher(children):
            while all_children:
                all_children.pop()
            for child in children:
                all_children.append(child)
            watcher_triggered.set()

        testutil.initialize_kazoo_client_manager(ZK_HOSTS)
        client = KazooClientManager().get_client()
        server_set = ServerSet(ServerSetWithFileTestCase.SERVER_SET_PATH,
                               ZK_HOSTS,
                               waiting_in_secs=0.01,
                               file_path=tmp_file)
        server_set.join(ServerSetWithFileTestCase.PORT_1, use_ip=False).join()
        # update the local file manually here, suppose there is a daemon
        with open(tmp_file, 'w') as f:
            f.write(ServerSetWithFileTestCase.END_POINT_1)
        gevent.sleep(1)
        server_set.monitor(server_set_watcher).join()
        watcher_triggered.wait(1)
        # Now the server set should only contain end point 1
        self.assertEqual(all_children, [ServerSetWithFileTestCase.END_POINT_1])
        watcher_triggered.clear()
        server_set.join(ServerSetWithFileTestCase.PORT_2, use_ip=False).join()
        # update the local file manually here, suppose there is a daemon
        with open(tmp_file, 'w') as f:
            f.write(ServerSetWithFileTestCase.END_POINT_1 + "\n" +
                    ServerSetWithFileTestCase.END_POINT_2)
        gevent.sleep(1)
        watcher_triggered.wait(1)
        all_children.sort()
        # Now the server set should contain both end point 1 and 2
        self.assertEqual(all_children, ServerSetWithFileTestCase.END_POINTS)
        # Test recoverable failure
        client.stop()
        watcher_triggered.clear()
        client.start()
        watcher_triggered.wait(1)
        # Server set should remain the same when the client recovers
        all_children.sort()
        self.assertEqual(all_children, ServerSetWithFileTestCase.END_POINTS)
        # Test client change
        client.stop()
        watcher_triggered.clear()
        # give the monit greenlet a chance to detect failures
        gevent.sleep(1)
        watcher_triggered.wait(1)
        # Server set should survive the underlying client being swapped out
        all_children.sort()
        self.assertEqual(all_children, ServerSetWithFileTestCase.END_POINTS)

        self.FILE_WATCH._clear_all_watches()
        os.remove(tmp_file)
示例#14
0
class ServerSetTestCase(unittest.TestCase):
    """Test server set."""

    SERVER_SET_PATH = "/test_server_set"
    SERVER_SET_DESTROY_PATH = "/test_server_set_destroy"
    PORT_1 = 8080
    PORT_2 = 8081
    END_POINT_1 = ServerSet._create_endpoint(PORT_1, True)
    END_POINT_2 = ServerSet._create_endpoint(PORT_2, True)
    END_POINTS = [END_POINT_1, END_POINT_2]

    @mock.patch("kazoo.client.KazooClient.__new__",
                new=mock.Mock(side_effect=testutil.get_mock_kazoo_client))
    def test_server_set(self):
        """Test various failure scenarios on server set implementation.

        1. When a new server joins the set, the watcher should be notified.
        2. When the underlying zk client disconnects and then recovers,
           the server set should be transparent to server set participants
           and watchers.
        3. When the underlying zk client messes up beyond recovery,
           the underlying client should be replaced, and this should be
           transparent to server set participants and watchers.

        """
        all_children = []
        watcher_triggered = Event()

        def server_set_watcher(children):
            while all_children:
                all_children.pop()
            for child in children:
                all_children.append(child)
            watcher_triggered.set()

        testutil.initialize_kazoo_client_manager(ZK_HOSTS)
        client = KazooClientManager().get_client()
        server_set = ServerSet(ServerSetTestCase.SERVER_SET_PATH,
                               ZK_HOSTS,
                               waiting_in_secs=0.01)
        server_set.join(ServerSetTestCase.PORT_1, use_ip=True).join()
        server_set.monitor(server_set_watcher).join()
        watcher_triggered.wait(1)
        # Now the server set should only contain end point 1
        self.assertEqual(all_children, [ServerSetTestCase.END_POINT_1])
        watcher_triggered.clear()
        server_set.join(ServerSetTestCase.PORT_2, use_ip=True).join()
        watcher_triggered.wait(1)
        all_children.sort()
        # Now the server set should contain both end point 1 and 2
        self.assertEqual(all_children, ServerSetTestCase.END_POINTS)
        # Test recoverable failure
        client.stop()
        watcher_triggered.clear()
        client.start()
        watcher_triggered.wait(1)
        # Server set should remain the same when the client recovers
        all_children.sort()
        self.assertEqual(all_children, ServerSetTestCase.END_POINTS)
        # Test client change
        client.stop()
        watcher_triggered.clear()
        # give the monit greenlet a chance to detect failures
        gevent.sleep(1)
        # Assert the client has been replaced with a new one
        self.assertFalse(KazooClientManager().get_client() is client)
        watcher_triggered.wait(1)
        # Server set should survive the underlying client being swapped out
        all_children.sort()
        self.assertEqual(all_children, ServerSetTestCase.END_POINTS)

    @attr('destroy_serverset')
    @mock.patch("kazoo.client.KazooClient.__new__",
                new=mock.Mock(side_effect=testutil.get_mock_kazoo_client))
    def test_serverset_destroy(self):
        testutil.initialize_kazoo_client_manager(ZK_HOSTS)
        client = KazooClientManager().get_client()
        server_set = ServerSet(ServerSetTestCase.SERVER_SET_DESTROY_PATH,
                               ZK_HOSTS,
                               waiting_in_secs=0.01)
        server_set.join(ServerSetTestCase.PORT_1, use_ip=False)
        server_set.join(ServerSetTestCase.PORT_2, use_ip=False)
        # Give time to let server set join to do its magic.
        gevent.sleep(1)
        server_set._destroy(ServerSetTestCase.END_POINT_1)
        gevent.sleep(1)
        children = client.get_children(
            ServerSetTestCase.SERVER_SET_DESTROY_PATH)
        for child in children:
            self.assertFalse(child.endswith(ServerSetTestCase.END_POINT_1))