You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stratos.apache.org by im...@apache.org on 2015/08/20 11:36:35 UTC

[49/51] [abbrv] [partial] stratos git commit: Revert "Upgrading to jclouds 1.9.1"

http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/README.txt
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/README.txt b/dependencies/jclouds/apis/gce/1.8.1-stratos/README.txt
new file mode 100644
index 0000000..0801104
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/README.txt
@@ -0,0 +1,77 @@
+======
+Stratos GCE provider 1.8.1
+======
+
+This code in Stratos is copied from Jclouds GCE [1]
+The jclouds GCE code has 2 directories oauth & google-compute-engine
+In Stratos, these two directories are mered into one.
+
+[1] https://github.com/jclouds/jclouds-labs-google/tree/jclouds-labs-google-1.8.1
+
+
+
+
+======
+jclouds Google Compute Engine Provider
+======
+
+
+Authenticating into the instances:
+--------
+
+User:
+If no user is provided in GoogleComputeEngineTemplateOptions when launching an instance by default "jclouds" is used.
+
+Credential:
+
+GCE uses exclusively ssh keys to login into instances.
+In order for an instance to be sshable a public key must be installed. Public keys are installed if they are present in the project or instance's metatada.
+
+For an instance to be ssable one of the following must happen:
+1 - the project's metadata has an adequately built "sshKeys" entry and a corresponding private key is provided in GoogleComputeEngineTemplateOptions when createNodesInGroup is called.
+2 - an instance of GoogleComputeEngineTemplateOptions with an adequate public and private key is provided.
+
+NOTE: if methods 2 is chosen the global project keys will not be installed in the instance.
+
+Please refer to Google's documentation on how to form valid project wide ssh keys metadata entries.
+
+FAQ:
+--------
+
+* Q. What is the identity for GCE?
+
+A. the identity is the developer email which can be obtained from the admin GUI. Its usually something in the form: <my account id>@developer.gserviceaccount.com
+
+* Q. What is the credential for GCE
+
+A. the credential is a private key, in pem format. It can be extracted from the p12 keystore that is obtained when creating a "Service Account" (in the GUI: Google apis console > Api Access > Create another client ID > "Service Account"
+
+* Q. How to convert a p12 keystore into a pem format jclouds Google Compute Engine can handle:
+
+A.
+
+1. Convert the p12 file into pem format (it will ask for the keystore password, which is usually "notasecret"):
+ openssl pkcs12 -in <my_keystore>.p12 -out <my_keystore>.pem -nodes
+
+2. Extract only the pk and remove passphrase
+ openssl rsa -in <my_keystore>.pem -out <my_key>.pem
+
+The last file (<my_key>.pem) should contain the pk that needs to be passed to `ContextBuilder.credential()` for the provider `google-compute-engine`.
+
+
+Running the live tests:
+--------
+
+1. Place the following in your ~/.m2/settings.xml in a profile enabled when live:
+```
+    <test.google-compute-engine.identity>YOUR_ACCOUNT_NUMBER@developer.gserviceaccount.com</test.google-compute-engine.identity>
+    <test.google-compute-engine.credential>-----BEGIN RSA PRIVATE KEY-----
+MIICXgIBAAKBgQRRbRqVDtJLN1MO/xJoKqZuphDeBh5jIKueW3aNIiWs1XFcct+h
+-- this text is literally from your <my_key>.pem
+aH7xmpHSTbbXmQkuuv+z8EKijigprd/FoJpTX1f5/R+4wQ==
+-----END RSA PRIVATE KEY-----</test.google-compute-engine.credential>
+  </properties>
+```
+
+2. mvn clean install -Plive 
+

http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/pom.xml
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/pom.xml b/dependencies/jclouds/apis/gce/1.8.1-stratos/pom.xml
new file mode 100644
index 0000000..c1a7b9d
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/pom.xml
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.jclouds.labs</groupId>
+        <artifactId>jclouds-labs-google</artifactId>
+        <version>1.8.1</version>
+    </parent>
+
+    <!-- TODO: when out of labs, switch to org.jclouds.provider -->
+    <groupId>org.apache.stratos</groupId>
+    <artifactId>gce</artifactId>
+    <version>1.8.1-stratosv1</version>
+    <name>jclouds Google Compute Engine provider</name>
+    <description>jclouds components to access GoogleCompute</description>
+    <packaging>bundle</packaging>
+
+    <properties>
+        <jclouds.version>1.8.1</jclouds.version>
+        <test.google-compute-engine.identity>Email associated with the Google API client_id
+        </test.google-compute-engine.identity>
+        <test.google-compute-engine.credential>Private key (PKCS12 file) associated with the Google API client_id
+        </test.google-compute-engine.credential>
+        <test.google-compute-engine.api-version>v1</test.google-compute-engine.api-version>
+        <test.google-compute-engine.build-version/>
+        <test.google-compute-engine.template>imageId=debian-7-wheezy-v20131120,locationId=us-central1-a,minRam=2048
+        </test.google-compute-engine.template>
+        <jclouds.osgi.export>org.jclouds.googlecomputeengine*;version="${project.version}"</jclouds.osgi.export>
+        <jclouds.osgi.import>
+            org.jclouds.compute.internal;version="${jclouds.version}",
+            org.jclouds.rest.internal;version="${jclouds.version}",
+            org.jclouds*;version="${jclouds.version}",
+            *
+        </jclouds.osgi.import>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.jclouds</groupId>
+            <artifactId>jclouds-core</artifactId>
+            <version>${jclouds.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds</groupId>
+            <artifactId>jclouds-compute</artifactId>
+            <version>${jclouds.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds</groupId>
+            <artifactId>jclouds-compute</artifactId>
+            <version>${jclouds.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds</groupId>
+            <artifactId>jclouds-core</artifactId>
+            <version>${jclouds.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds.driver</groupId>
+            <artifactId>jclouds-slf4j</artifactId>
+            <version>${jclouds.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds.driver</groupId>
+            <artifactId>jclouds-sshj</artifactId>
+            <version>${jclouds.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <profiles>
+        <profile>
+            <id>live</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>default-test</id>
+                                <configuration>
+                                    <skipTests>true</skipTests>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>integration</id>
+                                <phase>integration-test</phase>
+                                <goals>
+                                    <goal>test</goal>
+                                </goals>
+                                <configuration>
+                                    <systemPropertyVariables>
+                                        <test.google-compute-engine.identity>${test.google-compute-engine.identity}
+                                        </test.google-compute-engine.identity>
+                                        <test.google-compute-engine.credential>
+                                            ${test.google-compute-engine.credential}
+                                        </test.google-compute-engine.credential>
+                                        <test.google-compute-engine.api-version>
+                                            ${test.google-compute-engine.api-version}
+                                        </test.google-compute-engine.api-version>
+                                        <test.google-compute-engine.build-version>
+                                            ${test.google-compute-engine.build-version}
+                                        </test.google-compute-engine.build-version>
+                                        <test.google-compute-engine.template>${test.google-compute-engine.template}
+                                        </test.google-compute-engine.template>
+                                    </systemPropertyVariables>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApi.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApi.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApi.java
new file mode 100644
index 0000000..6440d91
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApi.java
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.jclouds.googlecomputeengine;
+
+import java.io.Closeable;
+
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+
+import org.jclouds.googlecomputeengine.features.AddressApi;
+import org.jclouds.googlecomputeengine.features.DiskApi;
+import org.jclouds.googlecomputeengine.features.FirewallApi;
+import org.jclouds.googlecomputeengine.features.GlobalOperationApi;
+import org.jclouds.googlecomputeengine.features.ImageApi;
+import org.jclouds.googlecomputeengine.features.InstanceApi;
+import org.jclouds.googlecomputeengine.features.MachineTypeApi;
+import org.jclouds.googlecomputeengine.features.NetworkApi;
+import org.jclouds.googlecomputeengine.features.ProjectApi;
+import org.jclouds.googlecomputeengine.features.RegionApi;
+import org.jclouds.googlecomputeengine.features.RegionOperationApi;
+import org.jclouds.googlecomputeengine.features.RouteApi;
+import org.jclouds.googlecomputeengine.features.SnapshotApi;
+import org.jclouds.googlecomputeengine.features.ZoneApi;
+import org.jclouds.googlecomputeengine.features.ZoneOperationApi;
+import org.jclouds.rest.annotations.Delegate;
+
+import com.google.common.annotations.Beta;
+
+
+/**
+ * Provides access to GoogleCompute.
+ * <p/>
+ *
+ * @see <a href="https://developers.google.com/compute/docs/reference/v1">api doc</a>
+ */
+@Beta
+public interface GoogleComputeEngineApi extends Closeable {
+
+   /**
+    * Provides access to Address features
+    *
+    * @param projectName the name of the project
+    */
+   @Delegate
+   @Path("/projects/{project}")
+   AddressApi getAddressApiForProject(@PathParam("project") String projectName);
+
+   /**
+    * Provides access to Disk features
+    *
+    * @param projectName the name of the project
+    */
+   @Delegate
+   @Path("/projects/{project}")
+   DiskApi getDiskApiForProject(@PathParam("project") String projectName);
+
+   /**
+    * Provides access to Firewall features
+    *
+    * @param projectName the name of the project
+    */
+   @Delegate
+   @Path("/projects/{project}")
+   FirewallApi getFirewallApiForProject(@PathParam("project") String projectName);
+
+   /**
+    * Provides access to Global Operation features
+    *
+    * @param projectName the name of the project
+    */
+   @Delegate
+   @Path("/projects/{project}")
+   GlobalOperationApi getGlobalOperationApiForProject(@PathParam("project") String projectName);
+
+   /**
+    * Provides access to Image features
+    *
+    * @param projectName the name of the project
+    */
+   @Delegate
+   @Path("/projects/{project}")
+   ImageApi getImageApiForProject(@PathParam("project") String projectName);
+
+   /**
+    * Provides access to Instance features
+    *
+    * @param projectName the name of the project
+    */
+   @Delegate
+   @Path("/projects/{project}")
+   InstanceApi getInstanceApiForProject(@PathParam("project") String projectName);
+
+   /**
+    * Provides access to MachineType features
+    *
+    * @param projectName the name of the project
+    */
+   @Delegate
+   @Path("/projects/{project}")
+   MachineTypeApi getMachineTypeApiForProject(@PathParam("project") String projectName);
+
+   /**
+    * Provides access to Network features
+    *
+    * @param projectName the name of the project
+    */
+   @Delegate
+   @Path("/projects/{project}")
+   NetworkApi getNetworkApiForProject(@PathParam("project") String projectName);
+
+   /**
+    * Provides access to Project features
+    */
+   @Delegate
+   ProjectApi getProjectApi();
+
+   /**
+    * Provides access to Region features
+    *
+    * @param projectName the name of the project
+    */
+   @Delegate
+   @Path("/projects/{project}")
+   RegionApi getRegionApiForProject(@PathParam("project") String projectName);
+
+   /**
+    * Provides access to Region Operation features
+    *
+    * @param projectName the name of the project
+    */
+   @Delegate
+   @Path("/projects/{project}")
+   RegionOperationApi getRegionOperationApiForProject(@PathParam("project") String projectName);
+
+   /**
+    * Provides access to Route features
+    *
+    * @param projectName the name of the project
+    */
+   @Delegate
+   @Path("/projects/{project}")
+   RouteApi getRouteApiForProject(@PathParam("project") String projectName);
+
+   /**
+    * Provides access to Snapshot features
+    *
+    * @param projectName the name of the project
+    */
+   @Delegate
+   @Path("/projects/{project}")
+   SnapshotApi getSnapshotApiForProject(@PathParam("project") String projectName);
+
+   /**
+    * Provides access to Zone features
+    *
+    * @param projectName the name of the project
+    */
+   @Delegate
+   @Path("/projects/{project}")
+   ZoneApi getZoneApiForProject(@PathParam("project") String projectName);
+
+   /**
+    * Provides access to Zone Operation features
+    *
+    * @param projectName the name of the project
+    */
+   @Delegate
+   @Path("/projects/{project}")
+   ZoneOperationApi getZoneOperationApiForProject(@PathParam("project") String projectName);
+
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApiMetadata.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApiMetadata.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApiMetadata.java
new file mode 100644
index 0000000..544a851
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineApiMetadata.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.jclouds.googlecomputeengine;
+
+import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
+import static org.jclouds.compute.config.ComputeServiceProperties.TEMPLATE;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.GCE_PROVIDER_NAME;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_INTERVAL;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_TIMEOUT;
+import static org.jclouds.oauth.v2.config.OAuthProperties.AUDIENCE;
+import static org.jclouds.oauth.v2.config.OAuthProperties.SIGNATURE_OR_MAC_ALGORITHM;
+import static org.jclouds.reflect.Reflection2.typeToken;
+
+import java.net.URI;
+import java.util.Properties;
+
+import org.jclouds.compute.ComputeServiceContext;
+import org.jclouds.googlecomputeengine.compute.config.GoogleComputeEngineServiceContextModule;
+import org.jclouds.googlecomputeengine.config.GoogleComputeEngineHttpApiModule;
+import org.jclouds.googlecomputeengine.config.GoogleComputeEngineParserModule;
+import org.jclouds.googlecomputeengine.config.OAuthModuleWithoutTypeAdapters;
+import org.jclouds.oauth.v2.config.OAuthAuthenticationModule;
+import org.jclouds.rest.internal.BaseHttpApiMetadata;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+
+/**
+ * Implementation of {@link ApiMetadata} for GoogleCompute v1 API
+ */
+public class GoogleComputeEngineApiMetadata extends BaseHttpApiMetadata<GoogleComputeEngineApi> {
+
+   @Override
+   public Builder toBuilder() {
+      return new Builder().fromApiMetadata(this);
+   }
+
+   public GoogleComputeEngineApiMetadata() {
+      this(new Builder());
+   }
+
+   protected GoogleComputeEngineApiMetadata(Builder builder) {
+      super(builder);
+   }
+
+   public static Properties defaultProperties() {
+      Properties properties = BaseHttpApiMetadata.defaultProperties();
+      properties.put("oauth.endpoint", "https://accounts.google.com/o/oauth2/token");
+      properties.put(AUDIENCE, "https://accounts.google.com/o/oauth2/token");
+      properties.put(SIGNATURE_OR_MAC_ALGORITHM, "RS256");
+      properties.put(PROPERTY_SESSION_INTERVAL, 3600);
+      properties.setProperty(TEMPLATE, "osFamily=DEBIAN,osVersionMatches=7\\..*,locationId=us-central1-a,loginUser=jclouds");
+      properties.put(OPERATION_COMPLETE_INTERVAL, 500);
+      properties.put(OPERATION_COMPLETE_TIMEOUT, 600000);
+      return properties;
+   }
+
+   public static class Builder extends BaseHttpApiMetadata.Builder<GoogleComputeEngineApi, Builder> {
+
+      protected Builder() {
+         id(GCE_PROVIDER_NAME)
+                 .name("Google Compute Engine Api")
+                 .identityName("Email associated with the Google API client_id")
+                 .credentialName("Private key literal associated with the Google API client_id")
+                 .documentation(URI.create("https://developers.google.com/compute/docs"))
+                 .version("v1")
+                 .defaultEndpoint("https://www.googleapis.com/compute/v1")
+                 .defaultProperties(GoogleComputeEngineApiMetadata.defaultProperties())
+                 .view(typeToken(ComputeServiceContext.class))
+                 .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+                         .add(GoogleComputeEngineHttpApiModule.class)
+                         .add(GoogleComputeEngineParserModule.class)
+                         .add(OAuthAuthenticationModule.class)
+                         .add(OAuthModuleWithoutTypeAdapters.class)
+                         .add(GoogleComputeEngineServiceContextModule.class)
+                         .build());
+      }
+
+      @Override
+      public GoogleComputeEngineApiMetadata build() {
+         return new GoogleComputeEngineApiMetadata(this);
+      }
+
+      @Override
+      protected Builder self() {
+         return this;
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineConstants.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineConstants.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineConstants.java
new file mode 100644
index 0000000..d20ff98
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/GoogleComputeEngineConstants.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.jclouds.googlecomputeengine;
+
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.domain.LocationScope;
+
+import com.google.common.annotations.Beta;
+
+public final class GoogleComputeEngineConstants {
+
+   public static final String GCE_PROVIDER_NAME = "google-compute-engine";
+
+   /**
+    * The name of the project that keeps public resources.
+    */
+   public static final String GOOGLE_PROJECT = "google";
+
+   public static final String CENTOS_PROJECT = "centos-cloud";
+
+   public static final String DEBIAN_PROJECT = "debian-cloud";
+
+   public static final String COMPUTE_SCOPE = "https://www.googleapis.com/auth/compute";
+
+   public static final String COMPUTE_READONLY_SCOPE = "https://www.googleapis.com/auth/compute.readonly";
+
+   public static final String STORAGE_READONLY_SCOPE = "https://www.googleapis.com/auth/devstorage.read_only";
+
+   public static final String STORAGE_WRITEONLY_SCOPE = "https://www.googleapis.com/auth/devstorage.write_only";
+
+
+   /**
+    * The total time, in msecs, to wait for an operation to complete.
+    */
+   @Beta
+   public static final String OPERATION_COMPLETE_TIMEOUT = "jclouds.google-compute-engine.operation-complete-timeout";
+
+   /**
+    * The interval, in msecs, between calls to check whether an operation has completed.
+    */
+   @Beta
+   public static final String OPERATION_COMPLETE_INTERVAL = "jclouds.google-compute-engine.operation-complete-interval";
+
+   public static final Location GOOGLE_PROVIDER_LOCATION = new LocationBuilder().scope(LocationScope.PROVIDER).id
+           (GCE_PROVIDER_NAME).description(GCE_PROVIDER_NAME).build();
+
+
+   /**
+    * The key we look for in instance metadata for the URI for the image the instance was created from.
+    */
+   public static final String GCE_IMAGE_METADATA_KEY = "jclouds-image";
+
+   /**
+    * Metadata key to check for whether we should delete an instance's boot disk when we delete the instance.
+    */
+   public static final String GCE_DELETE_BOOT_DISK_METADATA_KEY = "jclouds-delete-boot-disk";
+
+   /**
+    * The suffix we append to auto-created boot disk names.
+    */
+   public static final String GCE_BOOT_DISK_SUFFIX = "boot-disk";
+
+   private GoogleComputeEngineConstants() {
+      throw new AssertionError("intentionally unimplemented");
+   }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineService.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineService.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineService.java
new file mode 100644
index 0000000..3c140eb
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineService.java
@@ -0,0 +1,200 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.jclouds.googlecomputeengine.compute;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_INTERVAL;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_TIMEOUT;
+import static org.jclouds.util.Predicates2.retry;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Provider;
+
+import org.jclouds.Constants;
+import org.jclouds.collect.Memoized;
+import org.jclouds.compute.ComputeServiceContext;
+import org.jclouds.compute.callables.RunScriptOnNode;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.TemplateBuilder;
+import org.jclouds.compute.extensions.ImageExtension;
+import org.jclouds.compute.extensions.SecurityGroupExtension;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.compute.internal.BaseComputeService;
+import org.jclouds.compute.internal.PersistNodeCredentials;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
+import org.jclouds.compute.strategy.DestroyNodeStrategy;
+import org.jclouds.compute.strategy.GetImageStrategy;
+import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
+import org.jclouds.compute.strategy.InitializeRunScriptOnNodeOrPlaceInBadMap;
+import org.jclouds.compute.strategy.ListNodesStrategy;
+import org.jclouds.compute.strategy.RebootNodeStrategy;
+import org.jclouds.compute.strategy.ResumeNodeStrategy;
+import org.jclouds.compute.strategy.SuspendNodeStrategy;
+import org.jclouds.domain.Credentials;
+import org.jclouds.domain.Location;
+import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
+import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions;
+import org.jclouds.googlecomputeengine.config.UserProject;
+import org.jclouds.googlecomputeengine.domain.Firewall;
+import org.jclouds.googlecomputeengine.domain.Network;
+import org.jclouds.googlecomputeengine.domain.Operation;
+import org.jclouds.googlecomputeengine.features.FirewallApi;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.scriptbuilder.functions.InitAdminAccess;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.collect.Sets;
+import com.google.common.util.concurrent.Atomics;
+import com.google.common.util.concurrent.ListeningExecutorService;
+
+public class GoogleComputeEngineService extends BaseComputeService {
+
+   private final Function<Set<? extends NodeMetadata>, Set<String>> findOrphanedGroups;
+   private final GroupNamingConvention.Factory namingConvention;
+   private final GoogleComputeEngineApi api;
+   private final Supplier<String> project;
+   private final Predicate<AtomicReference<Operation>> operationDonePredicate;
+   private final long operationCompleteCheckInterval;
+   private final long operationCompleteCheckTimeout;
+
+   @Inject
+   protected GoogleComputeEngineService(ComputeServiceContext context,
+                                        Map<String, Credentials> credentialStore,
+                                        @Memoized Supplier<Set<? extends Image>> images,
+                                        @Memoized Supplier<Set<? extends Hardware>> hardwareProfiles,
+                                        @Memoized Supplier<Set<? extends Location>> locations,
+                                        ListNodesStrategy listNodesStrategy,
+                                        GetImageStrategy getImageStrategy,
+                                        GetNodeMetadataStrategy getNodeMetadataStrategy,
+                                        CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy,
+                                        RebootNodeStrategy rebootNodeStrategy,
+                                        DestroyNodeStrategy destroyNodeStrategy,
+                                        ResumeNodeStrategy resumeNodeStrategy,
+                                        SuspendNodeStrategy suspendNodeStrategy,
+                                        Provider<TemplateBuilder> templateBuilderProvider,
+                                        @Named("DEFAULT") Provider<TemplateOptions> templateOptionsProvider,
+                                        @Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>>
+                                                nodeRunning,
+                                        @Named(TIMEOUT_NODE_TERMINATED) Predicate<AtomicReference<NodeMetadata>>
+                                                nodeTerminated,
+                                        @Named(TIMEOUT_NODE_SUSPENDED)
+                                        Predicate<AtomicReference<NodeMetadata>> nodeSuspended,
+                                        InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
+                                        InitAdminAccess initAdminAccess,
+                                        RunScriptOnNode.Factory runScriptOnNodeFactory,
+                                        PersistNodeCredentials persistNodeCredentials,
+                                        ComputeServiceConstants.Timeouts timeouts,
+                                        @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
+                                        Optional<ImageExtension> imageExtension,
+                                        Optional<SecurityGroupExtension> securityGroupExtension,
+                                        Function<Set<? extends NodeMetadata>, Set<String>> findOrphanedGroups,
+                                        GroupNamingConvention.Factory namingConvention,
+                                        GoogleComputeEngineApi api,
+                                        @UserProject Supplier<String> project,
+                                        @Named("global") Predicate<AtomicReference<Operation>> operationDonePredicate,
+                                        @Named(OPERATION_COMPLETE_INTERVAL) Long operationCompleteCheckInterval,
+                                        @Named(OPERATION_COMPLETE_TIMEOUT) Long operationCompleteCheckTimeout) {
+
+      super(context, credentialStore, images, hardwareProfiles, locations, listNodesStrategy, getImageStrategy,
+              getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
+              resumeNodeStrategy, suspendNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
+              nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
+              persistNodeCredentials, timeouts, userExecutor, imageExtension, securityGroupExtension);
+      this.findOrphanedGroups = checkNotNull(findOrphanedGroups, "find orphaned groups function");
+      this.namingConvention = checkNotNull(namingConvention, "naming convention factory");
+      this.api = checkNotNull(api, "google compute api");
+      this.project = checkNotNull(project, "user project name");
+      this.operationDonePredicate = checkNotNull(operationDonePredicate, "operation completed predicate");
+      this.operationCompleteCheckInterval = checkNotNull(operationCompleteCheckInterval,
+              "operation completed check interval");
+      this.operationCompleteCheckTimeout = checkNotNull(operationCompleteCheckTimeout,
+              "operation completed check timeout");
+   }
+
+   @Override
+   protected synchronized void cleanUpIncidentalResourcesOfDeadNodes(Set<? extends NodeMetadata> deadNodes) {
+      Set<String> orphanedGroups = findOrphanedGroups.apply(deadNodes);
+      for (String orphanedGroup : orphanedGroups) {
+         cleanUpNetworksAndFirewallsForGroup(orphanedGroup);
+      }
+   }
+
+
+   protected void cleanUpNetworksAndFirewallsForGroup(final String groupName) {
+      String resourceName = namingConvention.create().sharedNameForGroup(groupName);
+      final Network network = api.getNetworkApiForProject(project.get()).get(resourceName);
+      FirewallApi firewallApi = api.getFirewallApiForProject(project.get());
+      Predicate<Firewall> firewallBelongsToNetwork = new Predicate<Firewall>() {
+         @Override
+         public boolean apply(Firewall input) {
+            return input != null && input.getNetwork().equals(network.getSelfLink());
+         }
+      };
+
+      Set<AtomicReference<Operation>> operations = Sets.newHashSet();
+      for (Firewall firewall : firewallApi.list().concat().filter(firewallBelongsToNetwork)) {
+         operations.add(new AtomicReference<Operation>(firewallApi.delete(firewall.getName())));
+      }
+
+      for (AtomicReference<Operation> operation : operations) {
+         retry(operationDonePredicate, operationCompleteCheckTimeout, operationCompleteCheckInterval,
+                 MILLISECONDS).apply(operation);
+
+         if (operation.get().getHttpError().isPresent()) {
+            HttpResponse response = operation.get().getHttpError().get();
+            logger.warn("delete orphaned firewall %s failed. Http Error Code: %d HttpError: %s",
+                    operation.get().getTargetId(), response.getStatusCode(), response.getMessage());
+         }
+      }
+
+      AtomicReference<Operation> operation = Atomics.newReference(api.getNetworkApiForProject(project.get()).delete(resourceName));
+
+      retry(operationDonePredicate, operationCompleteCheckTimeout, operationCompleteCheckInterval,
+              MILLISECONDS).apply(operation);
+
+      if (operation.get().getHttpError().isPresent()) {
+         HttpResponse response = operation.get().getHttpError().get();
+         logger.warn("delete orphaned network failed. Http Error Code: " + response.getStatusCode() +
+                 " HttpError: " + response.getMessage());
+      }
+   }
+
+
+   /**
+    * returns template options, except of type {@link org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions}.
+    */
+   @Override
+   public GoogleComputeEngineTemplateOptions templateOptions() {
+      return GoogleComputeEngineTemplateOptions.class.cast(super.templateOptions());
+   }
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceAdapter.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceAdapter.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceAdapter.java
new file mode 100644
index 0000000..3a26d34
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/GoogleComputeEngineServiceAdapter.java
@@ -0,0 +1,439 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.jclouds.googlecomputeengine.compute;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Iterables.contains;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.tryFind;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.CENTOS_PROJECT;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.DEBIAN_PROJECT;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.GCE_BOOT_DISK_SUFFIX;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.GCE_DELETE_BOOT_DISK_METADATA_KEY;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.GCE_IMAGE_METADATA_KEY;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_INTERVAL;
+import static org.jclouds.googlecomputeengine.GoogleComputeEngineConstants.OPERATION_COMPLETE_TIMEOUT;
+import static org.jclouds.googlecomputeengine.domain.Instance.NetworkInterface.AccessConfig.Type;
+import static org.jclouds.googlecomputeengine.predicates.InstancePredicates.isBootDisk;
+import static org.jclouds.util.Predicates2.retry;
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.annotation.Resource;
+import javax.inject.Named;
+
+import org.jclouds.collect.Memoized;
+import org.jclouds.compute.ComputeServiceAdapter;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
+import org.jclouds.googlecomputeengine.compute.functions.FirewallTagNamingConvention;
+import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions;
+import org.jclouds.googlecomputeengine.config.UserProject;
+import org.jclouds.googlecomputeengine.domain.Disk;
+import org.jclouds.googlecomputeengine.domain.Image;
+import org.jclouds.googlecomputeengine.domain.Instance;
+import org.jclouds.googlecomputeengine.domain.Instance.AttachedDisk;
+import org.jclouds.googlecomputeengine.domain.Instance.PersistentAttachedDisk;
+import org.jclouds.googlecomputeengine.domain.InstanceInZone;
+import org.jclouds.googlecomputeengine.domain.InstanceTemplate;
+import org.jclouds.googlecomputeengine.domain.InstanceTemplate.PersistentDisk;
+import org.jclouds.googlecomputeengine.domain.InstanceTemplate.PersistentDisk.Mode;
+import org.jclouds.googlecomputeengine.domain.MachineType;
+import org.jclouds.googlecomputeengine.domain.MachineTypeInZone;
+import org.jclouds.googlecomputeengine.domain.Operation;
+import org.jclouds.googlecomputeengine.domain.SlashEncodedIds;
+import org.jclouds.googlecomputeengine.domain.Zone;
+import org.jclouds.googlecomputeengine.features.InstanceApi;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.logging.Logger;
+
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.primitives.Ints;
+import com.google.common.util.concurrent.Atomics;
+import com.google.common.util.concurrent.UncheckedTimeoutException;
+import com.google.inject.Inject;
+
+public class GoogleComputeEngineServiceAdapter implements ComputeServiceAdapter<InstanceInZone, MachineTypeInZone, Image, Zone> {
+
+   @Resource
+   @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+   protected Logger logger = Logger.NULL;
+
+   private final GoogleComputeEngineApi api;
+   private final Supplier<String> userProject;
+   private final Supplier<Map<URI, ? extends Location>> zones;
+   private final Function<TemplateOptions, ImmutableMap.Builder<String, String>> metatadaFromTemplateOptions;
+   private final Predicate<AtomicReference<Operation>> retryOperationDonePredicate;
+   private final long operationCompleteCheckInterval;
+   private final long operationCompleteCheckTimeout;
+   private final FirewallTagNamingConvention.Factory firewallTagNamingConvention;
+
+   @Inject
+   public GoogleComputeEngineServiceAdapter(GoogleComputeEngineApi api,
+                                            @UserProject Supplier<String> userProject,
+                                            Function<TemplateOptions,
+                                                    ImmutableMap.Builder<String, String>> metatadaFromTemplateOptions,
+                                            @Named("zone") Predicate<AtomicReference<Operation>> operationDonePredicate,
+                                            @Named(OPERATION_COMPLETE_INTERVAL) Long operationCompleteCheckInterval,
+                                            @Named(OPERATION_COMPLETE_TIMEOUT) Long operationCompleteCheckTimeout,
+                                            @Memoized Supplier<Map<URI, ? extends Location>> zones,
+                                            FirewallTagNamingConvention.Factory firewallTagNamingConvention) {
+      this.api = checkNotNull(api, "google compute api");
+      this.userProject = checkNotNull(userProject, "user project name");
+      this.metatadaFromTemplateOptions = checkNotNull(metatadaFromTemplateOptions,
+              "metadata from template options function");
+      this.operationCompleteCheckInterval = checkNotNull(operationCompleteCheckInterval,
+              "operation completed check interval");
+      this.operationCompleteCheckTimeout = checkNotNull(operationCompleteCheckTimeout,
+                                                        "operation completed check timeout");
+      this.retryOperationDonePredicate = retry(operationDonePredicate, operationCompleteCheckTimeout,
+                                               operationCompleteCheckInterval, TimeUnit.MILLISECONDS);
+      this.zones = checkNotNull(zones, "zones");
+      this.firewallTagNamingConvention = checkNotNull(firewallTagNamingConvention, "firewallTagNamingConvention");
+   }
+
+   @Override
+   public NodeAndInitialCredentials<InstanceInZone> createNodeWithGroupEncodedIntoName(
+           final String group, final String name, final Template template) {
+
+      checkNotNull(template, "template");
+
+      GoogleComputeEngineTemplateOptions options = GoogleComputeEngineTemplateOptions.class.cast(template.getOptions()).clone();
+      checkState(options.getNetwork().isPresent(), "network was not present in template options");
+      Hardware hardware = checkNotNull(template.getHardware(), "hardware must be set");
+
+      checkNotNull(hardware.getUri(), "hardware must have a URI");
+      checkNotNull(template.getImage().getUri(), "image URI is null");
+
+      // Note that the ordering is significant here - the first disk must be the boot disk.
+      List<PersistentDisk> disks = Lists.newArrayList();
+
+      if (!tryFind(options.getDisks(), isBootDisk()).isPresent()) {
+         Disk bootDisk = createBootDisk(template, name);
+
+         disks.add(new PersistentDisk(Mode.READ_WRITE,
+                                      bootDisk.getSelfLink(),
+                                      null,
+                                      true,
+                                      true));
+      }
+
+      disks.addAll(options.getDisks());
+
+      InstanceTemplate instanceTemplate = InstanceTemplate.builder()
+              .forMachineType(hardware.getUri());
+
+      if (options.isEnableNat()) {
+         instanceTemplate.addNetworkInterface(options.getNetwork().get(), Type.ONE_TO_ONE_NAT);
+      } else {
+         instanceTemplate.addNetworkInterface(options.getNetwork().get());
+      }
+
+      instanceTemplate.disks(disks);
+
+      LoginCredentials credentials = getFromImageAndOverrideIfRequired(template.getImage(), options);
+
+      ImmutableMap.Builder<String, String> metadataBuilder = metatadaFromTemplateOptions.apply(options);
+
+      metadataBuilder.put(GCE_IMAGE_METADATA_KEY, template.getImage().getUri().toString());
+
+      if (!options.shouldKeepBootDisk()) {
+         metadataBuilder.put(GCE_DELETE_BOOT_DISK_METADATA_KEY, Boolean.TRUE.toString());
+      }
+
+      instanceTemplate.metadata(metadataBuilder.build());
+      instanceTemplate.serviceAccounts(options.getServiceAccounts());
+
+      final InstanceApi instanceApi = api.getInstanceApiForProject(userProject.get());
+      final String zone = template.getLocation().getId();
+      Operation operation = instanceApi.createInZone(name, zone, instanceTemplate);
+
+      if (options.shouldBlockUntilRunning()) {
+         waitOperationDone(operation);
+      }
+
+      // some times the newly created instances are not immediately returned
+      AtomicReference<Instance> instance = Atomics.newReference();
+
+      retry(new Predicate<AtomicReference<Instance>>() {
+         @Override
+         public boolean apply(AtomicReference<Instance> input) {
+            input.set(instanceApi.getInZone(zone, name));
+            return input.get() != null;
+         }
+      }, operationCompleteCheckTimeout, operationCompleteCheckInterval, MILLISECONDS).apply(instance);
+
+      if (!options.getTags().isEmpty()) {
+         Operation tagsOperation = instanceApi.setTagsInZone(zone,
+                 name, options.getTags(), instance.get().getTags().getFingerprint());
+
+         waitOperationDone(tagsOperation);
+
+         retry(new Predicate<AtomicReference<Instance>>() {
+            @Override
+            public boolean apply(AtomicReference<Instance> input) {
+               input.set(instanceApi.getInZone(zone, name));
+               return input.get() != null;
+            }
+         }, operationCompleteCheckTimeout, operationCompleteCheckInterval, MILLISECONDS).apply(instance);
+      }
+
+      // Add tags for security groups
+      final FirewallTagNamingConvention naming = firewallTagNamingConvention.get(group);
+      Set<String> tags = FluentIterable.from(Ints.asList(options.getInboundPorts()))
+              .transform(new Function<Integer, String>(){
+                       @Override
+                       public String apply(Integer input) {
+                          return input != null
+                                  ? naming.name(input)
+                                  : null;
+                       }
+                    })
+              .toSet();
+      instanceApi.setTagsInZone(zone, instance.get().getName(), tags, instance.get().getTags().getFingerprint());
+
+      InstanceInZone instanceInZone = new InstanceInZone(instance.get(), zone);
+
+      return new NodeAndInitialCredentials<InstanceInZone>(instanceInZone, instanceInZone.slashEncode(), credentials);
+   }
+
+   private Disk createBootDisk(Template template, String instanceName) {
+      URI imageUri = template.getImage().getUri();
+
+      GoogleComputeEngineTemplateOptions options = GoogleComputeEngineTemplateOptions.class.cast(template.getOptions()).clone();
+
+      int diskSize = options.getBootDiskSize().or(10l).intValue();
+
+      String diskName = instanceName + "-" + GCE_BOOT_DISK_SUFFIX;
+
+      Operation diskOperation = api.getDiskApiForProject(userProject.get())
+                                   .createFromImageWithSizeInZone(imageUri.toString(),
+                                                                  diskName,
+                                                                  diskSize,
+                                                                  template.getLocation().getId());
+
+      waitOperationDone(diskOperation);
+
+      return api.getDiskApiForProject(userProject.get()).getInZone(template.getLocation().getId(),
+                                                                   diskName);
+   }
+
+   @Override
+   public Iterable<MachineTypeInZone> listHardwareProfiles() {
+      ImmutableSet.Builder<MachineTypeInZone> builder = ImmutableSet.builder();
+
+      for (final Location zone : zones.get().values()) {
+         builder.addAll(api.getMachineTypeApiForProject(userProject.get())
+                 .listInZone(zone.getId())
+                 .concat()
+                 .filter(new Predicate<MachineType>() {
+                    @Override
+                    public boolean apply(MachineType input) {
+                       return !input.getDeprecated().isPresent();
+                    }
+                 })
+                 .transform(new Function<MachineType, MachineTypeInZone>() {
+
+                    @Override
+                    public MachineTypeInZone apply(MachineType arg0) {
+                       return new MachineTypeInZone(arg0, arg0.getZone());
+                    }
+                 }));
+      }
+
+      return builder.build();
+   }
+
+   @Override
+   public Iterable<Image> listImages() {
+      return ImmutableSet.<Image>builder()
+              .addAll(api.getImageApiForProject(userProject.get()).list().concat())
+              .addAll(api.getImageApiForProject(DEBIAN_PROJECT).list().concat())
+              .addAll(api.getImageApiForProject(CENTOS_PROJECT).list().concat())
+              .build();
+   }
+
+   @Override
+   public Image getImage(String id) {
+      return Objects.firstNonNull(api.getImageApiForProject(userProject.get()).get(id),
+                                  Objects.firstNonNull(api.getImageApiForProject(DEBIAN_PROJECT).get(id),
+                                          api.getImageApiForProject(CENTOS_PROJECT).get(id)));
+
+   }
+
+   @Override
+   public Iterable<Zone> listLocations() {
+      return api.getZoneApiForProject(userProject.get()).list().concat();
+   }
+
+   @Override
+   public InstanceInZone getNode(String name) {
+      SlashEncodedIds slashEncodedIds = SlashEncodedIds.fromSlashEncoded(name);
+
+      Instance instance = api.getInstanceApiForProject(userProject.get()).getInZone(slashEncodedIds.getFirstId(),
+              slashEncodedIds.getSecondId());
+
+      return instance == null ?  null : new InstanceInZone(instance, slashEncodedIds.getFirstId());
+   }
+
+   @Override
+   public Iterable<InstanceInZone> listNodes() {
+      return FluentIterable.from(zones.get().values()).transformAndConcat(new Function<Location, ImmutableSet<InstanceInZone>>() {
+         @Override
+         public ImmutableSet<InstanceInZone> apply(final Location input) {
+            return api.getInstanceApiForProject(userProject.get()).listInZone(input.getId()).concat()
+                    .transform(new Function<Instance, InstanceInZone>() {
+
+                       @Override
+                       public InstanceInZone apply(Instance arg0) {
+                          return new InstanceInZone(arg0, input.getId());
+                       }
+                    }).toSet();
+         }
+      }).toSet();
+   }
+
+   @Override
+   public Iterable<InstanceInZone> listNodesByIds(final Iterable<String> ids) {
+      return filter(listNodes(), new Predicate<InstanceInZone>() {
+
+         @Override
+         public boolean apply(InstanceInZone instanceInZone) {
+            return contains(ids, instanceInZone.getInstance().getName());
+         }
+      });
+   }
+
+   @Override
+   public void destroyNode(final String name) {
+      SlashEncodedIds slashEncodedIds = SlashEncodedIds.fromSlashEncoded(name);
+      String diskName = null;
+      try {
+         Instance instance = api.getInstanceApiForProject(userProject.get()).getInZone(slashEncodedIds.getFirstId(),
+                                                                              slashEncodedIds.getSecondId());
+         if (instance.getMetadata().getItems().get(GCE_DELETE_BOOT_DISK_METADATA_KEY).equals("true")) {
+            Optional<AttachedDisk> disk = tryFind(instance.getDisks(), new Predicate<AttachedDisk>() {
+               @Override
+               public boolean apply(AttachedDisk input) {
+                  return PersistentAttachedDisk.class.isInstance(input) &&
+                         PersistentAttachedDisk.class.cast(input).isBoot();
+               }
+            });
+            if (disk.isPresent()) {
+               diskName = PersistentAttachedDisk.class.cast(disk.get()).getSourceDiskName();
+            }
+         }
+      } catch (Exception e) {
+         // TODO: what exception actually gets thrown here if the instance doesn't really exist?
+      }
+      waitOperationDone(api.getInstanceApiForProject(userProject.get()).deleteInZone(slashEncodedIds.getFirstId(),
+              slashEncodedIds.getSecondId()));
+
+      if (diskName != null) {
+         waitOperationDone(api.getDiskApiForProject(userProject.get()).deleteInZone(slashEncodedIds.getFirstId(),
+                                                                                    diskName));
+      }
+
+   }
+
+   @Override
+   public void rebootNode(final String name) {
+      SlashEncodedIds slashEncodedIds = SlashEncodedIds.fromSlashEncoded(name);
+
+      waitOperationDone(api.getInstanceApiForProject(userProject.get()).resetInZone(slashEncodedIds.getFirstId(),
+              slashEncodedIds.getSecondId()));
+   }
+
+   @Override
+   public void resumeNode(String name) {
+      throw new UnsupportedOperationException("resume is not supported by GCE");
+   }
+
+   @Override
+   public void suspendNode(String name) {
+      throw new UnsupportedOperationException("suspend is not supported by GCE");
+   }
+
+   private LoginCredentials getFromImageAndOverrideIfRequired(org.jclouds.compute.domain.Image image,
+                                                              GoogleComputeEngineTemplateOptions options) {
+      LoginCredentials defaultCredentials = image.getDefaultCredentials();
+      String[] keys = defaultCredentials.getPrivateKey().split(":");
+      String publicKey = keys[0];
+      String privateKey = keys[1];
+
+      LoginCredentials.Builder credentialsBuilder = defaultCredentials.toBuilder();
+      credentialsBuilder.privateKey(privateKey);
+
+      // LoginCredentials from image stores the public key along with the private key in the privateKey field
+      // @see GoogleComputePopulateDefaultLoginCredentialsForImageStrategy
+      // so if options doesn't have a public key set we set it from the default
+      if (options.getPublicKey() == null) {
+         options.authorizePublicKey(publicKey);
+      }
+      if (options.hasLoginPrivateKeyOption()) {
+         credentialsBuilder.privateKey(options.getPrivateKey());
+      }
+      if (options.getLoginUser() != null) {
+         credentialsBuilder.identity(options.getLoginUser());
+      }
+      if (options.hasLoginPasswordOption()) {
+         credentialsBuilder.password(options.getLoginPassword());
+      }
+      if (options.shouldAuthenticateSudo() != null) {
+         credentialsBuilder.authenticateSudo(options.shouldAuthenticateSudo());
+      }
+      LoginCredentials credentials = credentialsBuilder.build();
+      options.overrideLoginCredentials(credentials);
+      return credentials;
+   }
+
+   private void waitOperationDone(Operation operation) {
+      AtomicReference<Operation> operationRef = Atomics.newReference(operation);
+
+      // wait for the operation to complete
+      if (!retryOperationDonePredicate.apply(operationRef)) {
+         throw new UncheckedTimeoutException("operation did not reach DONE state" + operationRef.get());
+      }
+
+      // check if the operation failed
+      if (operationRef.get().getHttpError().isPresent()) {
+         HttpResponse response = operationRef.get().getHttpError().get();
+         throw new IllegalStateException("operation failed. Http Error Code: " + response.getStatusCode() +
+                 " HttpError: " + response.getMessage());
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/stratos/blob/b45ae00e/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java
new file mode 100644
index 0000000..730c515
--- /dev/null
+++ b/dependencies/jclouds/apis/gce/1.8.1-stratos/src/main/java/org/jclouds/googlecomputeengine/compute/config/GoogleComputeEngineServiceContextModule.java
@@ -0,0 +1,283 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.jclouds.googlecomputeengine.compute.config;
+
+import static com.google.common.collect.Iterables.transform;
+import static com.google.common.collect.Maps.uniqueIndex;
+import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import com.google.inject.Scopes;
+import org.jclouds.collect.Memoized;
+import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.ComputeServiceAdapter;
+import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.SecurityGroup;
+import org.jclouds.compute.extensions.ImageExtension;
+import org.jclouds.compute.extensions.SecurityGroupExtension;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate;
+import org.jclouds.domain.Location;
+import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
+import org.jclouds.googlecomputeengine.compute.GoogleComputeEngineService;
+import org.jclouds.googlecomputeengine.compute.GoogleComputeEngineServiceAdapter;
+import org.jclouds.googlecomputeengine.compute.extensions.GoogleComputeEngineSecurityGroupExtension;
+import org.jclouds.googlecomputeengine.compute.functions.BuildInstanceMetadata;
+import org.jclouds.googlecomputeengine.compute.functions.FirewallTagNamingConvention;
+import org.jclouds.googlecomputeengine.compute.functions.FirewallToIpPermission;
+import org.jclouds.googlecomputeengine.compute.functions.GoogleComputeEngineImageToImage;
+import org.jclouds.googlecomputeengine.compute.functions.InstanceInZoneToNodeMetadata;
+import org.jclouds.googlecomputeengine.compute.functions.MachineTypeInZoneToHardware;
+import org.jclouds.googlecomputeengine.compute.functions.NetworkToSecurityGroup;
+import org.jclouds.googlecomputeengine.compute.functions.OrphanedGroupsFromDeadNodes;
+import org.jclouds.googlecomputeengine.compute.functions.RegionToLocation;
+import org.jclouds.googlecomputeengine.compute.functions.ZoneToLocation;
+import org.jclouds.googlecomputeengine.compute.loaders.FindNetworkOrCreate;
+import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions;
+import org.jclouds.googlecomputeengine.compute.predicates.AllNodesInGroupTerminated;
+import org.jclouds.googlecomputeengine.compute.strategy.CreateNodesWithGroupEncodedIntoNameThenAddToSet;
+import org.jclouds.googlecomputeengine.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
+import org.jclouds.googlecomputeengine.compute.strategy.UseNodeCredentialsButOverrideFromTemplate;
+import org.jclouds.googlecomputeengine.config.UserProject;
+import org.jclouds.googlecomputeengine.domain.Firewall;
+import org.jclouds.googlecomputeengine.domain.Image;
+import org.jclouds.googlecomputeengine.domain.Instance;
+import org.jclouds.googlecomputeengine.domain.InstanceInZone;
+import org.jclouds.googlecomputeengine.domain.MachineTypeInZone;
+import org.jclouds.googlecomputeengine.domain.Network;
+import org.jclouds.googlecomputeengine.domain.Region;
+import org.jclouds.googlecomputeengine.domain.Zone;
+import org.jclouds.googlecomputeengine.domain.internal.NetworkAndAddressRange;
+import org.jclouds.googlecomputeengine.functions.CreateNetworkIfNeeded;
+import org.jclouds.net.domain.IpPermission;
+import org.jclouds.rest.AuthorizationException;
+import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.Injector;
+import com.google.inject.Provides;
+import com.google.inject.TypeLiteral;
+
+public class GoogleComputeEngineServiceContextModule
+        extends ComputeServiceAdapterContextModule<InstanceInZone, MachineTypeInZone, Image, Zone> {
+
+   @Override
+   protected void configure() {
+      super.configure();
+
+      bind(ComputeService.class).to(GoogleComputeEngineService.class);
+
+      bind(new TypeLiteral<ComputeServiceAdapter<InstanceInZone, MachineTypeInZone, Image, Zone>>() {})
+              .to(GoogleComputeEngineServiceAdapter.class);
+
+      bind(new TypeLiteral<Function<InstanceInZone, NodeMetadata>>() {})
+              .to(InstanceInZoneToNodeMetadata.class);
+
+      bind(new TypeLiteral<Function<MachineTypeInZone, Hardware>>() {})
+              .to(MachineTypeInZoneToHardware.class);
+
+      bind(new TypeLiteral<Function<Image, org.jclouds.compute.domain.Image>>() {})
+              .to(GoogleComputeEngineImageToImage.class);
+
+      bind(new TypeLiteral<Function<Region, Location>>() {
+      })
+              .to(RegionToLocation.class);
+
+      bind(new TypeLiteral<Function<Zone, Location>>() {})
+              .to(ZoneToLocation.class);
+
+      bind(new TypeLiteral<Function<Firewall, Iterable<IpPermission>>>() {})
+              .to(FirewallToIpPermission.class);
+
+      bind(new TypeLiteral<Function<Network, SecurityGroup>>() {})
+              .to(NetworkToSecurityGroup.class);
+
+      bind(new TypeLiteral<Function<TemplateOptions, ImmutableMap.Builder<String, String>>>() {})
+              .to(BuildInstanceMetadata.class);
+
+      bind(org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy.class)
+              .to(PopulateDefaultLoginCredentialsForImageStrategy.class);
+
+      bind(org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet.class).to(
+              CreateNodesWithGroupEncodedIntoNameThenAddToSet.class);
+
+      bind(TemplateOptions.class).to(GoogleComputeEngineTemplateOptions.class);
+
+      bind(new TypeLiteral<Function<Set<? extends NodeMetadata>, Set<String>>>() {})
+              .to(OrphanedGroupsFromDeadNodes.class);
+
+      bind(new TypeLiteral<Predicate<String>>() {}).to(AllNodesInGroupTerminated.class);
+
+      bind(new TypeLiteral<Function<NetworkAndAddressRange, Network>>() {})
+              .to(CreateNetworkIfNeeded.class);
+
+      bind(new TypeLiteral<CacheLoader<NetworkAndAddressRange, Network>>() {})
+              .to(FindNetworkOrCreate.class);
+
+      bind(new TypeLiteral<SecurityGroupExtension>() {})
+              .to(GoogleComputeEngineSecurityGroupExtension.class);
+
+      bind(PrioritizeCredentialsFromTemplate.class).to(UseNodeCredentialsButOverrideFromTemplate.class);
+
+      install(new LocationsFromComputeServiceAdapterModule<InstanceInZone, MachineTypeInZone, Image, Zone>() {});
+
+      bind(FirewallTagNamingConvention.Factory.class).in(Scopes.SINGLETON);
+   }
+
+   @Provides
+   @Singleton
+   @Memoized
+   public Supplier<Map<URI, ? extends org.jclouds.compute.domain.Image>> provideImagesMap(
+           AtomicReference<AuthorizationException> authException,
+           final Supplier<Set<? extends org.jclouds.compute.domain.Image>> images,
+           @Named(PROPERTY_SESSION_INTERVAL) long seconds) {
+      return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException,
+              new Supplier<Map<URI, ? extends org.jclouds.compute.domain.Image>>() {
+                 @Override
+                 public Map<URI, ? extends org.jclouds.compute.domain.Image> get() {
+                    return uniqueIndex(images.get(), new Function<org.jclouds.compute.domain.Image, URI>() {
+                       @Override
+                       public URI apply(org.jclouds.compute.domain.Image input) {
+                          return input.getUri();
+                       }
+                    });
+                 }
+              },
+              seconds, TimeUnit.SECONDS);
+   }
+
+   @Provides
+   @Singleton
+   @Memoized
+   public Supplier<Map<URI, ? extends Hardware>> provideHardwaresMap(
+           AtomicReference<AuthorizationException> authException,
+           final Supplier<Set<? extends Hardware>> hardwares,
+           @Named(PROPERTY_SESSION_INTERVAL) long seconds) {
+      return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException,
+              new Supplier<Map<URI, ? extends Hardware>>() {
+                 @Override
+                 public Map<URI, ? extends Hardware> get() {
+                    return uniqueIndex(hardwares.get(), new Function<Hardware, URI>() {
+                       @Override
+                       public URI apply(Hardware input) {
+                          return input.getUri();
+                       }
+                    });
+                 }
+              },
+              seconds, TimeUnit.SECONDS);
+   }
+
+   @Provides
+   @Singleton
+   @Memoized
+   public Supplier<Map<URI, ? extends Location>> provideZones(
+           AtomicReference<AuthorizationException> authException,
+           final GoogleComputeEngineApi api, final Function<Zone, Location> zoneToLocation,
+           @UserProject final Supplier<String> userProject,
+           @Named(PROPERTY_SESSION_INTERVAL) long seconds) {
+      return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException,
+              new Supplier<Map<URI, ? extends Location>>() {
+                 @Override
+                 public Map<URI, ? extends Location> get() {
+                    return uniqueIndex(transform(api.getZoneApiForProject(userProject.get()).list().concat(), zoneToLocation),
+                            new Function<Location, URI>() {
+                               @Override
+                               public URI apply(Location input) {
+                                  return (URI) input.getMetadata().get("selfLink");
+                               }
+                            });
+                 }
+              },
+              seconds, TimeUnit.SECONDS);
+   }
+
+   @Provides
+   @Singleton
+   @Memoized
+   public Supplier<Map<URI, Region>> provideRegions(
+           AtomicReference<AuthorizationException> authException,
+           final GoogleComputeEngineApi api,
+           @UserProject final Supplier<String> userProject,
+           @Named(PROPERTY_SESSION_INTERVAL) long seconds) {
+      return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException,
+              new Supplier<Map<URI, Region>>() {
+                 @Override
+                 public Map<URI, Region> get() {
+                    return uniqueIndex(api.getRegionApiForProject(userProject.get()).list().concat(),
+                            new Function<Region, URI>() {
+                               @Override
+                               public URI apply(Region input) {
+                                  return input.getSelfLink();
+                               }
+                            });
+                 }
+              },
+              seconds, TimeUnit.SECONDS);
+   }
+
+   @Provides
+   @Singleton
+   protected LoadingCache<NetworkAndAddressRange, Network> networkMap(
+           CacheLoader<NetworkAndAddressRange, Network> in) {
+      return CacheBuilder.newBuilder().build(in);
+   }
+
+   @Override
+   protected Optional<ImageExtension> provideImageExtension(Injector i) {
+      return Optional.absent();
+   }
+
+   @Override
+   protected Optional<SecurityGroupExtension> provideSecurityGroupExtension(Injector i) {
+      return Optional.of(i.getInstance(SecurityGroupExtension.class));
+   }
+
+   @VisibleForTesting
+   public static final Map<Instance.Status, NodeMetadata.Status> toPortableNodeStatus =
+           ImmutableMap.<Instance.Status, NodeMetadata.Status>builder()
+                   .put(Instance.Status.PROVISIONING, NodeMetadata.Status.PENDING)
+                   .put(Instance.Status.STAGING, NodeMetadata.Status.PENDING)
+                   .put(Instance.Status.RUNNING, NodeMetadata.Status.RUNNING)
+                   .put(Instance.Status.STOPPING, NodeMetadata.Status.PENDING)
+                   .put(Instance.Status.STOPPED, NodeMetadata.Status.SUSPENDED)
+                   .put(Instance.Status.TERMINATED, NodeMetadata.Status.TERMINATED).build();
+
+   @Singleton
+   @Provides
+   protected Map<Instance.Status, NodeMetadata.Status> toPortableNodeStatus() {
+      return toPortableNodeStatus;
+   }
+}