Repository: kudu Updated Branches: refs/heads/master c7dab48eb -> 202e91249
KUDU-1304 - [python] Enable listing of tablet servers Kudu's python client currently doesn't expose the ListTabletServers method. To date, this has presented issues with unit tests executing before the tservers have started. This patch exposes the method and integrates it into the unit tests so that race conditions no longer occur. This patch also includes an additional test to confirm the integrity of the data returned from the method. Change-Id: I51794168750b358d8c1b371ac2bd08b5c8f15395 Reviewed-on: http://gerrit.cloudera.org:8080/4328 Reviewed-by: Todd Lipcon <[email protected]> Tested-by: Kudu Jenkins Project: http://git-wip-us.apache.org/repos/asf/kudu/repo Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/202e9124 Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/202e9124 Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/202e9124 Branch: refs/heads/master Commit: 202e9124929b2a0d9b33d62af1c773e69772a9e8 Parents: c7dab48 Author: Jordan Birdsell <[email protected]> Authored: Wed Sep 7 20:33:57 2016 -0400 Committer: Todd Lipcon <[email protected]> Committed: Fri Sep 9 02:14:58 2016 +0000 ---------------------------------------------------------------------- python/kudu/client.pyx | 47 +++++++++++++++++++++++++++++++++++ python/kudu/libkudu_client.pxd | 8 ++++++ python/kudu/tests/common.py | 11 ++++++++ python/kudu/tests/test_client.py | 11 ++++++++ 4 files changed, 77 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kudu/blob/202e9124/python/kudu/client.pyx ---------------------------------------------------------------------- diff --git a/python/kudu/client.pyx b/python/kudu/client.pyx index 8aefc1c..79a0c52 100644 --- a/python/kudu/client.pyx +++ b/python/kudu/client.pyx @@ -352,6 +352,27 @@ cdef class Client: result.append(frombytes(tables[i])) return result + def list_tablet_servers(self): + """ + Retrieve a list of tablet servers currently running in the Kudu cluster + + Returns + ------- + tservers : list[TabletServer] + List of TabletServer objects + """ + cdef: + vector[KuduTabletServer*] tservers + size_t i + + check_status(self.cp.ListTabletServers(&tservers)) + + result = [] + for i in range(tservers.size()): + ts = TabletServer() + result.append(ts._init(tservers[i])) + return result + def new_session(self, flush_mode='manual', timeout_ms=5000): """ Create a new KuduSession for applying write operations. @@ -477,6 +498,32 @@ cdef class StringVal(RawValue): del self.val #---------------------------------------------------------------------- +cdef class TabletServer: + """ + Represents a Kudu tablet server, containing the uuid, hostname and port. + Create a list of TabletServers by using the kudu.Client.list_tablet_servers + method after connecting to a cluster + """ + + cdef: + KuduTabletServer* _tserver + + cdef _init(self, KuduTabletServer* tserver): + self._tserver = tserver + return self + + def __dealloc__(self): + if self._tserver != NULL: + del self._tserver + + def uuid(self): + return frombytes(self._tserver.uuid()) + + def hostname(self): + return frombytes(self._tserver.hostname()) + + def port(self): + return self._tserver.port() cdef class Table: http://git-wip-us.apache.org/repos/asf/kudu/blob/202e9124/python/kudu/libkudu_client.pxd ---------------------------------------------------------------------- diff --git a/python/kudu/libkudu_client.pxd b/python/kudu/libkudu_client.pxd index ecc70b4..a10f601 100644 --- a/python/kudu/libkudu_client.pxd +++ b/python/kudu/libkudu_client.pxd @@ -463,6 +463,8 @@ cdef extern from "kudu/client/client.h" namespace "kudu::client" nogil: Status ListTables(vector[string]* tables) Status ListTables(vector[string]* tables, const string& filter) + Status ListTabletServers(vector[KuduTabletServer*]* tablet_servers) + Status TableExists(const string& table_name, c_bool* exists) KuduTableAlterer* NewTableAlterer() @@ -483,6 +485,12 @@ cdef extern from "kudu/client/client.h" namespace "kudu::client" nogil: Status Build(shared_ptr[KuduClient]* client) + cdef cppclass KuduTabletServer: + KuduTabletServer() + string& uuid() + string& hostname() + uint16_t port() + cdef cppclass KuduTableCreator: KuduTableCreator& table_name(string& name) KuduTableCreator& schema(KuduSchema* schema) http://git-wip-us.apache.org/repos/asf/kudu/blob/202e9124/python/kudu/tests/common.py ---------------------------------------------------------------------- diff --git a/python/kudu/tests/common.py b/python/kudu/tests/common.py index fee183a..75a6ca6 100644 --- a/python/kudu/tests/common.py +++ b/python/kudu/tests/common.py @@ -38,6 +38,7 @@ class KuduTestBase(object): BASE_PORT = 37000 NUM_TABLET_SERVERS = 3 + TSERVER_START_TIMEOUT_SECS = 10 @classmethod def start_cluster(cls): @@ -135,6 +136,16 @@ class KuduTestBase(object): cls.client = kudu.connect(cls.master_host, cls.master_port) + # Wait for all tablet servers to start with the configured timeout + timeout = time.time() + cls.TSERVER_START_TIMEOUT_SECS + while len(cls.client.list_tablet_servers()) < cls.NUM_TABLET_SERVERS: + if time.time() > timeout: + raise TimeoutError( + "Tablet servers took too long to start. Timeout set to {}" + .format(cls.TSERVER_START_TIMEOUT_SECS)) + # Sleep 50 milliseconds to avoid tight-looping rpc + time.sleep(0.05) + cls.schema = cls.example_schema() cls.partitioning = cls.example_partitioning() http://git-wip-us.apache.org/repos/asf/kudu/blob/202e9124/python/kudu/tests/test_client.py ---------------------------------------------------------------------- diff --git a/python/kudu/tests/test_client.py b/python/kudu/tests/test_client.py index dba95b3..8396aea 100644 --- a/python/kudu/tests/test_client.py +++ b/python/kudu/tests/test_client.py @@ -221,6 +221,17 @@ class TestClient(KuduTestBase, unittest.TestCase): def test_capture_kudu_error(self): pass + def test_list_tablet_server(self): + # Not confirming the number of tablet servers in this test because + # that is confirmed in the beginning of testing. This test confirms + # that all of the KuduTabletServer methods returned results and that + # a result is returned from the list_tablet_servers method. + tservers = self.client.list_tablet_servers() + self.assertTrue(tservers) + for tserver in tservers: + assert tserver.uuid() is not None + assert tserver.hostname() is not None + assert tserver.port() is not None class TestMonoDelta(unittest.TestCase):
