Repository: jclouds
Updated Branches:
  refs/heads/master 88c84af87 -> 50ae6828f


http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/CleanupResources.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/CleanupResources.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/CleanupResources.java
index 5da0b87..3e215bb 100644
--- 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/CleanupResources.java
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/CleanupResources.java
@@ -68,6 +68,7 @@ public class CleanupResources implements 
Function<NodeMetadata, Boolean> {
 
    public boolean 
removeSecurityGroupCreatedByJcloudsAndInvalidateCache(Set<String> tags) {
       String securityGroupIdCreatedByJclouds = 
getSecurityGroupIdCreatedByJclouds(tags);
+      if (securityGroupIdCreatedByJclouds == null) return true;
       return 
securityGroupExtension.removeSecurityGroup(securityGroupIdCreatedByJclouds);
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/RemoveFloatingIpFromNodeAndDeallocate.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/RemoveFloatingIpFromNodeAndDeallocate.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/RemoveFloatingIpFromNodeAndDeallocate.java
index 94309c8..8161443 100644
--- 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/RemoveFloatingIpFromNodeAndDeallocate.java
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/functions/RemoveFloatingIpFromNodeAndDeallocate.java
@@ -19,19 +19,23 @@ package org.jclouds.openstack.nova.v2_0.compute.functions;
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import javax.annotation.Resource;
-import javax.inject.Inject;
 import javax.inject.Named;
 
+import com.google.common.base.Supplier;
+import com.google.inject.Inject;
+import org.jclouds.Context;
 import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.logging.Logger;
+import org.jclouds.openstack.neutron.v2.NeutronApi;
 import org.jclouds.openstack.nova.v2_0.NovaApi;
-import org.jclouds.openstack.nova.v2_0.domain.FloatingIP;
+import org.jclouds.openstack.nova.v2_0.domain.FloatingIpForServer;
 import org.jclouds.openstack.nova.v2_0.domain.regionscoped.RegionAndId;
 import org.jclouds.openstack.nova.v2_0.extensions.FloatingIPApi;
 
 import com.google.common.base.Function;
 import com.google.common.base.MoreObjects;
 import com.google.common.cache.LoadingCache;
+import org.jclouds.rest.ApiContext;
 
 /**
  * A function for removing and deallocating an ip address from a node
@@ -42,31 +46,51 @@ public class RemoveFloatingIpFromNodeAndDeallocate 
implements Function<RegionAnd
    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
    protected Logger logger = Logger.NULL;
 
+   @Inject(optional = true)
+   @Named("openstack-neutron")
+   private Supplier<Context> neutronContextSupplier;
+
    private final NovaApi novaApi;
-   private final LoadingCache<RegionAndId, Iterable<? extends FloatingIP>> 
floatingIpCache;
+   private final LoadingCache<RegionAndId, Iterable<? extends 
FloatingIpForServer>> floatingIpCache;
 
    @Inject
    public RemoveFloatingIpFromNodeAndDeallocate(NovaApi novaApi,
-            @Named("FLOATINGIP") LoadingCache<RegionAndId, Iterable<? extends 
FloatingIP>> floatingIpCache) {
+            @Named("FLOATINGIP") LoadingCache<RegionAndId, Iterable<? extends 
FloatingIpForServer>> floatingIpCache) {
       this.novaApi = checkNotNull(novaApi, "novaApi");
       this.floatingIpCache = checkNotNull(floatingIpCache, "floatingIpCache");
    }
 
    @Override
    public RegionAndId apply(RegionAndId id) {
-      FloatingIPApi floatingIpApi = 
novaApi.getFloatingIPApi(id.getRegion()).get();
-      for (FloatingIP ip : floatingIpCache.getUnchecked(id)) {
-         logger.debug(">> removing floatingIp(%s) from node(%s)", ip, id);
-         floatingIpApi.removeFromServer(ip.getIp(), id.getId());
-         logger.debug(">> deallocating floatingIp(%s)", ip);
-         floatingIpApi.delete(ip.getId());
+      if (isNeutronLinked()) {
+         for (FloatingIpForServer floatingIpForServer : 
floatingIpCache.getUnchecked(id)) {
+            logger.debug(">> deallocating floatingIp(%s)", 
floatingIpForServer);
+            
getFloatingIPApi(id.getRegion()).delete(floatingIpForServer.floatingIpId());
+         }
+      } else { // try nova
+         FloatingIPApi floatingIpApi = 
novaApi.getFloatingIPApi(id.getRegion()).get();
+         for (FloatingIpForServer floatingIpForServer : 
floatingIpCache.getUnchecked(id)) {
+            logger.debug(">> removing floatingIp(%s) from node(%s)", 
floatingIpForServer, id);
+            floatingIpApi.removeFromServer(floatingIpForServer.ip(), 
id.getId());
+            logger.debug(">> deallocating floatingIp(%s)", 
floatingIpForServer);
+            floatingIpApi.delete(floatingIpForServer.floatingIpId());
+         }
       }
       floatingIpCache.invalidate(id);
       return id;
    }
 
+   // FIXME remove duplications from AllocateAndAddFloatingIpToNode
+   private boolean isNeutronLinked() {
+      return neutronContextSupplier != null && neutronContextSupplier.get() != 
null;
+   }
+
+   private org.jclouds.openstack.neutron.v2.features.FloatingIPApi 
getFloatingIPApi(String region) {
+      return ((ApiContext<NeutronApi>) 
neutronContextSupplier.get()).getApi().getFloatingIPApi(region);
+   }
+
    @Override
    public String toString() {
-      return 
MoreObjects.toStringHelper("RemoveFloatingIpFromNodeAndDecreate").toString();
+      return 
MoreObjects.toStringHelper("RemoveFloatingIpFromNodeAndDeallocate").toString();
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstance.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstance.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstance.java
index 1487a13..2e404d5 100644
--- 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstance.java
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstance.java
@@ -19,8 +19,10 @@ package org.jclouds.openstack.nova.v2_0.compute.loaders;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
+import com.google.common.base.Function;
 import org.jclouds.openstack.nova.v2_0.NovaApi;
 import org.jclouds.openstack.nova.v2_0.domain.FloatingIP;
+import org.jclouds.openstack.nova.v2_0.domain.FloatingIpForServer;
 import org.jclouds.openstack.nova.v2_0.domain.regionscoped.RegionAndId;
 import org.jclouds.openstack.nova.v2_0.extensions.FloatingIPApi;
 
@@ -35,7 +37,7 @@ import com.google.common.collect.ImmutableSet;
  * them.
  */
 @Singleton
-public class LoadFloatingIpsForInstance extends CacheLoader<RegionAndId, 
Iterable<? extends FloatingIP>> {
+public class LoadFloatingIpsForInstance extends CacheLoader<RegionAndId, 
Iterable<? extends FloatingIpForServer>> {
    private final NovaApi api;
 
    @Inject
@@ -44,7 +46,7 @@ public class LoadFloatingIpsForInstance extends 
CacheLoader<RegionAndId, Iterabl
    }
 
    @Override
-   public Iterable<? extends FloatingIP> load(final RegionAndId key) throws 
Exception {
+   public Iterable<? extends FloatingIpForServer> load(final RegionAndId key) 
throws Exception {
       String region = key.getRegion();
       Optional<? extends FloatingIPApi> ipApiOptional = 
api.getFloatingIPApi(region);
       if (ipApiOptional.isPresent()) {
@@ -54,7 +56,13 @@ public class LoadFloatingIpsForInstance extends 
CacheLoader<RegionAndId, Iterabl
                      public boolean apply(FloatingIP input) {
                         return key.getId().equals(input.getInstanceId());
                      }
-                  });
+                  })
+                 .transform(new Function<FloatingIP, FloatingIpForServer>() {
+                     @Override
+                     public FloatingIpForServer apply(FloatingIP input) {
+                         return FloatingIpForServer.create(key, input.getId(), 
input.getIp());
+                     }
+                 });
       }
       return ImmutableSet.of();
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/FloatingIpForServer.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/FloatingIpForServer.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/FloatingIpForServer.java
new file mode 100644
index 0000000..784ebfc
--- /dev/null
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/FloatingIpForServer.java
@@ -0,0 +1,38 @@
+/*
+ * 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.domain;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.openstack.nova.v2_0.domain.regionscoped.RegionAndId;
+
+@AutoValue
+public abstract class FloatingIpForServer {
+
+   public abstract RegionAndId serverId();
+   public abstract String floatingIpId();
+   public abstract String ip();
+
+   public static FloatingIpForServer create(RegionAndId serverId,
+                               String floatingIpId,
+                               String ip
+   ) {
+      return new AutoValue_FloatingIpForServer(serverId, floatingIpId, ip);
+   }
+
+   FloatingIpForServer() {
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/PortInterface.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/PortInterface.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/PortInterface.java
new file mode 100644
index 0000000..4931016
--- /dev/null
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/domain/PortInterface.java
@@ -0,0 +1,57 @@
+/*
+ * 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.domain;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.base.Enums;
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import org.jclouds.json.SerializedNames;
+
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+@AutoValue
+public abstract class PortInterface {
+
+    public enum State {
+        PROVISIONING, QUEUED, ACTIVE;
+
+        public static State fromValue(String value) {
+            Optional<State> state = Enums.getIfPresent(State.class, 
value.toUpperCase());
+            checkArgument(state.isPresent(), "Expected one of %s but was %s", 
Joiner.on(',').join(State.values()), value);
+            return state.get();
+        }
+    }
+
+    public abstract String portId();
+    public abstract String netId();
+    public abstract State portState();
+    public abstract List<FixedIP> fixedIPS();
+
+    @SerializedNames({"port_id", "net_id", "port_state", "fixed_ips"})
+    public static PortInterface create(String portId, String netId, State 
portState, List<FixedIP> fixedIPS) {
+        return new AutoValue_PortInterface(portId, netId, portState,
+                fixedIPS == null ? ImmutableList.<FixedIP> of() : 
ImmutableList.copyOf(fixedIPS)
+        );
+    }
+
+    PortInterface() {}
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ServerApi.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ServerApi.java
 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ServerApi.java
index 512f4a0..555d4e4 100644
--- 
a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ServerApi.java
+++ 
b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/features/ServerApi.java
@@ -42,6 +42,7 @@ import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
 import org.jclouds.collect.PagedIterable;
 import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
 import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.openstack.nova.v2_0.domain.PortInterface;
 import org.jclouds.openstack.nova.v2_0.domain.SecurityGroup;
 import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
 import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest;
@@ -446,4 +447,18 @@ public interface ServerApi {
    @Fallback(Fallbacks.EmptySetOnNotFoundOr404.class)
    Set<SecurityGroup> listSecurityGroupForServer(@PathParam("id") String id);
 
+   /**
+    * Lists port interfaces that are attached to a server.
+    *
+    * @param id
+    *           id of the server
+    * @return a list of ports attached to the server
+    */
+   @Named("server:getPortInterfaces")
+   @GET
+   @Path("/{id}/os-interface")
+   @SelectJson("interfaceAttachments")
+   @Fallback(Fallbacks.EmptySetOnNotFoundOr404.class)
+   Set<PortInterface> listPortInterfaces(@PathParam("id") String id);
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/NovaComputeServiceLiveTest.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/NovaComputeServiceLiveTest.java
 
b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/NovaComputeServiceLiveTest.java
index 1b6c6ad..d4aac07 100644
--- 
a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/NovaComputeServiceLiveTest.java
+++ 
b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/NovaComputeServiceLiveTest.java
@@ -21,15 +21,12 @@ import static java.util.logging.Logger.getAnonymousLogger;
 import java.util.Properties;
 
 import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
-import org.jclouds.logging.config.LoggingModule;
-import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
 import org.jclouds.openstack.keystone.config.KeystoneProperties;
 import org.jclouds.openstack.nova.v2_0.config.NovaProperties;
 import org.jclouds.rest.AuthorizationException;
 import org.jclouds.sshj.config.SshjSshClientModule;
 import org.testng.annotations.Test;
 
-import com.google.common.collect.ImmutableSet;
 import com.google.inject.Module;
 
 @Test(groups = "live", singleThreaded = true, testName = 
"NovaComputeServiceLiveTest")
@@ -43,17 +40,7 @@ public class NovaComputeServiceLiveTest extends 
BaseComputeServiceLiveTest {
    protected Module getSshModule() {
       return new SshjSshClientModule();
    }
-
-   @Override
-   protected LoggingModule getLoggingModule() {
-      return new SLF4JLoggingModule();
-   }
-
-   @Override
-   protected Iterable<Module> setupModules() {
-      return ImmutableSet.of(getLoggingModule(), credentialStoreModule, 
getSshModule());
-   }
-
+   
    @Override
    public void testOptionToNotBlock() {
       // start call is blocking anyway.
@@ -62,14 +49,12 @@ public class NovaComputeServiceLiveTest extends 
BaseComputeServiceLiveTest {
    @Test(enabled = true, dependsOnMethods = "testReboot")
    public void testSuspendResume() throws Exception {
       try {
-         // may fail because of lack of AdminActions extension or non-admin 
user, so log
-         // and continue
+         // may fail because of lack of AdminActions extension or non-admin 
user, so log and continue
          super.testSuspendResume();
       } catch (AuthorizationException e) {
          getAnonymousLogger().info("testSuspendResume() threw, probably due to 
lack of privileges: " + e.getMessage());
       } catch (UnsupportedOperationException e) {
-         getAnonymousLogger().info(
-               "testSuspendResume() threw, probably due to unavailable 
AdminActions extension: " + e.getMessage());
+         getAnonymousLogger().info("testSuspendResume() threw, probably due to 
unavailable AdminActions extension: " + e.getMessage());
       }
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/NovaWithNeutronComputeServiceLiveTest.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/NovaWithNeutronComputeServiceLiveTest.java
 
b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/NovaWithNeutronComputeServiceLiveTest.java
new file mode 100644
index 0000000..1559910
--- /dev/null
+++ 
b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/NovaWithNeutronComputeServiceLiveTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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;
+
+import static java.util.logging.Logger.getAnonymousLogger;
+
+import java.util.Properties;
+
+import com.google.common.collect.ImmutableSet;
+import org.jclouds.Context;
+import org.jclouds.ContextBuilder;
+import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
+import org.jclouds.config.ContextLinking;
+import org.jclouds.encryption.bouncycastle.config.BouncyCastleCryptoModule;
+import org.jclouds.logging.config.LoggingModule;
+import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
+import org.jclouds.openstack.keystone.config.KeystoneProperties;
+import org.jclouds.openstack.nova.v2_0.config.NovaProperties;
+import org.jclouds.rest.AuthorizationException;
+import org.jclouds.sshj.config.SshjSshClientModule;
+import org.testng.annotations.Test;
+
+import com.google.inject.Module;
+
+@Test(groups = "live", singleThreaded = true, testName = 
"NovaWithNeutronComputeServiceLiveTest")
+public class NovaWithNeutronComputeServiceLiveTest extends 
BaseComputeServiceLiveTest {
+
+   private Context neutronApiContext;
+
+   public NovaWithNeutronComputeServiceLiveTest() {
+      provider = "openstack-nova";
+
+      Properties overrides = setupProperties();
+      neutronApiContext = ContextBuilder.newBuilder("openstack-neutron")
+              .endpoint(setIfTestSystemPropertyPresent(overrides,
+                      "openstack-nova.endpoint"))
+              .credentials(setIfTestSystemPropertyPresent(overrides,
+                      "openstack-nova.identity"),
+                      setIfTestSystemPropertyPresent(overrides, 
"openstack-nova.credential"))
+              .modules(ImmutableSet.<Module>of(
+                      new SshjSshClientModule(),
+                      new SLF4JLoggingModule(),
+                      new BouncyCastleCryptoModule())
+              )
+              .build();
+   }
+
+   @Override
+   protected Module getSshModule() {
+      return new SshjSshClientModule();
+   }
+
+   @Override
+   protected LoggingModule getLoggingModule() {
+      return new SLF4JLoggingModule();
+   }
+
+   @Override
+   protected Iterable<Module> setupModules() {
+      return ImmutableSet.of(
+              ContextLinking.linkContext(neutronApiContext),
+              getLoggingModule(),
+              credentialStoreModule,
+              getSshModule()
+      );
+   }
+   
+   @Override
+   public void testOptionToNotBlock() {
+      // start call is blocking anyway.
+   }
+
+   @Test(enabled = true, dependsOnMethods = "testReboot")
+   public void testSuspendResume() throws Exception {
+      try {
+         // may fail because of lack of AdminActions extension or non-admin 
user, so log and continue
+         super.testSuspendResume();
+      } catch (AuthorizationException e) {
+         getAnonymousLogger().info("testSuspendResume() threw, probably due to 
lack of privileges: " + e.getMessage());
+      } catch (UnsupportedOperationException e) {
+         getAnonymousLogger().info("testSuspendResume() threw, probably due to 
unavailable AdminActions extension: " + e.getMessage());
+      }
+   }
+
+   @Test(enabled = true, dependsOnMethods = "testSuspendResume")
+   @Override
+   public void testGetNodesWithDetails() throws Exception {
+      super.testGetNodesWithDetails();
+   }
+
+   @Test(enabled = true, dependsOnMethods = "testSuspendResume")
+   @Override
+   public void testListNodes() throws Exception {
+      super.testListNodes();
+   }
+
+   @Test(enabled = true, dependsOnMethods = "testSuspendResume")
+   @Override
+   public void testListNodesByIds() throws Exception {
+      super.testListNodesByIds();
+   }
+
+   @Test(enabled = true, dependsOnMethods = { "testListNodes", 
"testGetNodesWithDetails", "testListNodesByIds" })
+   @Override
+   public void testDestroyNodes() {
+      super.testDestroyNodes();
+   }
+
+   @Override
+   protected Properties setupProperties() {
+      Properties props = super.setupProperties();
+      setIfTestSystemPropertyPresent(props, 
KeystoneProperties.CREDENTIAL_TYPE);
+      setIfTestSystemPropertyPresent(props, 
NovaProperties.AUTO_ALLOCATE_FLOATING_IPS);
+      return props;
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/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 af20d85..70ef379 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
@@ -68,14 +68,27 @@ public class AllocateAndAddFloatingIpToNodeExpectTest 
extends BaseNovaComputeSer
       HttpResponse createFloatingIPResponse = 
HttpResponse.builder().statusCode(200).payload(
                payloadFromResource("/floatingip_details.json")).build();
 
+      HttpRequest listAZs = HttpRequest.builder().method("GET").endpoint(
+              
URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v2/3456/os-availability-zone";)).headers(
+              ImmutableMultimap.<String, String> builder().put("Accept", 
"application/json")
+                      .put("X-Auth-Token", authToken)
+                      .build())
+              .build();
+
+      HttpResponse listAZsResponseForUnassigned = 
HttpResponse.builder().statusCode(200).payload(
+              payloadFromResource("/availability_zone_list.json")).build();
+
       HttpRequest addFloatingIPRequest = addFloatingIPForAddress("10.0.0.3");
 
       AllocateAndAddFloatingIpToNode fn = requestsSendResponses(
-               ImmutableMap.<HttpRequest, HttpResponse> 
builder().put(keystoneAuthWithUsernameAndPasswordAndTenantName,
-                        
responseWithKeystoneAccess).put(extensionsOfNovaRequest, 
extensionsOfNovaResponse).put(
-                        createFloatingIP, createFloatingIPResponse)
-                        .put(addFloatingIPRequest, 
addFloatingIPResponse).build()).getContext().utils().injector()
-               .getInstance(AllocateAndAddFloatingIpToNode.class);
+               ImmutableMap.<HttpRequest, HttpResponse> builder()
+                       .put(keystoneAuthWithUsernameAndPasswordAndTenantName, 
responseWithKeystoneAccess)
+                       .put(listAZs, listAZsResponseForUnassigned)
+                       .put(extensionsOfNovaRequest, extensionsOfNovaResponse)
+                       .put(createFloatingIP, createFloatingIPResponse)
+                       .put(addFloatingIPRequest, 
addFloatingIPResponse).build())
+              .getContext().utils().injector()
+              .getInstance(AllocateAndAddFloatingIpToNode.class);
 
       AtomicReference<NodeMetadata> nodeRef = Atomics.newReference(node);
       AtomicReference<NovaTemplateOptions> optionsRef = 
Atomics.newReference(options);
@@ -110,6 +123,16 @@ public class AllocateAndAddFloatingIpToNodeExpectTest 
extends BaseNovaComputeSer
                                  "{\"badRequest\": {\"message\": 
\"AddressLimitExceeded: Address quota exceeded. You cannot create any more 
addresses\", \"code\": 400}}",
                                  "application/json")).build();
 
+      HttpRequest listAZs = HttpRequest.builder().method("GET").endpoint(
+              
URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v2/3456/os-availability-zone";)).headers(
+              ImmutableMultimap.<String, String> builder().put("Accept", 
"application/json")
+                      .put("X-Auth-Token", authToken)
+                      .build())
+              .build();
+
+      HttpResponse listAZsResponseForUnassigned = 
HttpResponse.builder().statusCode(200).payload(
+              payloadFromResource("/availability_zone_list.json")).build();
+
       HttpRequest list = HttpRequest.builder().method("GET").endpoint(
                
URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v2/3456/os-floating-ips";)).headers(
                ImmutableMultimap.<String, String> builder().put("Accept", 
"application/json").put("X-Auth-Token",
@@ -121,12 +144,16 @@ public class AllocateAndAddFloatingIpToNodeExpectTest 
extends BaseNovaComputeSer
       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);
+               ImmutableMap.<HttpRequest, HttpResponse> builder()
+                       .put(keystoneAuthWithUsernameAndPasswordAndTenantName, 
responseWithKeystoneAccess)
+                       .put(listAZs, listAZsResponseForUnassigned)
+                       .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);
@@ -148,6 +175,16 @@ public class AllocateAndAddFloatingIpToNodeExpectTest 
extends BaseNovaComputeSer
                                  "{\"badRequest\": {\"message\": 
\"AddressLimitExceeded: Address quota exceeded. You cannot create any more 
addresses\", \"code\": 404}}",
                                  "application/json")).build();
 
+      HttpRequest listAZs = HttpRequest.builder().method("GET").endpoint(
+              
URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v2/3456/os-availability-zone";)).headers(
+              ImmutableMultimap.<String, String> builder().put("Accept", 
"application/json")
+                      .put("X-Auth-Token", authToken)
+                      .build())
+              .build();
+
+      HttpResponse listAZsResponseForUnassigned = 
HttpResponse.builder().statusCode(200).payload(
+              payloadFromResource("/availability_zone_list.json")).build();
+
       HttpRequest list = HttpRequest.builder().method("GET").endpoint(
                
URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v2/3456/os-floating-ips";)).headers(
                ImmutableMultimap.<String, String> builder().put("Accept", 
"application/json").put("X-Auth-Token",
@@ -159,12 +196,15 @@ public class AllocateAndAddFloatingIpToNodeExpectTest 
extends BaseNovaComputeSer
       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);
+               ImmutableMap.<HttpRequest, HttpResponse> builder()
+                       .put(keystoneAuthWithUsernameAndPasswordAndTenantName, 
responseWithKeystoneAccess)
+                       .put(listAZs, listAZsResponseForUnassigned)
+                       .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);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstanceTest.java
----------------------------------------------------------------------
diff --git 
a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstanceTest.java
 
b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstanceTest.java
index 84d2fa7..6760c6d 100644
--- 
a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstanceTest.java
+++ 
b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v2_0/compute/loaders/LoadFloatingIpsForInstanceTest.java
@@ -25,6 +25,7 @@ import static org.testng.AssertJUnit.assertFalse;
 
 import org.jclouds.openstack.nova.v2_0.NovaApi;
 import org.jclouds.openstack.nova.v2_0.domain.FloatingIP;
+import org.jclouds.openstack.nova.v2_0.domain.FloatingIpForServer;
 import org.jclouds.openstack.nova.v2_0.domain.regionscoped.RegionAndId;
 import org.jclouds.openstack.nova.v2_0.extensions.FloatingIPApi;
 import org.testng.annotations.Test;
@@ -50,8 +51,8 @@ public class LoadFloatingIpsForInstanceTest {
       replay(ipApi);
 
       LoadFloatingIpsForInstance parser = new LoadFloatingIpsForInstance(api);
-
-      
assertEquals(ImmutableSet.copyOf(parser.load(RegionAndId.fromRegionAndId("RegionOne",
 "i-blah"))), ImmutableSet.of(testIp));
+      FloatingIpForServer floatingIpForServer = 
FloatingIpForServer.create(RegionAndId.fromRegionAndId("RegionOne", "i-blah"), 
"1", "1.1.1.1");
+      
assertEquals(ImmutableSet.copyOf(parser.load(RegionAndId.fromRegionAndId("RegionOne",
 "i-blah"))), ImmutableSet.of(floatingIpForServer));
 
       verify(api);
       verify(ipApi);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-nova/src/test/resources/availability_zone_list.json
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/test/resources/availability_zone_list.json 
b/apis/openstack-nova/src/test/resources/availability_zone_list.json
new file mode 100644
index 0000000..0058762
--- /dev/null
+++ b/apis/openstack-nova/src/test/resources/availability_zone_list.json
@@ -0,0 +1,18 @@
+{
+  "availabilityZoneInfo": [
+    {
+      "zoneState": {
+        "available": true
+      },
+      "hosts": null,
+      "zoneName": "uk-1a"
+    },
+    {
+      "zoneState": {
+        "available": true
+      },
+      "hosts": null,
+      "zoneName": "uk-1b"
+    }
+  ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/s3/src/main/java/org/jclouds/s3/filters/Aws4SignerBase.java
----------------------------------------------------------------------
diff --git a/apis/s3/src/main/java/org/jclouds/s3/filters/Aws4SignerBase.java 
b/apis/s3/src/main/java/org/jclouds/s3/filters/Aws4SignerBase.java
index 615f0cf..5aa88da 100644
--- a/apis/s3/src/main/java/org/jclouds/s3/filters/Aws4SignerBase.java
+++ b/apis/s3/src/main/java/org/jclouds/s3/filters/Aws4SignerBase.java
@@ -270,7 +270,6 @@ public abstract class Aws4SignerBase {
       }
    }
 
-
    /**
     * hash string (encoding UTF_8) with sha256
     *

Reply via email to