diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java index cde961903..8754104cf 100644 --- a/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java +++ b/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java @@ -44,10 +44,12 @@ import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.io.CharStreams; import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; import io.grpc.alts.ComputeEngineChannelBuilder; import java.io.IOException; +import java.io.InputStreamReader; import java.util.Map; import java.util.concurrent.Executor; import java.util.concurrent.ScheduledExecutorService; @@ -74,6 +76,8 @@ public final class InstantiatingGrpcChannelProvider implements TransportChannelP static final long DIRECT_PATH_KEEP_ALIVE_TIMEOUT_SECONDS = 20; // reduce the thundering herd problem of too many channels trying to (re)connect at the same time static final int MAX_POOL_SIZE = 1000; + static final String GCE_PRODUCTION_NAME_PRIOR_2016 = "Google"; + static final String GCE_PRODUCTION_NAME_AFTER_2016 = "Google Compute Engine"; private final int processorCount; private final Executor executor; @@ -234,6 +238,26 @@ private boolean isDirectPathEnabled(String serviceAddress) { return false; } + // DirectPath should only be used on Compute Engine. + // Notice Windows is supported for now. + static boolean isOnComputeEngine() { + String osName = System.getProperty("os.name"); + if ("Linux".equals(osName)) { + String cmd = "cat /sys/class/dmi/id/product_name"; + try { + Process process = Runtime.getRuntime().exec(new String[] {"/bin/sh", "-c", cmd}); + process.waitFor(); + String result = + CharStreams.toString(new InputStreamReader(process.getInputStream(), "UTF-8")); + return result.contains(GCE_PRODUCTION_NAME_PRIOR_2016) + || result.contains(GCE_PRODUCTION_NAME_AFTER_2016); + } catch (IOException | InterruptedException e) { + return false; + } + } + return false; + } + private ManagedChannel createSingleChannel() throws IOException { GrpcHeaderInterceptor headerInterceptor = new GrpcHeaderInterceptor(headerProvider.getHeaders()); @@ -250,7 +274,9 @@ private ManagedChannel createSingleChannel() throws IOException { ManagedChannelBuilder builder; // TODO(weiranf): Add API in ComputeEngineCredentials to check default service account. - if (isDirectPathEnabled(serviceAddress) && credentials instanceof ComputeEngineCredentials) { + if (isDirectPathEnabled(serviceAddress) + && credentials instanceof ComputeEngineCredentials + && isOnComputeEngine()) { builder = ComputeEngineChannelBuilder.forAddress(serviceAddress, port); // Set default keepAliveTime and keepAliveTimeout when directpath environment is enabled. // Will be overridden by user defined values if any. diff --git a/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java b/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java index f72754ae1..16d04e0d5 100644 --- a/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java +++ b/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java @@ -219,7 +219,11 @@ public void testWithGCECredentials() throws IOException { ApiFunction channelConfigurator = new ApiFunction() { public ManagedChannelBuilder apply(ManagedChannelBuilder channelBuilder) { - assertThat(channelBuilder instanceof ComputeEngineChannelBuilder).isTrue(); + if (InstantiatingGrpcChannelProvider.isOnComputeEngine()) { + assertThat(channelBuilder instanceof ComputeEngineChannelBuilder).isTrue(); + } else { + assertThat(channelBuilder instanceof ComputeEngineChannelBuilder).isFalse(); + } return channelBuilder; } }; @@ -234,7 +238,11 @@ public ManagedChannelBuilder apply(ManagedChannelBuilder channelBuilder) { .withEndpoint("localhost:8080"); assertThat(provider.needsCredentials()).isTrue(); - provider = provider.withCredentials(ComputeEngineCredentials.create()); + if (InstantiatingGrpcChannelProvider.isOnComputeEngine()) { + provider = provider.withCredentials(ComputeEngineCredentials.create()); + } else { + provider = provider.withCredentials(CloudShellCredentials.create(3000)); + } assertThat(provider.needsCredentials()).isFalse(); provider.getTransportChannel().shutdownNow();