You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@whirr.apache.org by to...@apache.org on 2010/08/09 23:56:15 UTC

svn commit: r983834 - in /incubator/whirr/trunk: ./ core/src/main/java/org/jclouds/ core/src/main/java/org/jclouds/aws/ core/src/main/java/org/jclouds/aws/ec2/ core/src/main/java/org/jclouds/aws/ec2/compute/ core/src/main/java/org/jclouds/aws/ec2/compu...

Author: tomwhite
Date: Mon Aug  9 21:56:14 2010
New Revision: 983834

URL: http://svn.apache.org/viewvc?rev=983834&view=rev
Log:
Workaround bug 331 in jclouds (Some EC2ComputeService operations fail for stopped instances)

Added:
    incubator/whirr/trunk/core/src/main/java/org/jclouds/
    incubator/whirr/trunk/core/src/main/java/org/jclouds/aws/
    incubator/whirr/trunk/core/src/main/java/org/jclouds/aws/ec2/
    incubator/whirr/trunk/core/src/main/java/org/jclouds/aws/ec2/compute/
    incubator/whirr/trunk/core/src/main/java/org/jclouds/aws/ec2/compute/functions/
    incubator/whirr/trunk/core/src/main/java/org/jclouds/aws/ec2/compute/functions/RunningInstanceToNodeMetadata.java   (with props)
Modified:
    incubator/whirr/trunk/CHANGES.txt

Modified: incubator/whirr/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/CHANGES.txt?rev=983834&r1=983833&r2=983834&view=diff
==============================================================================
--- incubator/whirr/trunk/CHANGES.txt (original)
+++ incubator/whirr/trunk/CHANGES.txt Mon Aug  9 21:56:14 2010
@@ -42,3 +42,6 @@ Trunk (unreleased changes)
     WHIRR-50. Cassandra POM should depend on top-level. (tomwhite)
 
     WHIRR-48. Fix RAT warnings due to site files. (tomwhite)
+
+    WHIRR-65. Workaround bug 331 in jclouds (Some EC2ComputeService operations
+    fail for stopped instances). (tomwhite)

Added: incubator/whirr/trunk/core/src/main/java/org/jclouds/aws/ec2/compute/functions/RunningInstanceToNodeMetadata.java
URL: http://svn.apache.org/viewvc/incubator/whirr/trunk/core/src/main/java/org/jclouds/aws/ec2/compute/functions/RunningInstanceToNodeMetadata.java?rev=983834&view=auto
==============================================================================
--- incubator/whirr/trunk/core/src/main/java/org/jclouds/aws/ec2/compute/functions/RunningInstanceToNodeMetadata.java (added)
+++ incubator/whirr/trunk/core/src/main/java/org/jclouds/aws/ec2/compute/functions/RunningInstanceToNodeMetadata.java Mon Aug  9 21:56:14 2010
@@ -0,0 +1,195 @@
+/**
+ *
+ * Copyright (C) 2009 Cloud Conscious, LLC. <in...@cloudconscious.com>
+ *
+ * ====================================================================
+ * 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.
+ * ====================================================================
+ */
+package org.jclouds.aws.ec2.compute.functions;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.util.Utils.nullSafeSet;
+
+import java.net.InetAddress;
+import java.net.URI;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.aws.ec2.compute.domain.RegionTag;
+import org.jclouds.aws.ec2.domain.InstanceState;
+import org.jclouds.aws.ec2.domain.KeyPair;
+import org.jclouds.aws.ec2.domain.RunningInstance;
+import org.jclouds.aws.ec2.options.DescribeImagesOptions;
+import org.jclouds.aws.ec2.services.AMIClient;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.NodeState;
+import org.jclouds.compute.domain.internal.NodeMetadataImpl;
+import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
+import org.jclouds.domain.Credentials;
+import org.jclouds.domain.Location;
+import org.jclouds.logging.Logger;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
+
+/**
+ * @author Adrian Cole
+ */
+@Singleton
+public class RunningInstanceToNodeMetadata implements Function<RunningInstance, NodeMetadata> {
+
+   @Resource
+   protected Logger logger = Logger.NULL;
+
+   private static class FindImageForInstance implements Predicate<Image> {
+      private final Location location;
+      private final RunningInstance instance;
+
+      private FindImageForInstance(Location location, RunningInstance instance) {
+         this.location = location;
+         this.instance = instance;
+      }
+
+      @Override
+      public boolean apply(Image input) {
+         return input.getId().equals(instance.getImageId())
+                  && (input.getLocation() == null || input.getLocation().equals(location) || input
+                           .getLocation().equals(location.getParent()));
+      }
+   }
+
+   private static final Map<InstanceState, NodeState> instanceToNodeState = ImmutableMap
+            .<InstanceState, NodeState> builder().put(InstanceState.PENDING, NodeState.PENDING).put(
+                     InstanceState.RUNNING, NodeState.RUNNING).put(InstanceState.SHUTTING_DOWN, NodeState.PENDING).put(
+                     InstanceState.TERMINATED, NodeState.TERMINATED).put(
+                     InstanceState.STOPPING, NodeState.PENDING).put(
+                     InstanceState.STOPPED, NodeState.SUSPENDED).build();
+
+   private final AMIClient amiClient;
+   private final Map<RegionTag, KeyPair> credentialsMap;
+   private final PopulateDefaultLoginCredentialsForImageStrategy credentialProvider;
+   private final Set<? extends Image> images;
+   private final Set<? extends Location> locations;
+   private final Function<RunningInstance, Map<String, String>> instanceToStorageMapping;
+
+   @Inject
+   RunningInstanceToNodeMetadata(
+            AMIClient amiClient,
+            Map<RegionTag, KeyPair> credentialsMap,
+            PopulateDefaultLoginCredentialsForImageStrategy credentialProvider,
+            Set<? extends Image> images,
+            Set<? extends Location> locations,
+            @Named("volumeMapping") Function<RunningInstance, Map<String, String>> instanceToStorageMapping) {
+      this.amiClient = checkNotNull(amiClient, "amiClient");
+      this.credentialsMap = checkNotNull(credentialsMap, "credentialsMap");
+      this.credentialProvider = checkNotNull(credentialProvider, "credentialProvider");
+      this.images = checkNotNull(images, "images");
+      this.locations = checkNotNull(locations, "locations");
+      this.instanceToStorageMapping = checkNotNull(instanceToStorageMapping);
+   }
+
+   @Override
+   public NodeMetadata apply(final RunningInstance instance) {
+      String id = checkNotNull(instance, "instance").getId();
+      String name = null; // user doesn't determine a node name;
+      URI uri = null; // no uri to get rest access to host info
+
+      Credentials credentials = null;// default if no keypair exists
+      String tag = String.format("NOTAG-%s", instance.getId());// default if no keypair exists
+
+      if (instance.getKeyName() != null) {
+         tag = instance.getKeyName().replaceAll("-[0-9]+", "");
+         credentials = new Credentials(getLoginAccountFor(instance), getPrivateKeyOrNull(instance,
+                  tag));
+      }
+
+      Map<String, String> userMetadata = ImmutableMap.<String, String> of();
+
+      NodeState state = instanceToNodeState.get(instance.getInstanceState());
+
+      Set<InetAddress> publicAddresses = nullSafeSet(instance.getIpAddress());
+      Set<InetAddress> privateAddresses = nullSafeSet(instance.getPrivateIpAddress());
+
+      final String locationId = instance.getAvailabilityZone();
+
+      Map<String, String> extra = getExtra(instance);
+
+      final Location location = Iterables.find(locations, new Predicate<Location>() {
+
+         @Override
+         public boolean apply(Location input) {
+            return input.getId().equals(locationId);
+         }
+
+      });
+
+      Image image = null;
+      try {
+         image = Iterables.find(images, new FindImageForInstance(location, instance));
+      } catch (NoSuchElementException e) {
+         logger.warn("could not find a matching image for instance %s in location %s", instance,
+                  location);
+      }
+      return new NodeMetadataImpl(id, name, location, uri, userMetadata, tag, image, state,
+               publicAddresses, privateAddresses, extra, credentials);
+   }
+
+   /**
+    * Set extras for the node.
+    * 
+    * Extras are derived from either additional API calls or hard-coded values.
+    * 
+    * @param instance
+    *           instance for which the extras are retrieved
+    * @return map with extras
+    */
+   @VisibleForTesting
+   Map<String, String> getExtra(RunningInstance instance) {
+      Map<String, String> extra = Maps.newHashMap();
+
+      // put storage info
+      /* TODO: only valid for UNIX */
+      extra.putAll(instanceToStorageMapping.apply(instance));
+
+      return extra;
+   }
+
+   @VisibleForTesting
+   String getPrivateKeyOrNull(RunningInstance instance, String tag) {
+      KeyPair keyPair = credentialsMap.get(new RegionTag(instance.getRegion(), instance
+               .getKeyName()));
+      return keyPair != null ? keyPair.getKeyMaterial() : null;
+   }
+
+   @VisibleForTesting
+   String getLoginAccountFor(RunningInstance from) {
+      org.jclouds.aws.ec2.domain.Image image = Iterables.getOnlyElement(amiClient
+               .describeImagesInRegion(from.getRegion(), DescribeImagesOptions.Builder
+                        .imageIds(from.getImageId())));
+      return checkNotNull(credentialProvider.execute(image), "login from image: "
+               + from.getImageId()).account;
+   }
+
+}
\ No newline at end of file

Propchange: incubator/whirr/trunk/core/src/main/java/org/jclouds/aws/ec2/compute/functions/RunningInstanceToNodeMetadata.java
------------------------------------------------------------------------------
    svn:eol-style = native