You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by na...@apache.org on 2014/07/09 17:43:14 UTC

[1/2] git commit: JCLOUDS-607: ComputeService.createNodesInGroup throws NPE on FloatingIPApi.create()

Repository: jclouds
Updated Branches:
  refs/heads/1.7.x f52a264b8 -> e94b878b2


JCLOUDS-607: ComputeService.createNodesInGroup throws NPE on FloatingIPApi.create()


Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/7641bd61
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/7641bd61
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/7641bd61

Branch: refs/heads/1.7.x
Commit: 7641bd61cd56f7f5a4da5ac89769c1d200abe79f
Parents: f52a264
Author: Christopher Dancy <da...@pega.com>
Authored: Mon Jun 30 16:01:43 2014 -0400
Committer: Ignasi Barrera <na...@apache.org>
Committed: Wed Jul 9 17:26:57 2014 +0200

----------------------------------------------------------------------
 .../AllocateAndAddFloatingIpToNode.java         | 95 ++++++++++++++------
 .../options/NodeAndNovaTemplateOptions.java     | 54 +++++++++++
 .../compute/options/NovaTemplateOptions.java    | 57 +++++++++++-
 ...desWithGroupEncodedIntoNameThenAddToSet.java | 19 +++-
 ...llocateAndAddFloatingIpToNodeExpectTest.java | 56 +++++++++++-
 .../rest/InsufficientResourcesException.java    |  6 +-
 6 files changed, 248 insertions(+), 39 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/7641bd61/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/AllocateAndAddFloatingIpToNode.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/AllocateAndAddFloatingIpToNode.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/AllocateAndAddFloatingIpToNode.java
index f7c18ee..e1801b9 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/AllocateAndAddFloatingIpToNode.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/AllocateAndAddFloatingIpToNode.java
@@ -19,8 +19,9 @@ import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
 import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
 
-import java.util.ArrayList;
 import java.util.Collections;
+import java.util.List;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicReference;
 
 import javax.annotation.Resource;
@@ -32,6 +33,7 @@ import org.jclouds.compute.domain.NodeMetadataBuilder;
 import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.logging.Logger;
 import org.jclouds.openstack.nova.v2_0.NovaApi;
+import org.jclouds.openstack.nova.v2_0.compute.options.NodeAndNovaTemplateOptions;
 import org.jclouds.openstack.nova.v2_0.domain.FloatingIP;
 import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndId;
 import org.jclouds.openstack.nova.v2_0.extensions.FloatingIPApi;
@@ -39,6 +41,7 @@ import org.jclouds.rest.InsufficientResourcesException;
 
 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.cache.LoadingCache;
 import com.google.common.collect.ImmutableSet;
@@ -51,7 +54,7 @@ import com.google.common.collect.Lists;
  * @author Adrian Cole
  */
 public class AllocateAndAddFloatingIpToNode implements
-         Function<AtomicReference<NodeMetadata>, AtomicReference<NodeMetadata>> {
+         Function<AtomicReference<NodeAndNovaTemplateOptions>, AtomicReference<NodeMetadata>> {
 
    @Resource
    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
@@ -70,41 +73,79 @@ public class AllocateAndAddFloatingIpToNode implements
    }
 
    @Override
-   public AtomicReference<NodeMetadata> apply(AtomicReference<NodeMetadata> input) {
-      checkState(nodeRunning.apply(input), "node never achieved state running %s", input.get());
-      NodeMetadata node = input.get();
+   public AtomicReference<NodeMetadata> apply(AtomicReference<NodeAndNovaTemplateOptions> input) {
+      checkState(nodeRunning.apply(input.get().getNodeMetadata()), "node never achieved state running %s", input.get().getNodeMetadata());
+      NodeMetadata node = input.get().getNodeMetadata().get();
       // node's location is a host
       String zoneId = node.getLocation().getParent().getId();
       FloatingIPApi floatingIpApi = novaApi.getFloatingIPExtensionForZone(zoneId).get();
+      Optional<Set<String>> poolNames = input.get().getNovaTemplateOptions().get().getFloatingIpPoolNames();
+            
+      Optional<FloatingIP> ip = allocateFloatingIPForNode(floatingIpApi, poolNames, node.getId());
+      if (!ip.isPresent()) {
+         throw new InsufficientResourcesException("Failed to allocate a FloatingIP for node(" + node.getId() + ")");
+      }
+      logger.debug(">> adding floatingIp(%s) to node(%s)", ip.get().getIp(), node.getId());
 
+      floatingIpApi.addToServer(ip.get().getIp(), node.getProviderId());
+      input.get().getNodeMetadata().set(NodeMetadataBuilder.fromNodeMetadata(node).publicAddresses(ImmutableSet.of(ip.get().getIp())).build());
+      floatingIpCache.invalidate(ZoneAndId.fromSlashEncoded(node.getId()));
+      return input.get().getNodeMetadata();
+   }
+
+   /**
+    * Allocates a FloatingIP for a given Node
+    * 
+    * @param floatingIpApi FloatingIPApi to create or query for a valid FloatingIP
+    * @param poolNames optional set of pool names from which we will attempt to allocate an IP from. Most cases this is null
+    * @param nodeID optional id of the Node we are trying to allocate a FloatingIP for. Used here only for logging purposes
+    * @return Optional<FloatingIP> 
+    */
+   private Optional<FloatingIP> allocateFloatingIPForNode(FloatingIPApi floatingIpApi, Optional<Set<String>> poolNames, String nodeID) {
+	   
       FloatingIP ip = null;
+      
+      // 1.) Attempt to allocate from optionally passed poolNames
+      if (poolNames.isPresent()) {
+         for (String poolName : poolNames.get()){
+            try {
+               logger.debug(">> allocating floating IP from pool %s for node(%s)", poolName, nodeID);
+               ip = floatingIpApi.allocateFromPool(poolName);
+               if (ip != null)
+                  return Optional.of(ip);
+            } catch (InsufficientResourcesException ire){
+               logger.trace("<< [%s] failed to allocate floating IP from pool %s for node(%s)", ire.getMessage(), poolName, nodeID);
+            }
+         }
+      }
+      
+      // 2.) Attempt to allocate, if necessary, via 'create()' call
       try {
-         logger.debug(">> allocating or reassigning floating ip for node(%s)", node.getId());
+         logger.debug(">> creating floating IP for node(%s)", nodeID);
          ip = floatingIpApi.create();
-      } catch (InsufficientResourcesException e) {
-         logger.trace("<< [%s] allocating a new floating ip for node(%s)", e.getMessage(), node.getId());
-         logger.trace(">> searching for existing, unassigned floating ip for node(%s)", node.getId());
-         ArrayList<FloatingIP> unassignedIps = Lists.newArrayList(Iterables.filter(floatingIpApi.list(),
-                  new Predicate<FloatingIP>() {
-
-                     @Override
-                     public boolean apply(FloatingIP arg0) {
-                        return arg0.getFixedIp() == null;
-                     }
-
-                  }));
-         // try to prevent multiple parallel launches from choosing the same ip.
-         Collections.shuffle(unassignedIps);
-         ip = Iterables.getLast(unassignedIps);
+         if(ip != null)
+            return Optional.of(ip);
+      } catch (InsufficientResourcesException ire){
+         logger.trace("<< [%s] failed to create floating IP for node(%s)", ire.getMessage(), nodeID);
       }
-      logger.debug(">> adding floatingIp(%s) to node(%s)", ip.getIp(), node.getId());
+      
+      // 3.) If no IP was found make final attempt by searching through list of available IP's
+      logger.trace(">> searching for existing, unassigned floating IP for node(%s)", nodeID);
+      List<FloatingIP> unassignedIps = Lists.newArrayList(Iterables.filter(floatingIpApi.list(),
+            new Predicate<FloatingIP>() {
 
-      floatingIpApi.addToServer(ip.getIp(), node.getProviderId());
-      input.set(NodeMetadataBuilder.fromNodeMetadata(node).publicAddresses(ImmutableSet.of(ip.getIp())).build());
-      floatingIpCache.invalidate(ZoneAndId.fromSlashEncoded(node.getId()));
-      return input;
-   }
+               @Override
+               public boolean apply(FloatingIP arg0) {
+                  return arg0.getFixedIp() == null;
+               }
 
+      }));
+      // try to prevent multiple parallel launches from choosing the same ip.
+      Collections.shuffle(unassignedIps);
+      ip = Iterables.getLast(unassignedIps);
+      return Optional.fromNullable(ip);
+   }
+   
    @Override
    public String toString() {
       return Objects.toStringHelper("AllocateAndAddFloatingIpToNode").toString();

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7641bd61/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NodeAndNovaTemplateOptions.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NodeAndNovaTemplateOptions.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NodeAndNovaTemplateOptions.java
new file mode 100644
index 0000000..d95e817
--- /dev/null
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NodeAndNovaTemplateOptions.java
@@ -0,0 +1,54 @@
+/*
+ * 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.openstack.nova.v2_0.compute.options;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.jclouds.compute.domain.NodeMetadata;
+
+import com.google.common.util.concurrent.Atomics;
+
+/**
+ * Simple data-structure for holding a NodeMetadata object along with a 
+ * corresponding NovaTemplateOptions object.
+ */
+public class NodeAndNovaTemplateOptions {
+
+   private final AtomicReference<NodeMetadata> nodeMetadata;
+   private final AtomicReference<NovaTemplateOptions> novaTemplateOptions;
+   
+   protected NodeAndNovaTemplateOptions(AtomicReference<NodeMetadata> nodeMetadata, AtomicReference<NovaTemplateOptions> novaTemplateOptions){
+      this.nodeMetadata = nodeMetadata;
+      this.novaTemplateOptions = novaTemplateOptions;
+   }
+
+   public AtomicReference<NodeMetadata> getNodeMetadata() {
+      return nodeMetadata;
+   }
+
+   public AtomicReference<NovaTemplateOptions> getNovaTemplateOptions() {
+      return novaTemplateOptions;
+   }
+   
+   public static NodeAndNovaTemplateOptions newReference(AtomicReference<NodeMetadata> node, AtomicReference<NovaTemplateOptions> options){
+      return new NodeAndNovaTemplateOptions(node, options);
+   }
+   
+   public static AtomicReference<NodeAndNovaTemplateOptions> newAtomicReference(AtomicReference<NodeMetadata> node, AtomicReference<NovaTemplateOptions> options){
+      return Atomics.newReference(NodeAndNovaTemplateOptions.newReference(node, options));
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7641bd61/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptions.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptions.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptions.java
index 24328b8..4e6ce2e 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptions.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/options/NovaTemplateOptions.java
@@ -66,6 +66,8 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
       if (to instanceof NovaTemplateOptions) {
          NovaTemplateOptions eTo = NovaTemplateOptions.class.cast(to);
          eTo.autoAssignFloatingIp(shouldAutoAssignFloatingIp());
+         if (getFloatingIpPoolNames().isPresent())
+            eTo.floatingIpPoolNames(getFloatingIpPoolNames().get());
          if (getSecurityGroupNames().isPresent())
             eTo.securityGroupNames(getSecurityGroupNames().get());
          eTo.generateKeyPair(shouldGenerateKeyPair());
@@ -83,6 +85,7 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
    }
 
    protected boolean autoAssignFloatingIp = false;
+   protected Optional<Set<String>> floatingIpPoolNames = Optional.absent();
    protected Optional<Set<String>> securityGroupNames = Optional.absent();
    protected boolean generateKeyPair = false;
    protected String keyPairName;
@@ -99,6 +102,7 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
          return false;
       NovaTemplateOptions that = NovaTemplateOptions.class.cast(o);
       return super.equals(that) && equal(this.autoAssignFloatingIp, that.autoAssignFloatingIp)
+            && equal(this.floatingIpPoolNames, that.floatingIpPoolNames)
             && equal(this.securityGroupNames, that.securityGroupNames)
             && equal(this.generateKeyPair, that.generateKeyPair)
             && equal(this.keyPairName, that.keyPairName)
@@ -110,7 +114,7 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
 
    @Override
    public int hashCode() {
-      return Objects.hashCode(super.hashCode(), autoAssignFloatingIp, securityGroupNames, generateKeyPair, keyPairName, userData, diskConfig, configDrive, novaNetworks);
+      return Objects.hashCode(super.hashCode(), autoAssignFloatingIp, floatingIpPoolNames, securityGroupNames, generateKeyPair, keyPairName, userData, diskConfig, configDrive, novaNetworks);
    }
 
    @Override
@@ -118,6 +122,8 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
       ToStringHelper toString = super.string();
       if (!autoAssignFloatingIp)
          toString.add("autoAssignFloatingIp", autoAssignFloatingIp);
+      if (floatingIpPoolNames.isPresent())
+         toString.add("floatingIpPoolNames", floatingIpPoolNames.get());
       if (securityGroupNames.isPresent())
          toString.add("securityGroupNames", securityGroupNames.get());
       if (generateKeyPair)
@@ -133,12 +139,29 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
    public static final NovaTemplateOptions NONE = new NovaTemplateOptions();
 
    /**
-    * @see #shouldAutoAssignFloatingIp()
+    * @see #getFloatingIpPoolNames()
     */
    public NovaTemplateOptions autoAssignFloatingIp(boolean enable) {
       this.autoAssignFloatingIp = enable;
       return this;
    }
+   
+   /**
+    * @see #getFloatingIpPoolNames()
+    */
+   public NovaTemplateOptions floatingIpPoolNames(String... floatingIpPoolNames) {
+      return floatingIpPoolNames(ImmutableSet.copyOf(checkNotNull(floatingIpPoolNames, "floatingIpPoolNames")));
+   }
+
+   /**
+    * @see #getFloatingIpPoolNames()
+    */
+   public NovaTemplateOptions floatingIpPoolNames(Iterable<String> floatingIpPoolNames) {
+      for (String groupName : checkNotNull(floatingIpPoolNames, "floatingIpPoolNames"))
+        checkNotNull(emptyToNull(groupName), "all floating-ip-pool-names must be non-empty");
+      this.floatingIpPoolNames = Optional.<Set<String>> of(ImmutableSet.copyOf(floatingIpPoolNames));
+      return this;
+   }
 
    /**
     * @see #shouldGenerateKeyPair()
@@ -187,13 +210,25 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
    }
 
    /**
+    * The floating IP pool name(s) to use when allocating a FloatingIP. Applicable
+    * only if #shouldAutoAssignFloatingIp() returns true. If not set will attempt to 
+    * use whatever FloatingIP(s) can be found regardless of which pool they originated 
+    * from
+    * 
+    * @return floating-ip-pool names to use
+    */
+   public Optional<Set<String>> getFloatingIpPoolNames() {
+      return floatingIpPoolNames;
+   }   
+   
+   /**
     * Specifies the keypair used to run instances with
     * @return the keypair to be used
     */
    public String getKeyPairName() {
       return keyPairName;
    }
-
+   
    /**
     * <h3>Note</h3>
     *
@@ -251,6 +286,22 @@ public class NovaTemplateOptions extends TemplateOptions implements Cloneable {
       }
 
       /**
+       * @see #getFloatingIpPoolNames()
+       */
+      public NovaTemplateOptions floatingIpPoolNames(String... floatingIpPoolNames) {
+         NovaTemplateOptions options = new NovaTemplateOptions();
+         return NovaTemplateOptions.class.cast(options.floatingIpPoolNames(floatingIpPoolNames));         
+      }
+
+      /**
+       * @see #getFloatingIpPoolNames()
+       */
+      public NovaTemplateOptions floatingIpPoolNames(Iterable<String> floatingIpPoolNames) {
+         NovaTemplateOptions options = new NovaTemplateOptions();
+         return NovaTemplateOptions.class.cast(options.floatingIpPoolNames(floatingIpPoolNames)); 
+      }     
+      
+      /**
        * @see NovaTemplateOptions#shouldGenerateKeyPair() 
        */
       public static NovaTemplateOptions generateKeyPair(boolean enable) {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7641bd61/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/strategy/ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/strategy/ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/strategy/ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.java
index e3ea4cc..2ba160c 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/strategy/ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/strategy/ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.java
@@ -42,16 +42,19 @@ import org.jclouds.compute.strategy.ListNodesStrategy;
 import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet;
 import org.jclouds.openstack.nova.v2_0.NovaApi;
 import org.jclouds.openstack.nova.v2_0.compute.functions.AllocateAndAddFloatingIpToNode;
+import org.jclouds.openstack.nova.v2_0.compute.options.NodeAndNovaTemplateOptions;
 import org.jclouds.openstack.nova.v2_0.compute.options.NovaTemplateOptions;
 import org.jclouds.openstack.nova.v2_0.domain.KeyPair;
 import org.jclouds.openstack.nova.v2_0.domain.zonescoped.SecurityGroupInZone;
 import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneAndName;
 import org.jclouds.openstack.nova.v2_0.domain.zonescoped.ZoneSecurityGroupNameAndPorts;
 
+import com.google.common.base.Function;
 import com.google.common.base.Throwables;
 import com.google.common.cache.LoadingCache;
 import com.google.common.collect.Multimap;
 import com.google.common.primitives.Ints;
+import com.google.common.util.concurrent.Atomics;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
@@ -153,13 +156,21 @@ public class ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddT
             final String name, Template template) {
 
       ListenableFuture<AtomicReference<NodeMetadata>> future = super.createNodeInGroupWithNameAndTemplate(group, name, template);
-      NovaTemplateOptions templateOptions = NovaTemplateOptions.class.cast(template.getOptions());
-
+      final NovaTemplateOptions templateOptions = NovaTemplateOptions.class.cast(template.getOptions());
       if (templateOptions.shouldAutoAssignFloatingIp()) {
-         return Futures.transform(future, createAndAddFloatingIpToNode, userExecutor);
+         
+         ListenableFuture<AtomicReference<NodeAndNovaTemplateOptions>> nodeAndNovaTemplateOptions = Futures.transform(future, 
+               new Function<AtomicReference<NodeMetadata>, AtomicReference<NodeAndNovaTemplateOptions>>(){
+
+                  @Override
+                  public AtomicReference<NodeAndNovaTemplateOptions> apply(AtomicReference<NodeMetadata> input) {
+                     return NodeAndNovaTemplateOptions.newAtomicReference(input, Atomics.newReference(templateOptions));
+                  }
+               }
+         );
+         return Futures.transform(nodeAndNovaTemplateOptions, createAndAddFloatingIpToNode, userExecutor);
       } else {
          return future;
       }
    }
-
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7641bd61/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/functions/AllocateAndAddFloatingIpToNodeExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/functions/AllocateAndAddFloatingIpToNodeExpectTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/functions/AllocateAndAddFloatingIpToNodeExpectTest.java
index a5631ca..8edf4a5 100644
--- a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/functions/AllocateAndAddFloatingIpToNodeExpectTest.java
+++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/functions/AllocateAndAddFloatingIpToNodeExpectTest.java
@@ -31,6 +31,8 @@ import org.jclouds.domain.LocationScope;
 import org.jclouds.domain.LoginCredentials;
 import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
+import org.jclouds.openstack.nova.v2_0.compute.options.NodeAndNovaTemplateOptions;
+import org.jclouds.openstack.nova.v2_0.compute.options.NovaTemplateOptions;
 import org.jclouds.openstack.nova.v2_0.internal.BaseNovaComputeServiceExpectTest;
 import org.testng.annotations.Test;
 
@@ -55,7 +57,8 @@ public class AllocateAndAddFloatingIpToNodeExpectTest extends BaseNovaComputeSer
    final NodeMetadata node = new NodeMetadataBuilder().id("az-1.region-a.geo-1/71592").providerId("71592").location(
             host).name("Server 71592").status(Status.RUNNING).privateAddresses(ImmutableSet.of("10.4.27.237"))
             .credentials(LoginCredentials.builder().password("foo").build()).build();
-
+   final NovaTemplateOptions options = NovaTemplateOptions.Builder.autoAssignFloatingIp(false);
+   
    HttpRequest createFloatingIP = HttpRequest.builder().method("POST").endpoint(
             URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-floating-ips")).headers(
             ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
@@ -77,9 +80,13 @@ public class AllocateAndAddFloatingIpToNodeExpectTest extends BaseNovaComputeSer
                .getInstance(AllocateAndAddFloatingIpToNode.class);
 
       AtomicReference<NodeMetadata> nodeRef = Atomics.newReference(node);
-      fn.apply(nodeRef);
+      AtomicReference<NovaTemplateOptions> optionsRef = Atomics.newReference(options);
+      AtomicReference<NodeAndNovaTemplateOptions> nodeNovaRef = NodeAndNovaTemplateOptions.newAtomicReference(nodeRef, optionsRef);
+
+      fn.apply(nodeNovaRef);
       NodeMetadata node1 = nodeRef.get();
       assertNotNull(node1);
+      assertNotNull(optionsRef.get());
       assertEquals(node1.getPublicAddresses(), ImmutableSet.of("10.0.0.3"));
       assertEquals(node1.getCredentials(), node.getCredentials());
 
@@ -96,7 +103,7 @@ public class AllocateAndAddFloatingIpToNodeExpectTest extends BaseNovaComputeSer
       return addFloatingIPRequest;
    }
 
-   public void testAllocateWhenAllocationFailsLookupUnusedIpAddToServerAndUpdatesNodeMetadata() throws Exception {
+   public void testAllocateWhenAllocationFailsOn400LookupUnusedIpAddToServerAndUpdatesNodeMetadata() throws Exception {
       HttpResponse createFloatingIPResponse = HttpResponse
                .builder()
                .statusCode(400)
@@ -124,10 +131,51 @@ public class AllocateAndAddFloatingIpToNodeExpectTest extends BaseNovaComputeSer
                .getInstance(AllocateAndAddFloatingIpToNode.class);
 
       AtomicReference<NodeMetadata> nodeRef = Atomics.newReference(node);
-      fn.apply(nodeRef);
+      AtomicReference<NovaTemplateOptions> optionsRef = Atomics.newReference(options);
+      AtomicReference<NodeAndNovaTemplateOptions> nodeNovaRef = NodeAndNovaTemplateOptions.newAtomicReference(nodeRef, optionsRef);
+
+      fn.apply(nodeNovaRef);
       NodeMetadata node1 = nodeRef.get();
       assertNotNull(node1);
+      assertNotNull(optionsRef.get());
       assertEquals(node1.getPublicAddresses(), ImmutableSet.of("10.0.0.5"));
+   }
+   
+   public void testAllocateWhenAllocationFailsOn404LookupUnusedIpAddToServerAndUpdatesNodeMetadata() throws Exception {
+      HttpResponse createFloatingIPResponse = HttpResponse
+               .builder()
+               .statusCode(404)
+               .payload(
+                        payloadFromStringWithContentType(
+                                 "{\"badRequest\": {\"message\": \"AddressLimitExceeded: Address quota exceeded. You cannot create any more addresses\", \"code\": 404}}",
+                                 "application/json")).build();
+
+      HttpRequest list = HttpRequest.builder().method("GET").endpoint(
+               URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456/os-floating-ips")).headers(
+               ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
+                        authToken).build()).build();
+
+      HttpResponse listResponseForUnassigned = HttpResponse.builder().statusCode(200).payload(
+               payloadFromResource("/floatingip_list.json")).build();
+
+      HttpRequest addFloatingIPRequest = addFloatingIPForAddress("10.0.0.5");
+
+      AllocateAndAddFloatingIpToNode fn = requestsSendResponses(
+               ImmutableMap.<HttpRequest, HttpResponse> builder().put(keystoneAuthWithUsernameAndPasswordAndTenantName,
+                        responseWithKeystoneAccess).put(extensionsOfNovaRequest, extensionsOfNovaResponse).put(
+                        createFloatingIP, createFloatingIPResponse)
+                        .put(addFloatingIPRequest, addFloatingIPResponse).put(list,
+                                 listResponseForUnassigned).build()).getContext().utils().injector()
+               .getInstance(AllocateAndAddFloatingIpToNode.class);
+
+      AtomicReference<NodeMetadata> nodeRef = Atomics.newReference(node);
+      AtomicReference<NovaTemplateOptions> optionsRef = Atomics.newReference(options);
+      AtomicReference<NodeAndNovaTemplateOptions> nodeNovaRef = NodeAndNovaTemplateOptions.newAtomicReference(nodeRef, optionsRef);
 
+      fn.apply(nodeNovaRef);
+      NodeMetadata node1 = nodeRef.get();
+      assertNotNull(node1);
+      assertNotNull(optionsRef.get());
+      assertEquals(node1.getPublicAddresses(), ImmutableSet.of("10.0.0.5"));
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/7641bd61/core/src/main/java/org/jclouds/rest/InsufficientResourcesException.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/jclouds/rest/InsufficientResourcesException.java b/core/src/main/java/org/jclouds/rest/InsufficientResourcesException.java
index e73a9e6..15db2b4 100644
--- a/core/src/main/java/org/jclouds/rest/InsufficientResourcesException.java
+++ b/core/src/main/java/org/jclouds/rest/InsufficientResourcesException.java
@@ -28,7 +28,11 @@ public class InsufficientResourcesException extends RuntimeException {
    public InsufficientResourcesException() {
       super();
    }
-
+   
+   public InsufficientResourcesException(String arg0) {
+      super(arg0);
+   }
+   
    public InsufficientResourcesException(String arg0, Throwable arg1) {
       super(arg0, arg1);
    }


[2/2] git commit: Fixed version for hpcloud-blockstorage

Posted by na...@apache.org.
Fixed version for hpcloud-blockstorage


Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/e94b878b
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/e94b878b
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/e94b878b

Branch: refs/heads/1.7.x
Commit: e94b878b28dd77195790010ce146c211d35e64d8
Parents: 7641bd6
Author: Ignasi Barrera <na...@apache.org>
Authored: Wed Jul 9 17:42:56 2014 +0200
Committer: Ignasi Barrera <na...@apache.org>
Committed: Wed Jul 9 17:42:56 2014 +0200

----------------------------------------------------------------------
 providers/hpcloud-blockstorage/pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/e94b878b/providers/hpcloud-blockstorage/pom.xml
----------------------------------------------------------------------
diff --git a/providers/hpcloud-blockstorage/pom.xml b/providers/hpcloud-blockstorage/pom.xml
index 890ab3b..3b9c68d 100644
--- a/providers/hpcloud-blockstorage/pom.xml
+++ b/providers/hpcloud-blockstorage/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>org.apache.jclouds</groupId>
     <artifactId>jclouds-project</artifactId>
-    <version>1.8.0-SNAPSHOT</version>
+    <version>1.7.4-SNAPSHOT</version>
     <relativePath>../../project/pom.xml</relativePath>
   </parent>
   <groupId>org.apache.jclouds.provider</groupId>