コード例 #1
0
    def _connect(self):
        db_key = "%s.%s.%s" % (self.keyspace, self.shard, self.db_type)
        db_params_list = get_vt_connection_params_list(
            self.topo_client, self.keyspace, self.shard, self.db_type,
            self.timeout, self.encrypted, self.user, self.password)
        if not db_params_list:
            # no valid end-points were found, re-read the keyspace
            self.resolve_topology()
            raise dbexceptions.OperationalError(
                "empty db params list - no db instance available for key %s" %
                db_key)
        db_exception = None
        host_addr = None
        # no retries here, since there is a higher level retry with reconnect.
        for params in db_params_list:
            try:
                db_params = params.copy()
                host_addr = db_params['addr']
                self.conn = tablet.TabletConnection(**db_params)
                self.conn.dial()
                self.conn_db_params = db_params
                return self.conn
            except Exception as e:
                db_exception = e
                logging.warning('db connection failed: %s %s, %s', db_key,
                                host_addr, e)
                # vttablet threw an Operational Error on connect, re-read the keyspace
                if isinstance(e, dbexceptions.OperationalError):
                    self.resolve_topology()

        raise dbexceptions.OperationalError('unable to create vt connection',
                                            db_key, host_addr, db_exception)
コード例 #2
0
ファイル: tablet.py プロジェクト: ptomasroos/vitess
 def conn(self, user=None, password=None):
     conn = tablet.TabletConnection('localhost:%d' % self.port,
                                    self.tablet_type,
                                    self.keyspace,
                                    self.shard,
                                    30,
                                    caller_id='dev')
     conn.dial()
     return conn
コード例 #3
0
ファイル: tablet_test.py プロジェクト: zhzhy917/vitess
class TestRPCCallAndExtract(unittest.TestCase):
  """Tests rpc_call_and_extract_error is tolerant to various responses."""

  tablet_conn = tablet.TabletConnection('addr', 'type', 'keyspace', 'shard', 30)

  def test_reply_is_none(self):
    with mock.patch.object(self.tablet_conn, 'client', autospec=True) as mock_client:
      mock_client.call.return_value = gorpc.GoRpcResponse()
      self.tablet_conn.rpc_call_and_extract_error('method', 'req')

  def test_reply_is_empty_string(self):
    with mock.patch.object(self.tablet_conn, 'client', autospec=True) as mock_client:
      response = gorpc.GoRpcResponse()
      response.reply = ''
      mock_client.call.return_value = response
      self.tablet_conn.rpc_call_and_extract_error('method', 'req')

  def test_reply_is_string(self):
    with mock.patch.object(self.tablet_conn, 'client', autospec=True) as mock_client:
      response = gorpc.GoRpcResponse()
      response.reply = 'foo'
      mock_client.call.return_value = response
      self.tablet_conn.rpc_call_and_extract_error('method', 'req')

  def test_reply_is_dict(self):
    with mock.patch.object(self.tablet_conn, 'client', autospec=True) as mock_client:
      response = gorpc.GoRpcResponse()
      response.reply = {'foo': 'bar'}
      mock_client.call.return_value = response
      self.tablet_conn.rpc_call_and_extract_error('method', 'req')

  def test_reply_has_non_dict_err(self):
    with mock.patch.object(self.tablet_conn, 'client', autospec=True) as mock_client:
      response = gorpc.GoRpcResponse()
      response.reply = {'Err': 'foo'}
      mock_client.call.return_value = response
      with self.assertRaisesRegexp(gorpc.AppError, 'Missing error message'):
        self.tablet_conn.rpc_call_and_extract_error('method', 'req')

  def test_reply_has_missing_err_message(self):
    with mock.patch.object(self.tablet_conn, 'client', autospec=True) as mock_client:
      response = gorpc.GoRpcResponse()
      response.reply = {'Err': {'foo': 'bar'}}
      mock_client.call.return_value = response
      with self.assertRaisesRegexp(gorpc.AppError, 'Missing error message'):
        self.tablet_conn.rpc_call_and_extract_error('method', 'req')

  def test_reply_has_err_message(self):
    with mock.patch.object(self.tablet_conn, 'client', autospec=True) as mock_client:
      response = gorpc.GoRpcResponse()
      response.reply = {'Err': {'Message': 'bar'}}
      mock_client.call.return_value = response
      with self.assertRaisesRegexp(gorpc.AppError, "'bar', 'method'"):
        self.tablet_conn.rpc_call_and_extract_error('method', 'req')
コード例 #4
0
    def test_sharding(self):

        shard_0_master.init_tablet('master', 'test_keyspace', '-80')
        shard_0_replica.init_tablet('replica', 'test_keyspace', '-80')
        shard_1_master.init_tablet('master', 'test_keyspace', '80-')
        shard_1_replica.init_tablet('replica', 'test_keyspace', '80-')

        utils.run_vtctl(
            'RebuildShardGraph /zk/global/vt/keyspaces/test_keyspace/shards/*',
            auto_log=True)

        utils.run_vtctl('RebuildKeyspaceGraph /zk/global/vt/keyspaces/*',
                        auto_log=True)

        # run checks now before we start the tablets
        utils.validate_topology()

        # create databases
        shard_0_master.create_db('vt_test_keyspace')
        shard_0_replica.create_db('vt_test_keyspace')
        shard_1_master.create_db('vt_test_keyspace')
        shard_1_replica.create_db('vt_test_keyspace')

        # start the tablets
        shard_0_master.start_vttablet()
        shard_0_replica.start_vttablet()
        shard_1_master.start_vttablet()
        shard_1_replica.start_vttablet()

        # apply the schema on the first shard through vtctl, so all tablets
        # are the same (replication is not enabled yet, so allow_replication=false
        # is just there to be tested)
        utils.run_vtctl([
            'ApplySchema', '-stop-replication',
            '-sql=' + create_vt_select_test.replace("\n", ""),
            shard_0_master.tablet_alias
        ])
        utils.run_vtctl([
            'ApplySchema', '-stop-replication',
            '-sql=' + create_vt_select_test.replace("\n", ""),
            shard_0_replica.tablet_alias
        ])

        # start zkocc, we'll use it later
        zkocc_server = utils.zkocc_start()

        for t in [
                shard_0_master, shard_0_replica, shard_1_master,
                shard_1_replica
        ]:
            t.reset_replication()
        utils.run_vtctl('ReparentShard -force test_keyspace/-80 ' +
                        shard_0_master.tablet_alias,
                        auto_log=True)
        utils.run_vtctl('ReparentShard -force test_keyspace/80- ' +
                        shard_1_master.tablet_alias,
                        auto_log=True)

        # apply the schema on the second shard using a simple schema upgrade
        utils.run_vtctl([
            'ApplySchemaShard', '-simple',
            '-sql=' + create_vt_select_test_reverse.replace("\n", ""),
            'test_keyspace/80-'
        ])

        # insert some values directly (db is RO after minority reparent)
        # FIXME(alainjobart) these values don't match the shard map
        utils.run_vtctl('SetReadWrite ' + shard_0_master.tablet_alias)
        utils.run_vtctl('SetReadWrite ' + shard_1_master.tablet_alias)
        shard_0_master.mquery(
            'vt_test_keyspace',
            "insert into vt_select_test (id, msg) values (1, 'test 1')",
            write=True)
        shard_1_master.mquery(
            'vt_test_keyspace',
            "insert into vt_select_test (id, msg) values (10, 'test 10')",
            write=True)

        utils.validate_topology(ping_tablets=True)

        utils.pause("Before the sql scatter query")

        # note the order of the rows is not guaranteed, as the go routines
        # doing the work can go out of order
        self._check_rows(["Index\tid\tmsg", "1\ttest 1", "10\ttest 10"])

        # write a value, re-read them all
        utils.vtclient2(
            3803,
            "/test_nj/test_keyspace/master",
            "insert into vt_select_test (id, msg) values (:keyspace_id, 'test 2')",
            bindvars='{"keyspace_id": 2}',
            driver="vtdb",
            verbose=True)
        self._check_rows(
            ["Index\tid\tmsg", "1\ttest 1", "2\ttest 2", "10\ttest 10"])

        # make sure the '2' value was written on first shard
        rows = shard_0_master.mquery(
            'vt_test_keyspace',
            "select id, msg from vt_select_test order by id")
        self.assertEqual(rows, (
            (1, 'test 1'),
            (2, 'test 2'),
        ), 'wrong mysql_query output: %s' % str(rows))

        utils.pause("After db writes")

        # now use zkocc or streaming or both for the same query
        self._check_rows(
            ["Index\tid\tmsg", "1\ttest 1", "2\ttest 2", "10\ttest 10"],
            driver="vtdb-zkocc")
        self._check_rows(
            ["Index\tid\tmsg", "1\ttest 1", "2\ttest 2", "10\ttest 10"],
            driver="vtdb-streaming")
        self._check_rows(
            ["Index\tid\tmsg", "1\ttest 1", "2\ttest 2", "10\ttest 10"],
            driver="vtdb-zkocc-streaming")

        # make sure the schema checking works
        self._check_rows_schema_diff("vtdb-zkocc")
        self._check_rows_schema_diff("vtdb")

        # throw in some schema validation step
        # we created the schema differently, so it should show
        utils.run_vtctl('ValidateSchemaShard test_keyspace/-80')
        utils.run_vtctl('ValidateSchemaShard test_keyspace/80-')
        out, err = utils.run_vtctl('ValidateSchemaKeyspace test_keyspace',
                                   trap_output=True,
                                   raise_on_error=False)
        if "test_nj-0000062344 and test_nj-0000062346 disagree on schema for table vt_select_test:\nCREATE TABLE" not in err or \
           "test_nj-0000062344 and test_nj-0000062347 disagree on schema for table vt_select_test:\nCREATE TABLE" not in err:
            self.fail('wrong ValidateSchemaKeyspace output: ' + err)

        # validate versions
        utils.run_vtctl('ValidateVersionShard test_keyspace/-80',
                        auto_log=True)
        utils.run_vtctl('ValidateVersionKeyspace test_keyspace', auto_log=True)

        # show and validate permissions
        utils.run_vtctl('GetPermissions test_nj-0000062344', auto_log=True)
        utils.run_vtctl('ValidatePermissionsShard test_keyspace/-80',
                        auto_log=True)
        utils.run_vtctl('ValidatePermissionsKeyspace test_keyspace',
                        auto_log=True)

        # and create zkns on this complex keyspace, make sure a few files are created
        utils.run_vtctl('ExportZknsForKeyspace test_keyspace')
        out, err = utils.run(utils.vtroot +
                             '/bin/zk ls -R /zk/test_nj/zk?s/vt/test_keysp*',
                             trap_output=True)
        lines = out.splitlines()
        for base in ['-80', '80-']:
            for db_type in ['master', 'replica']:
                for sub_path in ['', '.vdns', '/0', '/_vtocc.vdns']:
                    expected = '/zk/test_nj/zkns/vt/test_keyspace/' + base + '/' + db_type + sub_path
                    if expected not in lines:
                        self.fail('missing zkns part:\n%s\nin:%s' %
                                  (expected, out))

        # now try to connect using the python client and shard-aware connection
        # to both shards
        # first get the topology and check it
        zkocc_client = zkocc.ZkOccConnection(
            "localhost:%u" % utils.zkocc_port_base, "test_nj", 30.0)
        topology.read_keyspaces(zkocc_client)

        shard_0_master_addrs = topology.get_host_port_by_name(
            zkocc_client, "test_keyspace.-80.master:_vtocc")
        if len(shard_0_master_addrs) != 1:
            self.fail(
                'topology.get_host_port_by_name failed for "test_keyspace.-80.master:_vtocc", got: %s'
                % " ".join([
                    "%s:%u(%s)" % (h, p, str(e))
                    for (h, p, e) in shard_0_master_addrs
                ]))
        logging.debug(
            "shard 0 master addrs: %s", " ".join([
                "%s:%u(%s)" % (h, p, str(e))
                for (h, p, e) in shard_0_master_addrs
            ]))

        # connect to shard -80
        conn = tablet3.TabletConnection(
            "%s:%u" % (shard_0_master_addrs[0][0], shard_0_master_addrs[0][1]),
            "test_keyspace", "-80", 10.0)
        conn.dial()
        (results, rowcount, lastrowid, fields) = conn._execute(
            "select id, msg from vt_select_test order by id", {})
        self.assertEqual(results, [
            (1, 'test 1'),
            (2, 'test 2'),
        ], 'wrong conn._execute output: %s' % str(results))

        # connect to shard 80-
        shard_1_master_addrs = topology.get_host_port_by_name(
            zkocc_client, "test_keyspace.80-.master:_vtocc")
        conn = tablet3.TabletConnection(
            "%s:%u" % (shard_1_master_addrs[0][0], shard_1_master_addrs[0][1]),
            "test_keyspace", "80-", 10.0)
        conn.dial()
        (results, rowcount, lastrowid, fields) = conn._execute(
            "select id, msg from vt_select_test order by id", {})
        self.assertEqual(results, [
            (10, 'test 10'),
        ], 'wrong conn._execute output: %s' % str(results))

        # try to connect with bad shard
        try:
            conn = tablet3.TabletConnection(
                "localhost:%u" % shard_0_master.port, "test_keyspace", "-90",
                10.0)
            conn.dial()
            self.fail('expected an exception')
        except Exception as e:
            if "fatal: Shard mismatch, expecting -80, received -90" not in str(
                    e):
                self.fail('unexpected exception: ' + str(e))

        utils.kill_sub_process(zkocc_server)
        shard_0_master.kill_vttablet()
        shard_0_replica.kill_vttablet()
        shard_1_master.kill_vttablet()
        shard_1_replica.kill_vttablet()
コード例 #5
0
    def test_secure(self):
        zkocc_server = utils.zkocc_start()

        # start the tablets
        shard_0_master.start_vttablet(cert=cert_dir + "/vt-server-cert.pem",
                                      key=cert_dir + "/vt-server-key.pem")
        shard_0_slave.start_vttablet(cert=cert_dir + "/vt-server-cert.pem",
                                     key=cert_dir + "/vt-server-key.pem",
                                     repl_extra_flags={
                                         'flags': "2048",
                                         'ssl-ca': cert_dir + "/ca-cert.pem",
                                         'ssl-cert':
                                         cert_dir + "/client-cert.pem",
                                         'ssl-key':
                                         cert_dir + "/client-key.pem",
                                     })

        # Reparent using SSL
        for t in [shard_0_master, shard_0_slave]:
            t.reset_replication()
        utils.run_vtctl('ReparentShard -force test_keyspace/0 ' +
                        shard_0_master.tablet_alias,
                        auto_log=True)

        # then get the topology and check it
        zkocc_client = zkocc.ZkOccConnection(
            "localhost:%u" % environment.zkocc_port_base, "test_nj", 30.0)
        topology.read_keyspaces(zkocc_client)

        shard_0_master_addrs = topology.get_host_port_by_name(
            zkocc_client, "test_keyspace.0.master:_vts")
        if len(shard_0_master_addrs) != 1:
            self.fail(
                'topology.get_host_port_by_name failed for "test_keyspace.0.master:_vts", got: %s'
                % " ".join([
                    "%s:%u(%s)" % (h, p, str(e))
                    for (h, p, e) in shard_0_master_addrs
                ]))
        if shard_0_master_addrs[0][2] != True:
            self.fail(
                'topology.get_host_port_by_name failed for "test_keyspace.0.master:_vts" is not encrypted'
            )
        logging.debug(
            "shard 0 master addrs: %s", " ".join([
                "%s:%u(%s)" % (h, p, str(e))
                for (h, p, e) in shard_0_master_addrs
            ]))

        # make sure asking for optionally secure connections works too
        auto_addrs = topology.get_host_port_by_name(
            zkocc_client, "test_keyspace.0.master:_vtocc", encrypted=True)
        if auto_addrs != shard_0_master_addrs:
            self.fail(
                'topology.get_host_port_by_name doesn\'t resolve encrypted addresses properly: %s != %s'
                % (str(shard_0_master_addrs), str(auto_addrs)))

        # try to connect with regular client
        try:
            conn = tablet3.TabletConnection(
                "%s:%u" %
                (shard_0_master_addrs[0][0], shard_0_master_addrs[0][1]), "",
                "test_keyspace", "0", 10.0)
            conn.dial()
            self.fail("No exception raised to secure port")
        except dbexceptions.FatalError as e:
            if not e.args[0][0].startswith('Unexpected EOF in handshake to'):
                self.fail("Unexpected exception: %s" % str(e))

        sconn = utils.get_vars(shard_0_master.port)["SecureConnections"]
        if sconn != 0:
            self.fail("unexpected conns %s" % sconn)

        # connect to encrypted port
        conn = tablet3.TabletConnection(
            "%s:%u" % (shard_0_master_addrs[0][0], shard_0_master_addrs[0][1]),
            "",
            "test_keyspace",
            "0",
            5.0,
            encrypted=True)
        conn.dial()
        (results, rowcount, lastrowid,
         fields) = conn._execute("select 1 from dual", {})
        self.assertEqual(results, [
            (1, ),
        ], 'wrong conn._execute output: %s' % str(results))

        sconn = utils.get_vars(shard_0_master.port)["SecureConnections"]
        if sconn != 1:
            self.fail("unexpected conns %s" % sconn)
        saccept = utils.get_vars(shard_0_master.port)["SecureAccepts"]
        if saccept == 0:
            self.fail("unexpected accepts %s" % saccept)

        # trigger a time out on a secure connection, see what exception we get
        try:
            conn._execute("select sleep(100) from dual", {})
            self.fail("No timeout exception")
        except dbexceptions.TimeoutError as e:
            logging.debug("Got the right exception for SSL timeout: %s",
                          str(e))

        # start a vtgate to connect to that tablet
        gate_proc, gate_port, gate_secure_port = utils.vtgate_start(
            tablet_bson_encrypted=True,
            cert=cert_dir + "/vt-server-cert.pem",
            key=cert_dir + "/vt-server-key.pem")

        # try to connect to vtgate with regular client
        timeout = 2.0
        try:
            conn = vtgatev2.connect([
                "localhost:%s" % (gate_secure_port),
            ], timeout)
            self.fail("No exception raised to VTGate secure port")
        except dbexceptions.OperationalError as e:
            exception_type = e.args[2]
            exception_msg = str(e.args[2][0][0])
            self.assertIsInstance(exception_type, dbexceptions.FatalError,
                                  "unexpected exception type")
            if not exception_msg.startswith('Unexpected EOF in handshake to'):
                self.fail("Unexpected exception message: %s" % exception_msg)

        sconn = utils.get_vars(gate_port)["SecureConnections"]
        if sconn != 0:
            self.fail("unexpected conns %s" % sconn)

        # connect to vtgate with encrypted port
        conn = vtgatev2.connect([
            "localhost:%s" % (gate_secure_port),
        ],
                                timeout,
                                encrypted=True)
        (results, rowcount, lastrowid, fields) = conn._execute(
            "select 1 from dual", {},
            "test_keyspace",
            "master",
            keyranges=[
                keyrange.KeyRange(keyrange_constants.NON_PARTIAL_KEYRANGE),
            ])
        self.assertEqual(rowcount, 1, "want 1, got %d" % (rowcount))
        self.assertEqual(len(fields), 1, "want 1, got %d" % (len(fields)))
        self.assertEqual(results, [
            (1, ),
        ], 'wrong conn._execute output: %s' % str(results))

        sconn = utils.get_vars(gate_port)["SecureConnections"]
        if sconn != 1:
            self.fail("unexpected conns %s" % sconn)
        saccept = utils.get_vars(gate_port)["SecureAccepts"]
        if saccept == 0:
            self.fail("unexpected accepts %s" % saccept)

        # trigger a time out on a vtgate secure connection, see what exception we get
        try:
            conn._execute("select sleep(4) from dual", {},
                          "test_keyspace",
                          "master",
                          keyranges=[
                              keyrange.KeyRange(
                                  keyrange_constants.NON_PARTIAL_KEYRANGE),
                          ])
            self.fail("No timeout exception")
        except dbexceptions.TimeoutError as e:
            logging.debug("Got the right exception for SSL timeout: %s",
                          str(e))
        conn.close()
        utils.vtgate_kill(gate_proc)

        # kill everything
        utils.kill_sub_process(zkocc_server)
コード例 #6
0
ファイル: tablet.py プロジェクト: miffa/vitess
 def conn(self):
     conn = tablet.TabletConnection('localhost:%d' % self.port,
                                    self.tablet_type, self.keyspace,
                                    self.shard, 30)
     conn.dial()
     return conn
コード例 #7
0
ファイル: sharded.py プロジェクト: zhzhy917/vitess
  def test_sharding(self):

    shard_0_master.init_tablet( 'master',  'test_keyspace', '-80')
    shard_0_replica.init_tablet('replica', 'test_keyspace', '-80')
    shard_1_master.init_tablet( 'master',  'test_keyspace', '80-')
    shard_1_replica.init_tablet('replica', 'test_keyspace', '80-')

    utils.run_vtctl(['RebuildKeyspaceGraph', 'test_keyspace'], auto_log=True)

    # run checks now before we start the tablets
    utils.validate_topology()

    # create databases, start the tablets, wait for them to start
    for t in [shard_0_master, shard_0_replica, shard_1_master, shard_1_replica]:
      t.create_db('vt_test_keyspace')
      t.start_vttablet(wait_for_state=None)
    for t in [shard_0_master, shard_0_replica, shard_1_master, shard_1_replica]:
      t.wait_for_vttablet_state('SERVING')

    # apply the schema on the first shard through vtctl, so all tablets
    # are the same.
    shard_0_master.mquery('vt_test_keyspace',
                          create_vt_select_test.replace("\n", ""), write=True)
    shard_0_replica.mquery('vt_test_keyspace',
                           create_vt_select_test.replace("\n", ""), write=True)

    # apply the schema on the second shard.
    shard_1_master.mquery('vt_test_keyspace',
                          create_vt_select_test_reverse.replace("\n", ""), write=True)
    shard_1_replica.mquery('vt_test_keyspace',
                           create_vt_select_test_reverse.replace("\n", ""), write=True)

    for t in [shard_0_master, shard_0_replica, shard_1_master, shard_1_replica]:
      utils.run_vtctl(['ReloadSchema', t.tablet_alias])

    # start vtgate, we'll use it later
    utils.VtGate().start()

    for t in [shard_0_master, shard_0_replica, shard_1_master, shard_1_replica]:
      t.reset_replication()
    utils.run_vtctl(['InitShardMaster', 'test_keyspace/-80',
                     shard_0_master.tablet_alias], auto_log=True)
    utils.run_vtctl(['InitShardMaster', 'test_keyspace/80-',
                     shard_1_master.tablet_alias], auto_log=True)

    # insert some values directly (db is RO after minority reparent)
    # FIXME(alainjobart) these values don't match the shard map
    utils.run_vtctl(['SetReadWrite', shard_0_master.tablet_alias])
    utils.run_vtctl(['SetReadWrite', shard_1_master.tablet_alias])
    shard_0_master.mquery('vt_test_keyspace', "insert into vt_select_test (id, msg) values (1, 'test 1')", write=True)
    shard_1_master.mquery('vt_test_keyspace', "insert into vt_select_test (id, msg) values (10, 'test 10')", write=True)

    utils.validate_topology(ping_tablets=True)

    utils.pause("Before the sql scatter query")

    # make sure the '1' value was written on first shard
    rows = shard_0_master.mquery('vt_test_keyspace', "select id, msg from vt_select_test order by id")
    self.assertEqual(rows, ((1, 'test 1'), ),
                     'wrong mysql_query output: %s' % str(rows))

    utils.pause("After db writes")

    # throw in some schema validation step
    # we created the schema differently, so it should show
    utils.run_vtctl(['ValidateSchemaShard', 'test_keyspace/-80'])
    utils.run_vtctl(['ValidateSchemaShard', 'test_keyspace/80-'])
    out, err = utils.run_vtctl(['ValidateSchemaKeyspace', 'test_keyspace'],
                               trap_output=True, raise_on_error=False)
    if 'test_nj-0000062344 and test_nj-0000062346 disagree on schema for table vt_select_test:\nCREATE TABLE' not in err or \
       'test_nj-0000062344 and test_nj-0000062347 disagree on schema for table vt_select_test:\nCREATE TABLE' not in err:
      self.fail('wrong ValidateSchemaKeyspace output: ' + err)

    # validate versions
    utils.run_vtctl(['ValidateVersionShard', 'test_keyspace/-80'],
                    auto_log=True)
    utils.run_vtctl(['ValidateVersionKeyspace', 'test_keyspace'], auto_log=True)

    # show and validate permissions
    utils.run_vtctl(['GetPermissions', 'test_nj-0000062344'], auto_log=True)
    utils.run_vtctl(['ValidatePermissionsShard', 'test_keyspace/-80'],
                    auto_log=True)
    utils.run_vtctl(['ValidatePermissionsKeyspace', 'test_keyspace'],
                    auto_log=True)

    if environment.topo_server().flavor() == 'zookeeper':
      # and create zkns on this complex keyspace, make sure a few files are created
      utils.run_vtctl(['ExportZknsForKeyspace', 'test_keyspace'])
      out, err = utils.run(environment.binary_argstr('zk')+' ls -R /zk/test_nj/zk?s/vt/test_keysp*', trap_output=True)
      lines = out.splitlines()
      for base in ['-80', '80-']:
        for db_type in ['master', 'replica']:
          for sub_path in ['', '.vdns', '/0', '/vt.vdns']:
            expected = '/zk/test_nj/zkns/vt/test_keyspace/' + base + '/' + db_type + sub_path
            if expected not in lines:
              self.fail('missing zkns part:\n%s\nin:%s' %(expected, out))

    # now try to connect using the python client and shard-aware connection
    # to both shards
    # first get the topology and check it
    vtgate_client = zkocc.ZkOccConnection(utils.vtgate.addr(),
                                          "test_nj", 30.0)
    topology.read_keyspaces(vtgate_client)

    shard_0_master_addrs = topology.get_host_port_by_name(vtgate_client, "test_keyspace.-80.master:vt")
    if len(shard_0_master_addrs) != 1:
      self.fail('topology.get_host_port_by_name failed for "test_keyspace.-80.master:vt", got: %s' % " ".join(["%s:%u(%s)" % (h, p, str(e)) for (h, p, e) in shard_0_master_addrs]))
    logging.debug("shard 0 master addrs: %s", " ".join(["%s:%u(%s)" % (h, p, str(e)) for (h, p, e) in shard_0_master_addrs]))

    # connect to shard -80
    conn = tablet3.TabletConnection("%s:%u" % (shard_0_master_addrs[0][0],
                                               shard_0_master_addrs[0][1]),
                                    "", "test_keyspace", "-80", 10.0)
    conn.dial()
    (results, rowcount, lastrowid, fields) = conn._execute("select id, msg from vt_select_test order by id", {})
    self.assertEqual(results, [(1, 'test 1'), ],
                     'wrong conn._execute output: %s' % str(results))

    # connect to shard 80-
    shard_1_master_addrs = topology.get_host_port_by_name(vtgate_client, "test_keyspace.80-.master:vt")
    conn = tablet3.TabletConnection("%s:%u" % (shard_1_master_addrs[0][0],
                                               shard_1_master_addrs[0][1]),
                                    "", "test_keyspace", "80-", 10.0)
    conn.dial()
    (results, rowcount, lastrowid, fields) = conn._execute("select id, msg from vt_select_test order by id", {})
    self.assertEqual(results, [(10, 'test 10'), ],
                     'wrong conn._execute output: %s' % str(results))
    vtgate_client.close()

    # try to connect with bad shard
    try:
      conn = tablet3.TabletConnection("localhost:%u" % shard_0_master.port,
                                      "", "test_keyspace", "-90", 10.0)
      conn.dial()
      self.fail('expected an exception')
    except Exception as e:
      if "fatal: Shard mismatch, expecting -80, received -90" not in str(e):
        self.fail('unexpected exception: ' + str(e))

    utils.vtgate.kill()
    tablet.kill_tablets([shard_0_master, shard_0_replica, shard_1_master,
                         shard_1_replica])
コード例 #8
0
    def test_secure(self):
        zkocc_server = utils.zkocc_start()

        # start the tablets
        shard_0_master.start_vttablet(cert=cert_dir + "/vt-server-cert.pem",
                                      key=cert_dir + "/vt-server-key.pem")
        shard_0_slave.start_vttablet(cert=cert_dir + "/vt-server-cert.pem",
                                     key=cert_dir + "/vt-server-key.pem",
                                     repl_extra_flags={
                                         'flags': 2048,
                                         'ssl_ca': cert_dir + "/ca-cert.pem",
                                         'ssl_cert':
                                         cert_dir + "/client-cert.pem",
                                         'ssl_key':
                                         cert_dir + "/client-key.pem",
                                     })

        # Reparent using SSL
        for t in [shard_0_master, shard_0_slave]:
            t.reset_replication()
        utils.run_vtctl('ReparentShard -force test_keyspace/0 ' +
                        shard_0_master.tablet_alias,
                        auto_log=True)

        # then get the topology and check it
        zkocc_client = zkocc.ZkOccConnection(
            "localhost:%u" % utils.zkocc_port_base, "test_nj", 30.0)
        topology.read_keyspaces(zkocc_client)

        shard_0_master_addrs = topology.get_host_port_by_name(
            zkocc_client, "test_keyspace.0.master:_vts")
        if len(shard_0_master_addrs) != 1:
            raise utils.TestError(
                'topology.get_host_port_by_name failed for "test_keyspace.0.master:_vts", got: %s'
                % " ".join([
                    "%s:%u(%s)" % (h, p, str(e))
                    for (h, p, e) in shard_0_master_addrs
                ]))
        if shard_0_master_addrs[0][2] != True:
            raise utils.TestError(
                'topology.get_host_port_by_name failed for "test_keyspace.0.master:_vts" is not encrypted'
            )
        logging.debug(
            "shard 0 master addrs: %s", " ".join([
                "%s:%u(%s)" % (h, p, str(e))
                for (h, p, e) in shard_0_master_addrs
            ]))

        # make sure asking for optionally secure connections works too
        auto_addrs = topology.get_host_port_by_name(
            zkocc_client, "test_keyspace.0.master:_vtocc", encrypted=True)
        if auto_addrs != shard_0_master_addrs:
            raise utils.TestError(
                'topology.get_host_port_by_name doesn\'t resolve encrypted addresses properly: %s != %s'
                % (str(shard_0_master_addrs), str(auto_addrs)))

        # try to connect with regular client
        try:
            conn = tablet3.TabletConnection(
                "%s:%u" %
                (shard_0_master_addrs[0][0], shard_0_master_addrs[0][1]),
                "test_keyspace", "0", 10.0)
            conn.dial()
            raise utils.TestError("No exception raised to secure port")
        except tablet3.FatalError as e:
            if not e.args[0][0].startswith('Unexpected EOF in handshake to'):
                raise utils.TestError("Unexpected exception: %s" % str(e))

        sconn = utils.get_vars(shard_0_master.port)["SecureConns"]
        if sconn != 0:
            raise utils.TestError("unexpected conns %s" % sconn)

        # connect to encrypted port
        conn = tablet3.TabletConnection(
            "%s:%u" % (shard_0_master_addrs[0][0], shard_0_master_addrs[0][1]),
            "test_keyspace",
            "0",
            5.0,
            encrypted=True)
        conn.dial()
        (results, rowcount, lastrowid,
         fields) = conn._execute("select 1 from dual", {})
        self.assertEqual(results, [
            (1, ),
        ], 'wrong conn._execute output: %s' % str(results))

        sconn = utils.get_vars(shard_0_master.port)["SecureConns"]
        if sconn != 1:
            raise utils.TestError("unexpected conns %s" % sconn)
        saccept = utils.get_vars(shard_0_master.port)["SecureAccepts"]
        if saccept == 0:
            raise utils.TestError("unexpected accepts %s" % saccept)

        # trigger a time out on a secure connection, see what exception we get
        try:
            conn._execute("select sleep(100) from dual", {})
            raise utils.TestError("No timeout exception")
        except tablet3.TimeoutError as e:
            logging.debug("Got the right exception for SSL timeout: %s",
                          str(e))

        # kill everything
        utils.kill_sub_process(zkocc_server)