Merge pull request #14888 from markdroth/ref_counted_inheritence_workaround

Work-around for ref-counted subclass deletion address problem.
diff --git a/examples/csharp/helloworld-from-cli/global.json b/examples/csharp/helloworld-from-cli/global.json
deleted file mode 100644
index e4b797e..0000000
--- a/examples/csharp/helloworld-from-cli/global.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "sdk": {
-    "version": "1.0.0"
-  }
-}
diff --git a/src/core/lib/iomgr/tcp_uv.cc b/src/core/lib/iomgr/tcp_uv.cc
index f20f8dc..8d0e4a5 100644
--- a/src/core/lib/iomgr/tcp_uv.cc
+++ b/src/core/lib/iomgr/tcp_uv.cc
@@ -204,6 +204,9 @@
   uv_socket->write_buffers = nullptr;
   uv_socket->read_len = 0;
   uv_tcp_nodelay(uv_socket->handle, 1);
+  // Node uses a garbage collector to call destructors, so we don't
+  // want to hold the uv loop open with active gRPC objects.
+  uv_unref((uv_handle_t*)uv_socket->handle);
   uv_socket->pending_connection = false;
   uv_socket->accept_socket = nullptr;
   uv_socket->accept_error = GRPC_ERROR_NONE;
diff --git a/src/core/lib/iomgr/timer_uv.cc b/src/core/lib/iomgr/timer_uv.cc
index dadeb96..8b7c82e 100644
--- a/src/core/lib/iomgr/timer_uv.cc
+++ b/src/core/lib/iomgr/timer_uv.cc
@@ -52,6 +52,9 @@
   uv_timer->data = t;
   t->timer = (void*)uv_timer;
   uv_timer_start(uv_timer, run_expired_timer, t->timeout_ms, 0);
+  // Node uses a garbage collector to call destructors, so we don't
+  // want to hold the uv loop open with active gRPC objects.
+  uv_unref((uv_handle_t*)uv_timer);
 }
 
 static void timer_stop(grpc_custom_timer* t) {
diff --git a/src/core/lib/surface/server.cc b/src/core/lib/surface/server.cc
index f7505c8..cb34def 100644
--- a/src/core/lib/surface/server.cc
+++ b/src/core/lib/surface/server.cc
@@ -1161,6 +1161,22 @@
   gpr_mu_unlock(&server->mu_global);
 }
 
+/*
+  - Kills all pending requests-for-incoming-RPC-calls (i.e the requests made via
+    grpc_server_request_call and grpc_server_request_registered call will now be
+    cancelled). See 'kill_pending_work_locked()'
+
+  - Shuts down the listeners (i.e the server will no longer listen on the port
+    for new incoming channels).
+
+  - Iterates through all channels on the server and sends shutdown msg (see
+    'channel_broadcaster_shutdown()' for details) to the clients via the
+    transport layer. The transport layer then guarantees the following:
+     -- Sends shutdown to the client (for eg: HTTP2 transport sends GOAWAY)
+     -- If the server has outstanding calls that are in the process, the
+        connection is NOT closed until the server is done with all those calls
+     -- Once, there are no more calls in progress, the channel is closed
+ */
 void grpc_server_shutdown_and_notify(grpc_server* server,
                                      grpc_completion_queue* cq, void* tag) {
   listener* l;
diff --git a/src/csharp/Grpc.Core/NativeDeps.Mac.csproj.include b/src/csharp/Grpc.Core/NativeDeps.Mac.csproj.include
index f1b85c3..309e33d 100644
--- a/src/csharp/Grpc.Core/NativeDeps.Mac.csproj.include
+++ b/src/csharp/Grpc.Core/NativeDeps.Mac.csproj.include
@@ -1,13 +1,5 @@
 <Project>
   <ItemGroup>
-    <!-- We are relying on run_tests.py to build grpc_csharp_ext with the right bitness
-    and we copy it as both x86 (needed by net45) and x64 (needed by netcoreapp1.0) as we don't
-    know which one will be needed to run the tests. -->
-    <Content Include="..\..\..\libs\$(NativeDependenciesConfigurationUnix)\libgrpc_csharp_ext.dylib">
-      <Link>libgrpc_csharp_ext.x86.dylib</Link>
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-      <Pack>false</Pack>
-    </Content>
     <Content Include="..\..\..\libs\$(NativeDependenciesConfigurationUnix)\libgrpc_csharp_ext.dylib">
       <Link>libgrpc_csharp_ext.x64.dylib</Link>
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
diff --git a/src/csharp/Grpc.Core/RpcException.cs b/src/csharp/Grpc.Core/RpcException.cs
index d2c912e..94429d7 100644
--- a/src/csharp/Grpc.Core/RpcException.cs
+++ b/src/csharp/Grpc.Core/RpcException.cs
@@ -73,6 +73,17 @@
         }
 
         /// <summary>
+        /// Returns the status code of the call, as a convenient alternative to <see cref="StatusCode">Status.StatusCode</see>.
+        /// </summary>
+        public StatusCode StatusCode
+        {
+            get
+            {
+                return status.StatusCode;
+            }
+        }
+
+        /// <summary>
         /// Gets the call trailing metadata.
         /// Trailers only have meaningful content for client-side calls (in which case they represent the trailing metadata sent by the server when closing the call).
         /// Instances of <c>RpcException</c> thrown by the server-side part of the stack will have trailers always set to empty.
diff --git a/src/csharp/global.json b/src/csharp/global.json
deleted file mode 100644
index 815be4b..0000000
--- a/src/csharp/global.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "sdk": {
-    "version": "2.1.4"
-  }
-}
diff --git a/templates/tools/dockerfile/python_deps.include b/templates/tools/dockerfile/python_deps.include
index ce36de8..c7bf238 100644
--- a/templates/tools/dockerfile/python_deps.include
+++ b/templates/tools/dockerfile/python_deps.include
@@ -9,6 +9,6 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
diff --git a/templates/tools/dockerfile/test/cxx_alpine_x64/Dockerfile.template b/templates/tools/dockerfile/test/cxx_alpine_x64/Dockerfile.template
index b250566..d70ad94 100644
--- a/templates/tools/dockerfile/test/cxx_alpine_x64/Dockerfile.template
+++ b/templates/tools/dockerfile/test/cxx_alpine_x64/Dockerfile.template
@@ -40,7 +40,7 @@
     zip
   
   # Install Python packages from PyPI
-  RUN pip install --upgrade pip==9.0.2
+  RUN pip install --upgrade pip==10.0.1
   RUN pip install virtualenv
   RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
   
diff --git a/test/core/tsi/alts/fake_handshaker/BUILD b/test/core/tsi/alts/fake_handshaker/BUILD
new file mode 100644
index 0000000..a09a046
--- /dev/null
+++ b/test/core/tsi/alts/fake_handshaker/BUILD
@@ -0,0 +1,57 @@
+# Copyright 2018 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+licenses(["notice"])  # Apache v2
+
+load("//bazel:grpc_build_system.bzl", "grpc_proto_library", "grpc_cc_library", "grpc_cc_binary", "grpc_package")
+
+grpc_package(name = "test/core/tsi/alts/fake_handshaker", visibility = "public")
+
+grpc_proto_library(
+    name = "transport_security_common_proto",
+    srcs = ["transport_security_common.proto"],
+    has_services = False,
+)
+
+grpc_proto_library(
+    name = "handshaker_proto",
+    srcs = ["handshaker.proto"],
+    has_services = True,
+    deps = [
+        "transport_security_common_proto",
+    ],
+)
+
+grpc_cc_library(
+    name = "fake_handshaker_lib",
+    testonly = True,
+    srcs = ["fake_handshaker_server.cc"],
+    language = "C++",
+    deps = [
+        "handshaker_proto",
+        "transport_security_common_proto",
+        "//:grpc++",
+        "//test/cpp/util:test_config",
+    ],
+)
+
+grpc_cc_binary(
+    name = "fake_handshaker_server",
+    testonly = True,
+    srcs = ["fake_handshaker_server.cc"],
+    language = "C++",
+    deps = [
+        "fake_handshaker_lib",
+    ],
+)
diff --git a/test/core/tsi/alts/fake_handshaker/fake_handshaker_server.cc b/test/core/tsi/alts/fake_handshaker/fake_handshaker_server.cc
new file mode 100644
index 0000000..f6a4791
--- /dev/null
+++ b/test/core/tsi/alts/fake_handshaker/fake_handshaker_server.cc
@@ -0,0 +1,268 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <memory>
+#include <sstream>
+#include <string>
+
+#include <gflags/gflags.h>
+#include <grpc/grpc.h>
+#include <grpc/support/log.h>
+#include <grpcpp/impl/codegen/async_stream.h>
+#include <grpcpp/security/server_credentials.h>
+#include <grpcpp/server.h>
+#include <grpcpp/server_builder.h>
+#include <grpcpp/server_context.h>
+
+#include "test/core/tsi/alts/fake_handshaker/handshaker.grpc.pb.h"
+#include "test/core/tsi/alts/fake_handshaker/handshaker.pb.h"
+#include "test/core/tsi/alts/fake_handshaker/transport_security_common.pb.h"
+#include "test/cpp/util/test_config.h"
+
+DEFINE_int32(handshaker_port, 55056,
+             "TCP port on which the fake handshaker server listens to.");
+
+// Fake handshake messages.
+constexpr char kClientInitFrame[] = "ClientInit";
+constexpr char kServerFrame[] = "ServerInitAndFinished";
+constexpr char kClientFinishFrame[] = "ClientFinished";
+// Error messages.
+constexpr char kInvalidFrameError[] = "Invalid input frame.";
+constexpr char kWrongStateError[] = "Wrong handshake state.";
+
+namespace grpc {
+namespace gcp {
+
+// FakeHandshakeService implements a fake handshaker service using a fake key
+// exchange protocol. The fake key exchange protocol is a 3-message protocol:
+// - Client first sends ClientInit message to Server.
+// - Server then sends ServerInitAndFinished message back to Client.
+// - Client finally sends ClientFinished message to Server.
+// This fake handshaker service is intended for ALTS integration testing without
+// relying on real ALTS handshaker service inside GCE.
+// It is thread-safe.
+class FakeHandshakerService : public HandshakerService::Service {
+ public:
+  Status DoHandshake(
+      ServerContext* server_context,
+      ServerReaderWriter<HandshakerResp, HandshakerReq>* stream) override {
+    Status status;
+    HandshakerContext context;
+    HandshakerReq request;
+    HandshakerResp response;
+    gpr_log(GPR_DEBUG, "Start a new handshake.");
+    while (stream->Read(&request)) {
+      status = ProcessRequest(&context, request, &response);
+      if (!status.ok()) return WriteErrorResponse(stream, status);
+      stream->Write(response);
+      if (context.state == COMPLETED) return Status::OK;
+      request.Clear();
+    }
+    return Status::OK;
+  }
+
+ private:
+  // HandshakeState is used by fake handshaker server to keep track of client's
+  // handshake status. In the beginning of a handshake, the state is INITIAL.
+  // If start_client or start_server request is called, the state becomes at
+  // least STARTED. When the handshaker server produces the first fame, the
+  // state becomes SENT. After the handshaker server processes the final frame
+  // from the peer, the state becomes COMPLETED.
+  enum HandshakeState { INITIAL, STARTED, SENT, COMPLETED };
+
+  struct HandshakerContext {
+    bool is_client = true;
+    HandshakeState state = INITIAL;
+  };
+
+  Status ProcessRequest(HandshakerContext* context,
+                        const HandshakerReq& request,
+                        HandshakerResp* response) {
+    GPR_ASSERT(context != nullptr && response != nullptr);
+    response->Clear();
+    if (request.has_client_start()) {
+      gpr_log(GPR_DEBUG, "Process client start request.");
+      return ProcessClientStart(context, request.client_start(), response);
+    } else if (request.has_server_start()) {
+      gpr_log(GPR_DEBUG, "Process server start request.");
+      return ProcessServerStart(context, request.server_start(), response);
+    } else if (request.has_next()) {
+      gpr_log(GPR_DEBUG, "Process next request.");
+      return ProcessNext(context, request.next(), response);
+    }
+    return Status(StatusCode::INVALID_ARGUMENT, "Request is empty.");
+  }
+
+  Status ProcessClientStart(HandshakerContext* context,
+                            const StartClientHandshakeReq& request,
+                            HandshakerResp* response) {
+    GPR_ASSERT(context != nullptr && response != nullptr);
+    // Checks request.
+    if (context->state != INITIAL) {
+      return Status(StatusCode::FAILED_PRECONDITION, kWrongStateError);
+    }
+    if (request.application_protocols_size() == 0) {
+      return Status(StatusCode::INVALID_ARGUMENT,
+                    "At least one application protocol needed.");
+    }
+    if (request.record_protocols_size() == 0) {
+      return Status(StatusCode::INVALID_ARGUMENT,
+                    "At least one record protocol needed.");
+    }
+    // Sets response.
+    response->set_out_frames(kClientInitFrame);
+    response->set_bytes_consumed(0);
+    response->mutable_status()->set_code(StatusCode::OK);
+    // Updates handshaker context.
+    context->is_client = true;
+    context->state = SENT;
+    return Status::OK;
+  }
+
+  Status ProcessServerStart(HandshakerContext* context,
+                            const StartServerHandshakeReq& request,
+                            HandshakerResp* response) {
+    GPR_ASSERT(context != nullptr && response != nullptr);
+    // Checks request.
+    if (context->state != INITIAL) {
+      return Status(StatusCode::FAILED_PRECONDITION, kWrongStateError);
+    }
+    if (request.application_protocols_size() == 0) {
+      return Status(StatusCode::INVALID_ARGUMENT,
+                    "At least one application protocol needed.");
+    }
+    if (request.handshake_parameters().empty()) {
+      return Status(StatusCode::INVALID_ARGUMENT,
+                    "At least one set of handshake parameters needed.");
+    }
+    // Sets response.
+    if (request.in_bytes().empty()) {
+      // start_server request does not have in_bytes.
+      response->set_bytes_consumed(0);
+      context->state = STARTED;
+    } else {
+      // start_server request has in_bytes.
+      if (request.in_bytes() == kClientInitFrame) {
+        response->set_out_frames(kServerFrame);
+        response->set_bytes_consumed(strlen(kClientInitFrame));
+        context->state = SENT;
+      } else {
+        return Status(StatusCode::UNKNOWN, kInvalidFrameError);
+      }
+    }
+    response->mutable_status()->set_code(StatusCode::OK);
+    context->is_client = false;
+    return Status::OK;
+  }
+
+  Status ProcessNext(HandshakerContext* context,
+                     const NextHandshakeMessageReq& request,
+                     HandshakerResp* response) {
+    GPR_ASSERT(context != nullptr && response != nullptr);
+    if (context->is_client) {
+      // Processes next request on client side.
+      if (context->state != SENT) {
+        return Status(StatusCode::FAILED_PRECONDITION, kWrongStateError);
+      }
+      if (request.in_bytes() != kServerFrame) {
+        return Status(StatusCode::UNKNOWN, kInvalidFrameError);
+      }
+      response->set_out_frames(kClientFinishFrame);
+      response->set_bytes_consumed(strlen(kServerFrame));
+      context->state = COMPLETED;
+    } else {
+      // Processes next request on server side.
+      HandshakeState current_state = context->state;
+      if (current_state == STARTED) {
+        if (request.in_bytes() != kClientInitFrame) {
+          return Status(StatusCode::UNKNOWN, kInvalidFrameError);
+        }
+        response->set_out_frames(kServerFrame);
+        response->set_bytes_consumed(strlen(kClientInitFrame));
+        context->state = SENT;
+      } else if (current_state == SENT) {
+        // Client finish frame may be sent along with the first payload from the
+        // client, handshaker only consumes the client finish frame.
+        if (request.in_bytes().substr(0, strlen(kClientFinishFrame)) !=
+            kClientFinishFrame) {
+          return Status(StatusCode::UNKNOWN, kInvalidFrameError);
+        }
+        response->set_bytes_consumed(strlen(kClientFinishFrame));
+        context->state = COMPLETED;
+      } else {
+        return Status(StatusCode::FAILED_PRECONDITION, kWrongStateError);
+      }
+    }
+    // At this point, processing next request succeeded.
+    response->mutable_status()->set_code(StatusCode::OK);
+    if (context->state == COMPLETED) {
+      *response->mutable_result() = GetHandshakerResult();
+    }
+    return Status::OK;
+  }
+
+  Status WriteErrorResponse(
+      ServerReaderWriter<HandshakerResp, HandshakerReq>* stream,
+      const Status& status) {
+    GPR_ASSERT(!status.ok());
+    HandshakerResp response;
+    response.mutable_status()->set_code(status.error_code());
+    response.mutable_status()->set_details(status.error_message());
+    stream->Write(response);
+    return status;
+  }
+
+  HandshakerResult GetHandshakerResult() {
+    HandshakerResult result;
+    result.set_application_protocol("grpc");
+    result.set_record_protocol("ALTSRP_GCM_AES128_REKEY");
+    result.mutable_peer_identity()->set_service_account("peer_identity");
+    result.mutable_local_identity()->set_service_account("local_identity");
+    string key(1024, '\0');
+    result.set_key_data(key);
+    result.mutable_peer_rpc_versions()->mutable_max_rpc_version()->set_major(2);
+    result.mutable_peer_rpc_versions()->mutable_max_rpc_version()->set_minor(1);
+    result.mutable_peer_rpc_versions()->mutable_min_rpc_version()->set_major(2);
+    result.mutable_peer_rpc_versions()->mutable_min_rpc_version()->set_minor(1);
+    return result;
+  }
+};
+
+}  // namespace gcp
+}  // namespace grpc
+
+void RunServer() {
+  GPR_ASSERT(FLAGS_handshaker_port != 0);
+  std::ostringstream server_address;
+  server_address << "[::1]:" << FLAGS_handshaker_port;
+  grpc::gcp::FakeHandshakerService service;
+  grpc::ServerBuilder builder;
+  builder.AddListeningPort(server_address.str(),
+                           grpc::InsecureServerCredentials());
+  builder.RegisterService(&service);
+  std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
+  gpr_log(GPR_INFO, "Fake handshaker server listening on %s",
+          server_address.str().c_str());
+  server->Wait();
+}
+
+int main(int argc, char** argv) {
+  grpc::testing::InitTest(&argc, &argv, true);
+  RunServer();
+  return 0;
+}
diff --git a/test/core/tsi/alts/fake_handshaker/handshaker.proto b/test/core/tsi/alts/fake_handshaker/handshaker.proto
new file mode 100644
index 0000000..8af9abf
--- /dev/null
+++ b/test/core/tsi/alts/fake_handshaker/handshaker.proto
@@ -0,0 +1,224 @@
+// Copyright 2018 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+import "test/core/tsi/alts/fake_handshaker/transport_security_common.proto";
+
+package grpc.gcp;
+
+option java_package = "io.grpc.alts.internal";
+
+enum HandshakeProtocol {
+  // Default value.
+  HANDSHAKE_PROTOCOL_UNSPECIFIED = 0;
+
+  // TLS handshake protocol.
+  TLS = 1;
+
+  // Application Layer Transport Security handshake protocol.
+  ALTS = 2;
+}
+
+enum NetworkProtocol {
+  NETWORK_PROTOCOL_UNSPECIFIED = 0;
+  TCP = 1;
+  UDP = 2;
+}
+
+message Endpoint {
+  // IP address. It should contain an IPv4 or IPv6 string literal, e.g.
+  // "192.168.0.1" or "2001:db8::1".
+  string ip_address = 1;
+
+  // Port number.
+  int32 port = 2;
+
+  // Network protocol (e.g., TCP, UDP) associated with this endpoint.
+  NetworkProtocol protocol = 3;
+}
+
+message Identity {
+  oneof identity_oneof {
+    // Service account of a connection endpoint.
+    string service_account = 1;
+
+    // Hostname of a connection endpoint.
+    string hostname = 2;
+  }
+}
+
+message StartClientHandshakeReq {
+  // Handshake security protocol requested by the client.
+  HandshakeProtocol handshake_security_protocol = 1;
+
+  // The application protocols supported by the client, e.g., "h2" (for http2),
+  // "grpc".
+  repeated string application_protocols = 2;
+
+  // The record protocols supported by the client, e.g.,
+  // "ALTSRP_GCM_AES128".
+  repeated string record_protocols = 3;
+
+  // (Optional) Describes which server identities are acceptable by the client.
+  // If target identities are provided and none of them matches the peer
+  // identity of the server, handshake will fail.
+  repeated Identity target_identities = 4;
+
+  // (Optional) Application may specify a local identity. Otherwise, the
+  // handshaker chooses a default local identity.
+  Identity local_identity = 5;
+
+  // (Optional) Local endpoint information of the connection to the server,
+  // such as local IP address, port number, and network protocol.
+  Endpoint local_endpoint = 6;
+
+  // (Optional) Endpoint information of the remote server, such as IP address,
+  // port number, and network protocol.
+  Endpoint remote_endpoint = 7;
+
+  // (Optional) If target name is provided, a secure naming check is performed
+  // to verify that the peer authenticated identity is indeed authorized to run
+  // the target name.
+  string target_name = 8;
+
+  // (Optional) RPC protocol versions supported by the client.
+  RpcProtocolVersions rpc_versions = 9;
+}
+
+message ServerHandshakeParameters {
+  // The record protocols supported by the server, e.g.,
+  // "ALTSRP_GCM_AES128".
+  repeated string record_protocols = 1;
+
+  // (Optional) A list of local identities supported by the server, if
+  // specified. Otherwise, the handshaker chooses a default local identity.
+  repeated Identity local_identities = 2;
+}
+
+message StartServerHandshakeReq {
+  // The application protocols supported by the server, e.g., "h2" (for http2),
+  // "grpc".
+  repeated string application_protocols = 1;
+
+  // Handshake parameters (record protocols and local identities supported by
+  // the server) mapped by the handshake protocol. Each handshake security
+  // protocol (e.g., TLS or ALTS) has its own set of record protocols and local
+  // identities. Since protobuf does not support enum as key to the map, the key
+  // to handshake_parameters is the integer value of HandshakeProtocol enum.
+  map<int32, ServerHandshakeParameters> handshake_parameters = 2;
+
+  // Bytes in out_frames returned from the peer's HandshakerResp. It is possible
+  // that the peer's out_frames are split into multiple HandshakReq messages.
+  bytes in_bytes = 3;
+
+  // (Optional) Local endpoint information of the connection to the client,
+  // such as local IP address, port number, and network protocol.
+  Endpoint local_endpoint = 4;
+
+  // (Optional) Endpoint information of the remote client, such as IP address,
+  // port number, and network protocol.
+  Endpoint remote_endpoint = 5;
+
+  // (Optional) RPC protocol versions supported by the server.
+  RpcProtocolVersions rpc_versions = 6;
+}
+
+message NextHandshakeMessageReq {
+  // Bytes in out_frames returned from the peer's HandshakerResp. It is possible
+  // that the peer's out_frames are split into multiple NextHandshakerMessageReq
+  // messages.
+  bytes in_bytes = 1;
+}
+
+message HandshakerReq {
+  oneof req_oneof {
+    // The start client handshake request message.
+    StartClientHandshakeReq client_start = 1;
+
+    // The start server handshake request message.
+    StartServerHandshakeReq server_start = 2;
+
+    // The next handshake request message.
+    NextHandshakeMessageReq next = 3;
+  }
+}
+
+message HandshakerResult {
+  // The application protocol negotiated for this connection.
+  string application_protocol = 1;
+
+  // The record protocol negotiated for this connection.
+  string record_protocol = 2;
+
+  // Cryptographic key data. The key data may be more than the key length
+  // required for the record protocol, thus the client of the handshaker
+  // service needs to truncate the key data into the right key length.
+  bytes key_data = 3;
+
+  // The authenticated identity of the peer.
+  Identity peer_identity = 4;
+
+  // The local identity used in the handshake.
+  Identity local_identity = 5;
+
+  // Indicate whether the handshaker service client should keep the channel
+  // between the handshaker service open, e.g., in order to handle
+  // post-handshake messages in the future.
+  bool keep_channel_open = 6;
+
+  // The RPC protocol versions supported by the peer.
+  RpcProtocolVersions peer_rpc_versions = 7;
+}
+
+message HandshakerStatus {
+  // The status code. This could be the gRPC status code.
+  uint32 code = 1;
+
+  // The status details.
+  string details = 2;
+}
+
+message HandshakerResp {
+  // Frames to be given to the peer for the NextHandshakeMessageReq. May be
+  // empty if no out_frames have to be sent to the peer or if in_bytes in the
+  // HandshakerReq are incomplete. All the non-empty out frames must be sent to
+  // the peer even if the handshaker status is not OK as these frames may
+  // contain the alert frames.
+  bytes out_frames = 1;
+
+  // Number of bytes in the in_bytes consumed by the handshaker. It is possible
+  // that part of in_bytes in HandshakerReq was unrelated to the handshake
+  // process.
+  uint32 bytes_consumed = 2;
+
+  // This is set iff the handshake was successful. out_frames may still be set
+  // to frames that needs to be forwarded to the peer.
+  HandshakerResult result = 3;
+
+  // Status of the handshaker.
+  HandshakerStatus status = 4;
+}
+
+service HandshakerService {
+  // Handshaker service accepts a stream of handshaker request, returning a
+  // stream of handshaker response. Client is expected to send exactly one
+  // message with either client_start or server_start followed by one or more
+  // messages with next. Each time client sends a request, the handshaker
+  // service expects to respond. Client does not have to wait for service's
+  // response before sending next request.
+  rpc DoHandshake(stream HandshakerReq)
+      returns (stream HandshakerResp) {
+  }
+}
diff --git a/test/core/tsi/alts/fake_handshaker/transport_security_common.proto b/test/core/tsi/alts/fake_handshaker/transport_security_common.proto
new file mode 100644
index 0000000..d0f861e
--- /dev/null
+++ b/test/core/tsi/alts/fake_handshaker/transport_security_common.proto
@@ -0,0 +1,40 @@
+// Copyright 2018 gRPC authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+package grpc.gcp;
+
+option java_package = "io.grpc.alts.internal";
+
+// The security level of the created channel. The list is sorted in increasing
+// level of security. This order must always be maintained.
+enum SecurityLevel {
+  SECURITY_NONE = 0;
+  INTEGRITY_ONLY = 1;
+  INTEGRITY_AND_PRIVACY = 2;
+}
+
+// Max and min supported RPC protocol versions.
+message RpcProtocolVersions {
+  // RPC version contains a major version and a minor version.
+  message Version {
+    uint32 major = 1;
+    uint32 minor = 2;
+  }
+  // Maximum supported RPC version.
+  Version max_rpc_version = 1;
+  // Minimum supported RPC version.
+  Version min_rpc_version = 2;
+}
diff --git a/test/core/tsi/ssl_transport_security_test.cc b/test/core/tsi/ssl_transport_security_test.cc
index 88f1abc..cf1ac82 100644
--- a/test/core/tsi/ssl_transport_security_test.cc
+++ b/test/core/tsi/ssl_transport_security_test.cc
@@ -34,6 +34,10 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
+extern "C" {
+#include <openssl/crypto.h>
+}
+
 #define SSL_TSI_TEST_ALPN1 "foo"
 #define SSL_TSI_TEST_ALPN2 "toto"
 #define SSL_TSI_TEST_ALPN3 "baz"
@@ -42,6 +46,14 @@
 #define SSL_TSI_TEST_BAD_SERVER_KEY_CERT_PAIRS_NUM 1
 #define SSL_TSI_TEST_CREDENTIALS_DIR "src/core/tsi/test_creds/"
 
+// OpenSSL 1.1 uses AES256 for encryption session ticket by default so specify
+// different STEK size.
+#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(OPENSSL_IS_BORINGSSL)
+const size_t kSessionTicketEncryptionKeySize = 80;
+#else
+const size_t kSessionTicketEncryptionKeySize = 48;
+#endif
+
 typedef enum AlpnMode {
   NO_ALPN,
   ALPN_CLIENT_NO_SERVER,
@@ -624,7 +636,7 @@
 
 void ssl_tsi_test_do_handshake_session_cache() {
   tsi_ssl_session_cache* session_cache = tsi_ssl_session_cache_create_lru(16);
-  char session_ticket_key[48];
+  char session_ticket_key[kSessionTicketEncryptionKeySize];
   auto do_handshake = [&session_ticket_key,
                        &session_cache](bool session_reused) {
     tsi_test_fixture* fixture = ssl_tsi_test_fixture_create();
@@ -633,22 +645,22 @@
     ssl_fixture->server_name_indication =
         const_cast<char*>("waterzooi.test.google.be");
     ssl_fixture->session_ticket_key = session_ticket_key;
-    ssl_fixture->session_ticket_key_size = 48;
+    ssl_fixture->session_ticket_key_size = sizeof(session_ticket_key);
     tsi_ssl_session_cache_ref(session_cache);
     ssl_fixture->session_cache = session_cache;
     ssl_fixture->session_reused = session_reused;
     tsi_test_do_round_trip(&ssl_fixture->base);
     tsi_test_fixture_destroy(fixture);
   };
-  memset(session_ticket_key, 'a', 48);
+  memset(session_ticket_key, 'a', sizeof(session_ticket_key));
   do_handshake(false);
   do_handshake(true);
   do_handshake(true);
   // Changing session_ticket_key on server invalidates ticket.
-  memset(session_ticket_key, 'b', 48);
+  memset(session_ticket_key, 'b', sizeof(session_ticket_key));
   do_handshake(false);
   do_handshake(true);
-  memset(session_ticket_key, 'c', 48);
+  memset(session_ticket_key, 'c', sizeof(session_ticket_key));
   do_handshake(false);
   do_handshake(true);
   tsi_ssl_session_cache_unref(session_cache);
diff --git a/test/cpp/interop/client.cc b/test/cpp/interop/client.cc
index ca8ee3d..3eb155e 100644
--- a/test/cpp/interop/client.cc
+++ b/test/cpp/interop/client.cc
@@ -31,6 +31,8 @@
 #include "test/cpp/interop/interop_client.h"
 #include "test/cpp/util/test_config.h"
 
+DEFINE_bool(use_alts, false,
+            "Whether to use alts. Enable alts will disable tls.");
 DEFINE_bool(use_tls, false, "Whether to use tls.");
 DEFINE_string(custom_credentials_type, "", "User provided credentials type.");
 DEFINE_bool(use_test_ca, false, "False to use SSL roots for google");
diff --git a/test/cpp/interop/client_helper.cc b/test/cpp/interop/client_helper.cc
index 4041f95..29b5a1e 100644
--- a/test/cpp/interop/client_helper.cc
+++ b/test/cpp/interop/client_helper.cc
@@ -35,6 +35,7 @@
 #include "test/cpp/util/create_test_channel.h"
 #include "test/cpp/util/test_credentials_provider.h"
 
+DECLARE_bool(use_alts);
 DECLARE_bool(use_tls);
 DECLARE_string(custom_credentials_type);
 DECLARE_bool(use_test_ca);
@@ -103,8 +104,10 @@
     GPR_ASSERT(creds);
   }
   if (FLAGS_custom_credentials_type.empty()) {
+    transport_security security_type =
+        FLAGS_use_alts ? ALTS : (FLAGS_use_tls ? TLS : INSECURE);
     return CreateTestChannel(host_port, FLAGS_server_host_override,
-                             FLAGS_use_tls, !FLAGS_use_test_ca, creds);
+                             security_type, !FLAGS_use_test_ca, creds);
   } else {
     return CreateTestChannel(host_port, FLAGS_custom_credentials_type, creds);
   }
diff --git a/test/cpp/interop/http2_client.cc b/test/cpp/interop/http2_client.cc
index 821815c..543f159 100644
--- a/test/cpp/interop/http2_client.cc
+++ b/test/cpp/interop/http2_client.cc
@@ -194,7 +194,7 @@
   snprintf(host_port, host_port_buf_size, "%s:%d", FLAGS_server_host.c_str(),
            FLAGS_server_port);
   std::shared_ptr<grpc::Channel> channel =
-      grpc::CreateTestChannel(host_port, false);
+      grpc::CreateTestChannel(host_port, grpc::testing::INSECURE);
   GPR_ASSERT(channel->WaitForConnected(gpr_time_add(
       gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(300, GPR_TIMESPAN))));
   grpc::testing::Http2Client client(channel);
diff --git a/test/cpp/interop/interop_server.cc b/test/cpp/interop/interop_server.cc
index 5fa1a33..6526e05 100644
--- a/test/cpp/interop/interop_server.cc
+++ b/test/cpp/interop/interop_server.cc
@@ -38,6 +38,8 @@
 #include "test/cpp/interop/server_helper.h"
 #include "test/cpp/util/test_config.h"
 
+DEFINE_bool(use_alts, false,
+            "Whether to use alts. Enable alts will disable tls.");
 DEFINE_bool(use_tls, false, "Whether to use tls.");
 DEFINE_string(custom_credentials_type, "", "User provided credentials type.");
 DEFINE_int32(port, 0, "Server port.");
diff --git a/test/cpp/interop/reconnect_interop_client.cc b/test/cpp/interop/reconnect_interop_client.cc
index 9a451fa..8a071d4 100644
--- a/test/cpp/interop/reconnect_interop_client.cc
+++ b/test/cpp/interop/reconnect_interop_client.cc
@@ -44,9 +44,11 @@
 using grpc::CreateTestChannel;
 using grpc::Status;
 using grpc::testing::Empty;
+using grpc::testing::INSECURE;
 using grpc::testing::ReconnectInfo;
 using grpc::testing::ReconnectParams;
 using grpc::testing::ReconnectService;
+using grpc::testing::TLS;
 
 int main(int argc, char** argv) {
   grpc::testing::InitTest(&argc, &argv, true);
@@ -57,7 +59,7 @@
   server_address << FLAGS_server_host << ':' << FLAGS_server_control_port;
   std::unique_ptr<ReconnectService::Stub> control_stub(
       ReconnectService::NewStub(
-          CreateTestChannel(server_address.str(), false)));
+          CreateTestChannel(server_address.str(), INSECURE)));
   ClientContext start_context;
   ReconnectParams reconnect_params;
   reconnect_params.set_max_reconnect_backoff_ms(FLAGS_max_reconnect_backoff_ms);
@@ -75,7 +77,7 @@
                         FLAGS_max_reconnect_backoff_ms);
   }
   std::shared_ptr<Channel> retry_channel =
-      CreateTestChannel(server_address.str(), "foo.test.google.fr", true, false,
+      CreateTestChannel(server_address.str(), "foo.test.google.fr", TLS, false,
                         std::shared_ptr<CallCredentials>(), channel_args);
 
   // About 13 retries.
diff --git a/test/cpp/interop/server_helper.cc b/test/cpp/interop/server_helper.cc
index 93ffd52..2194521 100644
--- a/test/cpp/interop/server_helper.cc
+++ b/test/cpp/interop/server_helper.cc
@@ -26,6 +26,7 @@
 #include "src/core/lib/surface/call_test_only.h"
 #include "test/cpp/util/test_credentials_provider.h"
 
+DECLARE_bool(use_alts);
 DECLARE_bool(use_tls);
 DECLARE_string(custom_credentials_type);
 
@@ -36,6 +37,8 @@
   if (!FLAGS_custom_credentials_type.empty()) {
     return GetCredentialsProvider()->GetServerCredentials(
         FLAGS_custom_credentials_type);
+  } else if (FLAGS_use_alts) {
+    return GetCredentialsProvider()->GetServerCredentials(kAltsCredentialsType);
   } else if (FLAGS_use_tls) {
     return GetCredentialsProvider()->GetServerCredentials(kTlsCredentialsType);
   } else {
diff --git a/test/cpp/interop/stress_test.cc b/test/cpp/interop/stress_test.cc
index 6e8134a..023e0c8 100644
--- a/test/cpp/interop/stress_test.cc
+++ b/test/cpp/interop/stress_test.cc
@@ -99,18 +99,24 @@
 
 // Options from client.cc (for compatibility with interop test).
 // TODO(sreek): Consolidate overlapping options
+DEFINE_bool(use_alts, false,
+            "Whether to use alts. Enable alts will disable tls.");
 DEFINE_bool(use_tls, false, "Whether to use tls.");
 DEFINE_bool(use_test_ca, false, "False to use SSL roots for google");
 DEFINE_string(server_host_override, "foo.test.google.fr",
               "Override the server host which is sent in HTTP header");
 
+using grpc::testing::ALTS;
+using grpc::testing::INSECURE;
 using grpc::testing::MetricsService;
 using grpc::testing::MetricsServiceImpl;
 using grpc::testing::StressTestInteropClient;
+using grpc::testing::TLS;
 using grpc::testing::TestCaseType;
 using grpc::testing::UNKNOWN_TEST;
 using grpc::testing::WeightedRandomTestSelector;
 using grpc::testing::kTestCaseList;
+using grpc::testing::transport_security;
 
 static int log_level = GPR_LOG_SEVERITY_DEBUG;
 
@@ -268,6 +274,8 @@
   int thread_idx = 0;
   int server_idx = -1;
   char buffer[256];
+  transport_security security_type =
+      FLAGS_use_alts ? ALTS : (FLAGS_use_tls ? TLS : INSECURE);
   for (auto it = server_addresses.begin(); it != server_addresses.end(); it++) {
     ++server_idx;
     // Create channel(s) for each server
@@ -276,7 +284,7 @@
       gpr_log(GPR_INFO, "Starting test with %s channel_idx=%d..", it->c_str(),
               channel_idx);
       std::shared_ptr<grpc::Channel> channel = grpc::CreateTestChannel(
-          *it, FLAGS_server_host_override, FLAGS_use_tls, !FLAGS_use_test_ca);
+          *it, FLAGS_server_host_override, security_type, !FLAGS_use_test_ca);
 
       // Create stub(s) for each channel
       for (int stub_idx = 0; stub_idx < FLAGS_num_stubs_per_channel;
diff --git a/test/cpp/util/create_test_channel.cc b/test/cpp/util/create_test_channel.cc
index 1047d44..0bcd4db 100644
--- a/test/cpp/util/create_test_channel.cc
+++ b/test/cpp/util/create_test_channel.cc
@@ -107,37 +107,37 @@
 
 std::shared_ptr<Channel> CreateTestChannel(
     const grpc::string& server, const grpc::string& override_hostname,
-    bool enable_ssl, bool use_prod_roots,
+    testing::transport_security security_type, bool use_prod_roots,
     const std::shared_ptr<CallCredentials>& creds,
     const ChannelArguments& args) {
-  grpc::string type;
-  if (enable_ssl) {
-    type = testing::kTlsCredentialsType;
-  }
-
+  grpc::string type =
+      security_type == testing::ALTS
+          ? testing::kAltsCredentialsType
+          : (security_type == testing::TLS ? testing::kTlsCredentialsType
+                                           : testing::kInsecureCredentialsType);
   return CreateTestChannel(server, type, override_hostname, use_prod_roots,
                            creds, args);
 }
 
 std::shared_ptr<Channel> CreateTestChannel(
     const grpc::string& server, const grpc::string& override_hostname,
-    bool enable_ssl, bool use_prod_roots,
+    testing::transport_security security_type, bool use_prod_roots,
     const std::shared_ptr<CallCredentials>& creds) {
-  return CreateTestChannel(server, override_hostname, enable_ssl,
+  return CreateTestChannel(server, override_hostname, security_type,
                            use_prod_roots, creds, ChannelArguments());
 }
 
 std::shared_ptr<Channel> CreateTestChannel(
     const grpc::string& server, const grpc::string& override_hostname,
-    bool enable_ssl, bool use_prod_roots) {
-  return CreateTestChannel(server, override_hostname, enable_ssl,
+    testing::transport_security security_type, bool use_prod_roots) {
+  return CreateTestChannel(server, override_hostname, security_type,
                            use_prod_roots, std::shared_ptr<CallCredentials>());
 }
 
 // Shortcut for end2end and interop tests.
-std::shared_ptr<Channel> CreateTestChannel(const grpc::string& server,
-                                           bool enable_ssl) {
-  return CreateTestChannel(server, "foo.test.google.fr", enable_ssl, false);
+std::shared_ptr<Channel> CreateTestChannel(
+    const grpc::string& server, testing::transport_security security_type) {
+  return CreateTestChannel(server, "foo.test.google.fr", security_type, false);
 }
 
 std::shared_ptr<Channel> CreateTestChannel(
diff --git a/test/cpp/util/create_test_channel.h b/test/cpp/util/create_test_channel.h
index ddaa99f..c615fb7 100644
--- a/test/cpp/util/create_test_channel.h
+++ b/test/cpp/util/create_test_channel.h
@@ -26,21 +26,27 @@
 namespace grpc {
 class Channel;
 
-std::shared_ptr<Channel> CreateTestChannel(const grpc::string& server,
-                                           bool enable_ssl);
+namespace testing {
+
+typedef enum { INSECURE = 0, TLS, ALTS } transport_security;
+
+}  // namespace testing
+
+std::shared_ptr<Channel> CreateTestChannel(
+    const grpc::string& server, testing::transport_security security_type);
 
 std::shared_ptr<Channel> CreateTestChannel(
     const grpc::string& server, const grpc::string& override_hostname,
-    bool enable_ssl, bool use_prod_roots);
+    testing::transport_security security_type, bool use_prod_roots);
 
 std::shared_ptr<Channel> CreateTestChannel(
     const grpc::string& server, const grpc::string& override_hostname,
-    bool enable_ssl, bool use_prod_roots,
+    testing::transport_security security_type, bool use_prod_roots,
     const std::shared_ptr<CallCredentials>& creds);
 
 std::shared_ptr<Channel> CreateTestChannel(
     const grpc::string& server, const grpc::string& override_hostname,
-    bool enable_ssl, bool use_prod_roots,
+    testing::transport_security security_type, bool use_prod_roots,
     const std::shared_ptr<CallCredentials>& creds,
     const ChannelArguments& args);
 
diff --git a/test/cpp/util/test_credentials_provider.cc b/test/cpp/util/test_credentials_provider.cc
index 7656100..c8b0ac7 100644
--- a/test/cpp/util/test_credentials_provider.cc
+++ b/test/cpp/util/test_credentials_provider.cc
@@ -56,6 +56,9 @@
       const grpc::string& type, ChannelArguments* args) override {
     if (type == grpc::testing::kInsecureCredentialsType) {
       return InsecureChannelCredentials();
+    } else if (type == grpc::testing::kAltsCredentialsType) {
+      grpc::experimental::AltsCredentialsOptions alts_opts;
+      return grpc::experimental::AltsCredentials(alts_opts);
     } else if (type == grpc::testing::kTlsCredentialsType) {
       SslCredentialsOptions ssl_opts = {test_root_cert, "", ""};
       args->SetSslTargetNameOverride("foo.test.google.fr");
@@ -77,6 +80,9 @@
       const grpc::string& type) override {
     if (type == grpc::testing::kInsecureCredentialsType) {
       return InsecureServerCredentials();
+    } else if (type == grpc::testing::kAltsCredentialsType) {
+      grpc::experimental::AltsServerCredentialsOptions alts_opts;
+      return grpc::experimental::AltsServerCredentials(alts_opts);
     } else if (type == grpc::testing::kTlsCredentialsType) {
       SslServerCredentialsOptions::PemKeyCertPair pkcp = {test_server1_key,
                                                           test_server1_cert};
diff --git a/test/cpp/util/test_credentials_provider.h b/test/cpp/util/test_credentials_provider.h
index f489a2c..b1d69e8 100644
--- a/test/cpp/util/test_credentials_provider.h
+++ b/test/cpp/util/test_credentials_provider.h
@@ -29,10 +29,10 @@
 namespace testing {
 
 const char kInsecureCredentialsType[] = "INSECURE_CREDENTIALS";
-
 // For real credentials, like tls/ssl, this name should match the AuthContext
 // property "transport_security_type".
 const char kTlsCredentialsType[] = "ssl";
+const char kAltsCredentialsType[] = "alts";
 
 // Provide test credentials of a particular type.
 class CredentialTypeProvider {
diff --git a/tools/distrib/pylint_code.sh b/tools/distrib/pylint_code.sh
index 307fe6c..013b666 100755
--- a/tools/distrib/pylint_code.sh
+++ b/tools/distrib/pylint_code.sh
@@ -30,10 +30,11 @@
 )
 
 VIRTUALENV=python_pylint_venv
+python -m virtualenv $VIRTUALENV
 
-virtualenv $VIRTUALENV
-PYTHON=$(realpath $VIRTUALENV/bin/python)
-$PYTHON -m pip install --upgrade pip==9.0.2
+PYTHON=$VIRTUALENV/bin/python
+
+$PYTHON -m pip install --upgrade pip==10.0.1
 $PYTHON -m pip install pylint==1.6.5
 
 for dir in "${DIRS[@]}"; do
diff --git a/tools/distrib/python/docgen.py b/tools/distrib/python/docgen.py
index 4d6fcb5..732d948 100755
--- a/tools/distrib/python/docgen.py
+++ b/tools/distrib/python/docgen.py
@@ -70,7 +70,7 @@
         'env': environment
     },
     {
-        'args': [VIRTUALENV_PIP_PATH, 'install', '--upgrade', 'pip==9.0.1'],
+        'args': [VIRTUALENV_PIP_PATH, 'install', '--upgrade', 'pip==10.0.1'],
         'env': environment
     },
     {
diff --git a/tools/distrib/yapf_code.sh b/tools/distrib/yapf_code.sh
index 919e9c1..dbc842f 100755
--- a/tools/distrib/yapf_code.sh
+++ b/tools/distrib/yapf_code.sh
@@ -32,7 +32,7 @@
 
 virtualenv $VIRTUALENV
 PYTHON=$(realpath "${VIRTUALENV}/bin/python")
-$PYTHON -m pip install --upgrade pip==9.0.2
+$PYTHON -m pip install --upgrade pip==10.0.1
 $PYTHON -m pip install --upgrade futures
 $PYTHON -m pip install yapf==0.20.0
 
diff --git a/tools/dockerfile/grpc_clang_tidy/Dockerfile b/tools/dockerfile/grpc_clang_tidy/Dockerfile
index d9599af..dec7680 100644
--- a/tools/dockerfile/grpc_clang_tidy/Dockerfile
+++ b/tools/dockerfile/grpc_clang_tidy/Dockerfile
@@ -33,9 +33,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 ADD clang_tidy_all_the_things.sh /
 
diff --git a/tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile
index 96154c8..e806ba5 100644
--- a/tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile
@@ -60,9 +60,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #================
 # C# dependencies
diff --git a/tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile
index 96154c8..e806ba5 100644
--- a/tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile
@@ -60,9 +60,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #================
 # C# dependencies
diff --git a/tools/dockerfile/interoptest/grpc_interop_cxx/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_cxx/Dockerfile
index 3e0f477..d3eb456 100644
--- a/tools/dockerfile/interoptest/grpc_interop_cxx/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_cxx/Dockerfile
@@ -60,9 +60,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #=================
 # C++ dependencies
diff --git a/tools/dockerfile/interoptest/grpc_interop_go/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_go/Dockerfile
index 83f05d8..b136259 100644
--- a/tools/dockerfile/interoptest/grpc_interop_go/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_go/Dockerfile
@@ -28,9 +28,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 # Define the default command.
 CMD ["bash"]
diff --git a/tools/dockerfile/interoptest/grpc_interop_go1.7/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_go1.7/Dockerfile
index 79907f3..d43d0e4 100644
--- a/tools/dockerfile/interoptest/grpc_interop_go1.7/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_go1.7/Dockerfile
@@ -28,9 +28,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 # Define the default command.
 CMD ["bash"]
diff --git a/tools/dockerfile/interoptest/grpc_interop_go1.8/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_go1.8/Dockerfile
index 4206941..17ca678 100644
--- a/tools/dockerfile/interoptest/grpc_interop_go1.8/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_go1.8/Dockerfile
@@ -28,9 +28,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 # Define the default command.
 CMD ["bash"]
diff --git a/tools/dockerfile/interoptest/grpc_interop_http2/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_http2/Dockerfile
index c14bcda..e7555c9 100644
--- a/tools/dockerfile/interoptest/grpc_interop_http2/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_http2/Dockerfile
@@ -28,9 +28,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 RUN pip install twisted h2==2.6.1 hyper
 
diff --git a/tools/dockerfile/interoptest/grpc_interop_java/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_java/Dockerfile
index 510e157..fc29ada 100644
--- a/tools/dockerfile/interoptest/grpc_interop_java/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_java/Dockerfile
@@ -43,9 +43,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 
 # Trigger download of as many Gradle artifacts as possible.
diff --git a/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile
index 510e157..fc29ada 100644
--- a/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile
@@ -43,9 +43,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 
 # Trigger download of as many Gradle artifacts as possible.
diff --git a/tools/dockerfile/interoptest/grpc_interop_node/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_node/Dockerfile
index 7464e31..539a869 100644
--- a/tools/dockerfile/interoptest/grpc_interop_node/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_node/Dockerfile
@@ -60,9 +60,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #==================
 # Node dependencies
diff --git a/tools/dockerfile/interoptest/grpc_interop_node/build_interop.sh b/tools/dockerfile/interoptest/grpc_interop_node/build_interop.sh
index c16efc1..21fdd0b 100755
--- a/tools/dockerfile/interoptest/grpc_interop_node/build_interop.sh
+++ b/tools/dockerfile/interoptest/grpc_interop_node/build_interop.sh
@@ -17,12 +17,23 @@
 set -e
 
 mkdir -p /var/local/git
+
 git clone /var/local/jenkins/grpc-node /var/local/git/grpc-node
 # clone gRPC submodules, use data from locally cloned submodules where possible
 (cd /var/local/jenkins/grpc-node/ && git submodule foreach 'cd /var/local/git/grpc-node \
 && git submodule update --init --recursive --reference /var/local/jenkins/grpc-node/${name} \
 ${name}')
 
+# Use the pending c-core changes if possible
+if [ -d "/var/local/jenkins/grpc" ]; then
+  cd /var/local/jenkins/grpc
+  CURRENT_COMMIT="$(git rev-parse --verify HEAD)"
+  cd /var/local/git/grpc-node/packages/grpc-native-core/deps/grpc/
+  git fetch --tags --progress https://github.com/grpc/grpc.git +refs/pull/*:refs/remotes/origin/pr/*
+  git checkout $CURRENT_COMMIT
+  git submodule update --init --recursive --reference /var/local/jenkins/grpc
+fi
+
 # copy service account keys if available
 cp -r /var/local/jenkins/service_account $HOME || true
 
diff --git a/tools/dockerfile/interoptest/grpc_interop_python/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_python/Dockerfile
index 49c1191..97cdf48 100644
--- a/tools/dockerfile/interoptest/grpc_interop_python/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_python/Dockerfile
@@ -60,9 +60,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 # Prepare ccache
 RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
diff --git a/tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile
index f3667b5..75e3314 100644
--- a/tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile
@@ -60,9 +60,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #==================
 # Ruby dependencies
diff --git a/tools/dockerfile/test/csharp_jessie_x64/Dockerfile b/tools/dockerfile/test/csharp_jessie_x64/Dockerfile
index c9335f0..7a8e26d 100644
--- a/tools/dockerfile/test/csharp_jessie_x64/Dockerfile
+++ b/tools/dockerfile/test/csharp_jessie_x64/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #================
 # C# dependencies
diff --git a/tools/dockerfile/test/cxx_alpine_x64/Dockerfile b/tools/dockerfile/test/cxx_alpine_x64/Dockerfile
index 5b2b527..3449af1 100644
--- a/tools/dockerfile/test/cxx_alpine_x64/Dockerfile
+++ b/tools/dockerfile/test/cxx_alpine_x64/Dockerfile
@@ -38,7 +38,7 @@
   zip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
 
diff --git a/tools/dockerfile/test/cxx_jessie_x64/Dockerfile b/tools/dockerfile/test/cxx_jessie_x64/Dockerfile
index 825896b..f251753 100644
--- a/tools/dockerfile/test/cxx_jessie_x64/Dockerfile
+++ b/tools/dockerfile/test/cxx_jessie_x64/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #=================
 # C++ dependencies
diff --git a/tools/dockerfile/test/cxx_jessie_x86/Dockerfile b/tools/dockerfile/test/cxx_jessie_x86/Dockerfile
index 692960d..bb9c751 100644
--- a/tools/dockerfile/test/cxx_jessie_x86/Dockerfile
+++ b/tools/dockerfile/test/cxx_jessie_x86/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #=================
 # C++ dependencies
diff --git a/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile b/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile
index 38b040b..b0d9261 100644
--- a/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile
+++ b/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #=================
 # C++ dependencies
diff --git a/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile b/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile
index 5487b6d..65ff58e 100644
--- a/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile
+++ b/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #=================
 # C++ dependencies
diff --git a/tools/dockerfile/test/cxx_ubuntu1710_x64/Dockerfile b/tools/dockerfile/test/cxx_ubuntu1710_x64/Dockerfile
index ffb0858..e926443 100644
--- a/tools/dockerfile/test/cxx_ubuntu1710_x64/Dockerfile
+++ b/tools/dockerfile/test/cxx_ubuntu1710_x64/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #=================
 # C++ dependencies
diff --git a/tools/dockerfile/test/fuzzer/Dockerfile b/tools/dockerfile/test/fuzzer/Dockerfile
index 3671219..a242492 100644
--- a/tools/dockerfile/test/fuzzer/Dockerfile
+++ b/tools/dockerfile/test/fuzzer/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #=================
 # C++ dependencies
diff --git a/tools/dockerfile/test/multilang_jessie_x64/Dockerfile b/tools/dockerfile/test/multilang_jessie_x64/Dockerfile
index 8202a4a..962fe97 100644
--- a/tools/dockerfile/test/multilang_jessie_x64/Dockerfile
+++ b/tools/dockerfile/test/multilang_jessie_x64/Dockerfile
@@ -140,9 +140,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 # Install coverage for Python test coverage reporting
 RUN pip install coverage
diff --git a/tools/dockerfile/test/node_jessie_x64/Dockerfile b/tools/dockerfile/test/node_jessie_x64/Dockerfile
index e87eb6f..f32b437 100644
--- a/tools/dockerfile/test/node_jessie_x64/Dockerfile
+++ b/tools/dockerfile/test/node_jessie_x64/Dockerfile
@@ -75,9 +75,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #==================
 # Node dependencies
diff --git a/tools/dockerfile/test/php7_jessie_x64/Dockerfile b/tools/dockerfile/test/php7_jessie_x64/Dockerfile
index 3a63867..e96be27 100644
--- a/tools/dockerfile/test/php7_jessie_x64/Dockerfile
+++ b/tools/dockerfile/test/php7_jessie_x64/Dockerfile
@@ -75,9 +75,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 # Prepare ccache
 RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
diff --git a/tools/dockerfile/test/php_jessie_x64/Dockerfile b/tools/dockerfile/test/php_jessie_x64/Dockerfile
index 32a4b61..88ee267 100644
--- a/tools/dockerfile/test/php_jessie_x64/Dockerfile
+++ b/tools/dockerfile/test/php_jessie_x64/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #=================
 # PHP dependencies
diff --git a/tools/dockerfile/test/python_alpine_x64/Dockerfile b/tools/dockerfile/test/python_alpine_x64/Dockerfile
index 66ec34a..6e06e2d 100644
--- a/tools/dockerfile/test/python_alpine_x64/Dockerfile
+++ b/tools/dockerfile/test/python_alpine_x64/Dockerfile
@@ -37,7 +37,7 @@
   zip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0
 
diff --git a/tools/dockerfile/test/python_jessie_x64/Dockerfile b/tools/dockerfile/test/python_jessie_x64/Dockerfile
index 4e6916d..41b670c 100644
--- a/tools/dockerfile/test/python_jessie_x64/Dockerfile
+++ b/tools/dockerfile/test/python_jessie_x64/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 # Prepare ccache
 RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
diff --git a/tools/dockerfile/test/python_pyenv_x64/Dockerfile b/tools/dockerfile/test/python_pyenv_x64/Dockerfile
index bd1432e..24fe7b2 100644
--- a/tools/dockerfile/test/python_pyenv_x64/Dockerfile
+++ b/tools/dockerfile/test/python_pyenv_x64/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 # Install dependencies for pyenv
 RUN apt-get update && apt-get install -y \
diff --git a/tools/dockerfile/test/ruby_jessie_x64/Dockerfile b/tools/dockerfile/test/ruby_jessie_x64/Dockerfile
index 45923ca..37d909a 100644
--- a/tools/dockerfile/test/ruby_jessie_x64/Dockerfile
+++ b/tools/dockerfile/test/ruby_jessie_x64/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #==================
 # Ruby dependencies
diff --git a/tools/dockerfile/test/sanity/Dockerfile b/tools/dockerfile/test/sanity/Dockerfile
index c93693c..4885843 100644
--- a/tools/dockerfile/test/sanity/Dockerfile
+++ b/tools/dockerfile/test/sanity/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.2
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #=================
 # C++ dependencies
diff --git a/tools/gce/linux_kokoro_performance_worker_init.sh b/tools/gce/linux_kokoro_performance_worker_init.sh
index 084e9fb..4a1e3e6 100755
--- a/tools/gce/linux_kokoro_performance_worker_init.sh
+++ b/tools/gce/linux_kokoro_performance_worker_init.sh
@@ -72,7 +72,7 @@
 sudo apt-get install -y libgflags-dev libgtest-dev libc++-dev clang
 
 # Python dependencies
-sudo pip install --upgrade pip==9.0.2
+sudo pip install --upgrade pip==10.0.1
 sudo pip install tabulate
 sudo pip install google-api-python-client
 sudo pip install virtualenv
diff --git a/tools/gce/linux_performance_worker_init.sh b/tools/gce/linux_performance_worker_init.sh
index 09d8fd0..7222cef 100755
--- a/tools/gce/linux_performance_worker_init.sh
+++ b/tools/gce/linux_performance_worker_init.sh
@@ -72,7 +72,7 @@
 sudo apt-get install -y libgflags-dev libgtest-dev libc++-dev clang
 
 # Python dependencies
-sudo pip install --upgrade pip==9.0.2
+sudo pip install --upgrade pip==10.0.1
 sudo pip install tabulate
 sudo pip install google-api-python-client
 sudo pip install virtualenv
diff --git a/tools/interop_matrix/client_matrix.py b/tools/interop_matrix/client_matrix.py
index 730fe64..e39fabe 100644
--- a/tools/interop_matrix/client_matrix.py
+++ b/tools/interop_matrix/client_matrix.py
@@ -358,4 +358,14 @@
     'ruby_v1.0.1': 'ruby__v1.0.1',
     'csharp_v1.1.4': 'csharp__v1.1.4',
     'csharp_v1.2.5': 'csharp__v1.1.4',
+    'python_v1.0.x': 'python__v1.0.x',
+    'python_v1.1.4': 'python__v1.0.x',
+    'python_v1.2.5': 'python__v1.0.x',
+    'python_v1.3.9': 'python__v1.0.x',
+    'python_v1.4.2': 'python__v1.0.x',
+    'python_v1.6.6': 'python__v1.0.x',
+    'python_v1.7.2': 'python__v1.0.x',
+    'python_v1.8.1': 'python__v1.0.x',
+    'python_v1.9.1': 'python__v1.0.x',
+    'python_v1.10.0': 'python__v1.0.x',
 }
diff --git a/tools/interop_matrix/testcases/python__master b/tools/interop_matrix/testcases/python__master
index 71ba75e..467e41f 100755
--- a/tools/interop_matrix/testcases/python__master
+++ b/tools/interop_matrix/testcases/python__master
@@ -1,20 +1,20 @@
 #!/bin/bash
 echo "Testing ${docker_image:=grpc_interop_python:797ca293-94e8-48d4-92e9-a4d52fcfcca9}"
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=large_unary\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_unary\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=ping_pong\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_stream\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=client_streaming\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=server_streaming\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_begin\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_first_response\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=timeout_on_sleeping_server\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=large_unary\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_unary\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=ping_pong\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_stream\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=client_streaming\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=server_streaming\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_begin\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_first_response\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=timeout_on_sleeping_server\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=large_unary\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_unary\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=ping_pong\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_stream\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=client_streaming\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=server_streaming\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_begin\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_first_response\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=timeout_on_sleeping_server\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=large_unary\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_unary\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=ping_pong\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_stream\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=client_streaming\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=server_streaming\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_begin\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_first_response\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=timeout_on_sleeping_server\""
diff --git a/tools/interop_matrix/testcases/python__v1.0.x b/tools/interop_matrix/testcases/python__v1.0.x
new file mode 100755
index 0000000..71ba75e
--- /dev/null
+++ b/tools/interop_matrix/testcases/python__v1.0.x
@@ -0,0 +1,20 @@
+#!/bin/bash
+echo "Testing ${docker_image:=grpc_interop_python:797ca293-94e8-48d4-92e9-a4d52fcfcca9}"
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=large_unary\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_unary\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=ping_pong\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_stream\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=client_streaming\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=server_streaming\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_begin\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_first_response\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=timeout_on_sleeping_server\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=large_unary\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_unary\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=ping_pong\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_stream\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=client_streaming\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=server_streaming\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_begin\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_first_response\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=timeout_on_sleeping_server\""
diff --git a/tools/run_tests/helper_scripts/build_python.sh b/tools/run_tests/helper_scripts/build_python.sh
index bd95272..b0a6f0f 100755
--- a/tools/run_tests/helper_scripts/build_python.sh
+++ b/tools/run_tests/helper_scripts/build_python.sh
@@ -163,7 +163,7 @@
   ;;
 esac
 
-$VENV_PYTHON -m pip install --upgrade pip==9.0.2
+$VENV_PYTHON -m pip install --upgrade pip==10.0.1
 $VENV_PYTHON -m pip install setuptools
 $VENV_PYTHON -m pip install cython
 $VENV_PYTHON -m pip install six enum34 protobuf futures
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 4146eec..6fb0f89 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -921,9 +921,6 @@
             if self.platform == 'mac':
                 # TODO(jtattermusch): EMBED_ZLIB=true currently breaks the mac build
                 self._make_options = ['EMBED_OPENSSL=true']
-                if self.args.compiler != 'coreclr':
-                    # On Mac, official distribution of mono is 32bit.
-                    self._make_options += ['ARCH_FLAGS=-m32', 'LDFLAGS=-m32']
             else:
                 self._make_options = ['EMBED_OPENSSL=true', 'EMBED_ZLIB=true']
 
@@ -944,6 +941,9 @@
             assembly_subdir += '/net45'
             if self.platform == 'windows':
                 runtime_cmd = []
+            elif self.platform == 'mac':
+                # mono before version 5.2 on MacOS defaults to 32bit runtime
+                runtime_cmd = ['mono', '--arch=64']
             else:
                 runtime_cmd = ['mono']