You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by an...@apache.org on 2018/02/15 17:09:19 UTC
[1/2] jclouds git commit: [JCLOUDS-1382] improve usage of Neutron
capabilities from Nova
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
*
[2/2] jclouds git commit: [JCLOUDS-1382] improve usage of Neutron
capabilities from Nova
Posted by an...@apache.org.
[JCLOUDS-1382] improve usage of Neutron capabilities from Nova
- move Neutron FloatingIP API from extension to feature
- introduce FloatingIpForServer as abstract domain object to represents Nova and Neutron objects
- manage floating ip cache and its invalidation
Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/50ae6828
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/50ae6828
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/50ae6828
Branch: refs/heads/master
Commit: 50ae6828f52cebe4dffab518c4d5053d93b2a494
Parents: 88c84af
Author: Andrea Turli <an...@gmail.com>
Authored: Wed Feb 14 16:03:57 2018 +0100
Committer: Andrea Turli <an...@gmail.com>
Committed: Thu Feb 15 18:08:53 2018 +0100
----------------------------------------------------------------------
.../openstack/neutron/v2/NeutronApi.java | 14 +-
.../openstack/neutron/v2/domain/FloatingIP.java | 68 ++++-
.../openstack/neutron/v2/domain/Network.java | 31 +-
.../openstack/neutron/v2/domain/Networks.java | 23 ++
.../neutron/v2/extensions/FloatingIPApi.java | 139 ---------
.../neutron/v2/features/FloatingIPApi.java | 136 +++++++++
.../functions/FloatingIPsToPagedIterable.java | 4 +-
.../neutron/v2/extensions/FWaaSApiMockTest.java | 7 +-
.../v2/extensions/FloatingIPApiLiveTest.java | 92 ------
.../v2/extensions/FloatingIPApiMockTest.java | 292 -------------------
.../v2/features/FloatingIPApiLiveTest.java | 77 +++++
.../v2/features/FloatingIPApiMockTest.java | 278 ++++++++++++++++++
.../config/NovaComputeServiceContextModule.java | 12 +-
.../AllocateAndAddFloatingIpToNode.java | 184 ++++++++++--
.../compute/functions/CleanupResources.java | 1 +
.../RemoveFloatingIpFromNodeAndDeallocate.java | 46 ++-
.../loaders/LoadFloatingIpsForInstance.java | 14 +-
.../nova/v2_0/domain/FloatingIpForServer.java | 38 +++
.../nova/v2_0/domain/PortInterface.java | 57 ++++
.../openstack/nova/v2_0/features/ServerApi.java | 15 +
.../compute/NovaComputeServiceLiveTest.java | 21 +-
.../NovaWithNeutronComputeServiceLiveTest.java | 130 +++++++++
...llocateAndAddFloatingIpToNodeExpectTest.java | 74 +++--
.../loaders/LoadFloatingIpsForInstanceTest.java | 5 +-
.../test/resources/availability_zone_list.json | 18 ++
.../org/jclouds/s3/filters/Aws4SignerBase.java | 1 -
26 files changed, 1141 insertions(+), 636 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/NeutronApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/NeutronApi.java b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/NeutronApi.java
index 97530f8..e7863d2 100644
--- a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/NeutronApi.java
+++ b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/NeutronApi.java
@@ -22,7 +22,7 @@ import java.util.Set;
import javax.ws.rs.Path;
import org.jclouds.location.Region;
-import org.jclouds.openstack.neutron.v2.extensions.FloatingIPApi;
+import org.jclouds.openstack.neutron.v2.features.FloatingIPApi;
import org.jclouds.openstack.neutron.v2.extensions.RouterApi;
import org.jclouds.openstack.neutron.v2.features.SecurityGroupApi;
import org.jclouds.openstack.neutron.v2.extensions.lbaas.v1.LBaaSApi;
@@ -89,24 +89,20 @@ public interface NeutronApi extends Closeable {
SecurityGroupApi getSecurityGroupApi(@EndpointParam(parser = VersionAwareRegionToEndpoint.class) String region);
/**
- * Provides access to Router features.
- *
- * <h3>NOTE</h3>
- * This API is an extension that may or may not be present in your OpenStack cloud. Use the Optional return type
- * to determine if it is present.
+ * Provides access to Floating IP features.
*/
@Delegate
- Optional<RouterApi> getRouterApi(@EndpointParam(parser = VersionAwareRegionToEndpoint.class) String region);
+ FloatingIPApi getFloatingIPApi(@EndpointParam(parser = VersionAwareRegionToEndpoint.class) String region);
/**
- * Provides access to Floating IP features.
+ * Provides access to Router features.
*
* <h3>NOTE</h3>
* This API is an extension that may or may not be present in your OpenStack cloud. Use the Optional return type
* to determine if it is present.
*/
@Delegate
- Optional<FloatingIPApi> getFloatingIPApi(@EndpointParam(parser = VersionAwareRegionToEndpoint.class) String region);
+ Optional<RouterApi> getRouterApi(@EndpointParam(parser = VersionAwareRegionToEndpoint.class) String region);
/**
* Provides access to LBaaS features.
http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/FloatingIP.java
----------------------------------------------------------------------
diff --git a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/FloatingIP.java b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/FloatingIP.java
index be61ad3..dbb550c 100644
--- a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/FloatingIP.java
+++ b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/FloatingIP.java
@@ -34,6 +34,8 @@ public class FloatingIP {
private String id;
@Named("router_id")
private String routerId;
+ @Named("project_id")
+ private String projectId;
@Named("tenant_id")
private String tenantId;
// Only mandatory attribute when creating
@@ -45,21 +47,25 @@ public class FloatingIP {
private String floatingIpAddress;
@Named("port_id")
private String portId;
+ @Named("availability_zone")
+ private String availabilityZone;
/**
* Deserialization constructor
*/
- @ConstructorProperties({"id", "router_id", "tenant_id", "floating_network_id", "fixed_ip_address",
- "floating_ip_address", "port_id"})
- private FloatingIP(String id, String routerId, String tenantId, String floatingNetworkId, String fixedIpAddress,
- String floatingIpAddress, String portId) {
+ @ConstructorProperties({"id", "router_id", "project_id", "tenant_id", "floating_network_id", "fixed_ip_address",
+ "floating_ip_address", "port_id", "availability_zone"})
+ private FloatingIP(String id, String routerId, String projectId, String tenantId, String floatingNetworkId, String fixedIpAddress,
+ String floatingIpAddress, String portId, String availabilityZone) {
this.id = id;
this.routerId = routerId;
+ this.projectId = projectId;
this.tenantId = tenantId;
this.floatingNetworkId = floatingNetworkId;
this.fixedIpAddress = fixedIpAddress;
this.floatingIpAddress = floatingIpAddress;
this.portId = portId;
+ this.availabilityZone = availabilityZone;
}
private FloatingIP() {}
@@ -68,8 +74,8 @@ public class FloatingIP {
* @param floatingIP The floating IP to copy from
*/
private FloatingIP(FloatingIP floatingIP) {
- this(floatingIP.id, floatingIP.routerId, floatingIP.tenantId, floatingIP.floatingNetworkId,
- floatingIP.fixedIpAddress, floatingIP.floatingIpAddress, floatingIP.portId);
+ this(floatingIP.id, floatingIP.routerId, floatingIP.projectId, floatingIP.tenantId, floatingIP.floatingNetworkId,
+ floatingIP.fixedIpAddress, floatingIP.floatingIpAddress, floatingIP.portId, floatingIP.availabilityZone);
}
/**
@@ -89,6 +95,14 @@ public class FloatingIP {
}
/**
+ * @return the project id of the Floating IP
+ */
+ @Nullable
+ public String getProjectId() {
+ return projectId;
+ }
+
+ /**
* @return the tenant id of the Floating IP
*/
@Nullable
@@ -128,6 +142,14 @@ public class FloatingIP {
return portId;
}
+ /**
+ * @return the availability zone for this floating IP
+ */
+ @Nullable
+ public String getAvailabilityZone() {
+ return availabilityZone;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o)
@@ -139,17 +161,20 @@ public class FloatingIP {
return Objects.equal(this.id, that.id) &&
Objects.equal(this.routerId, that.routerId) &&
+ Objects.equal(this.projectId, that.projectId) &&
Objects.equal(this.tenantId, that.tenantId) &&
Objects.equal(this.floatingNetworkId, that.floatingNetworkId) &&
Objects.equal(this.fixedIpAddress, that.fixedIpAddress) &&
Objects.equal(this.floatingIpAddress, that.floatingIpAddress) &&
- Objects.equal(this.portId, that.portId);
+ Objects.equal(this.portId, that.portId) &&
+ Objects.equal(this.availabilityZone, that.availabilityZone);
+
}
@Override
public int hashCode() {
- return Objects.hashCode(id, routerId, tenantId, floatingNetworkId, fixedIpAddress, floatingIpAddress,
- portId);
+ return Objects.hashCode(id, routerId, projectId, tenantId, floatingNetworkId, fixedIpAddress, floatingIpAddress,
+ portId, availabilityZone);
}
@Override
@@ -157,11 +182,13 @@ public class FloatingIP {
return MoreObjects.toStringHelper(this)
.add("id", id)
.add("routerId", routerId)
+ .add("projectId", projectId)
.add("tenantId", tenantId)
.add("floatingNetworkId", floatingNetworkId)
.add("fixedIpAddress", fixedIpAddress)
.add("floatingIpAddress", floatingIpAddress)
.add("portId", portId)
+ .add("availabilityZone", availabilityZone)
.toString();
}
@@ -192,6 +219,17 @@ public class FloatingIP {
protected abstract ParameterizedBuilderType self();
/**
+ * Provide the project ID for this Floating IP.
+ *
+ * @return the Builder.
+ * @see FloatingIP#getProjectId() ()
+ */
+ public ParameterizedBuilderType projectId(String projectId) {
+ floatingIP.projectId = projectId;
+ return self();
+ }
+
+ /**
* Provide the tenantId for this Floating IP. Admin-only.
* When keystone is enabled, it is not mandatory to specify tenant_id for resources in create requests, as the
* tenant identifier will be derived from the Authentication token. Please note that the default authorization
@@ -249,6 +287,18 @@ public class FloatingIP {
floatingIP.portId = portId;
return self();
}
+
+ /**
+ * Provides the availability zone for this Floating IP.
+ *
+ * @return the Builder.
+ * @see FloatingIP#getAvailabilityZone()
+ */
+ public ParameterizedBuilderType availabilityZone(String availabilityZone) {
+ floatingIP.availabilityZone = availabilityZone;
+ return self();
+ }
+
}
public static class CreateBuilder extends Builder<CreateBuilder> {
http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Network.java
----------------------------------------------------------------------
diff --git a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Network.java b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Network.java
index c269593..d8fca09 100644
--- a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Network.java
+++ b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Network.java
@@ -47,6 +47,8 @@ public class Network {
private Boolean shared;
@Named("tenant_id")
private String tenantId;
+ @Named("availability_zone")
+ private String availabilityZone;
// providernet.py: Provider Networks Extension
@Named("provider:network_type")
@@ -85,12 +87,12 @@ public class Network {
@Named("flavor:network")
private String networkFlavor;
- @ConstructorProperties({"id", "status", "subnets", "name", "admin_state_up", "shared", "tenant_id",
+ @ConstructorProperties({"id", "status", "subnets", "name", "admin_state_up", "shared", "tenant_id", "availability_zone",
"provider:network_type", "provider:physical_network", "provider:segmentation_id", "router:external",
"port_security_enabled", "n1kv:profile_id", "n1kv:multicast_ip", "n1kv:segment_add", "n1kv:segment_del",
"n1kv:member_segments", "segments", "flavor:network"})
private Network(String id, NetworkStatus status, ImmutableSet<String> subnets, String name, Boolean adminStateUp,
- Boolean shared, String tenantId, NetworkType networkType, String physicalNetworkName, Integer segmentationId,
+ Boolean shared, String tenantId, String availabilityZone, NetworkType networkType, String physicalNetworkName, Integer segmentationId,
Boolean external, Boolean portSecurity, String profileId, String multicastIp, String segmentAdd,
String segmentDel, String memberSegments, ImmutableSet<NetworkSegment> segments, String networkFlavor) {
// No checkNotNulls. With Neutron, any of these properties can be left null when used in an update.
@@ -101,6 +103,7 @@ public class Network {
this.adminStateUp = adminStateUp;
this.shared = shared;
this.tenantId = tenantId;
+ this.availabilityZone = availabilityZone;
this.networkType = networkType;
this.physicalNetworkName = physicalNetworkName;
this.segmentationId = segmentationId;
@@ -132,6 +135,7 @@ public class Network {
network.adminStateUp,
network.shared,
network.tenantId,
+ network.availabilityZone,
network.networkType,
network.physicalNetworkName,
network.segmentationId,
@@ -206,6 +210,14 @@ public class Network {
}
/**
+ * @return the availability zone of the Network
+ */
+ @Nullable
+ public String getAvailabilityZone() {
+ return availabilityZone;
+ }
+
+ /**
* @return the networkType of the Network
*/
@Nullable
@@ -304,7 +316,7 @@ public class Network {
@Override
public int hashCode() {
- return Objects.hashCode(id, status, subnets, name, adminStateUp, shared, tenantId, networkType,
+ return Objects.hashCode(id, status, subnets, name, adminStateUp, shared, tenantId, availabilityZone, networkType,
physicalNetworkName, segmentationId, external, portSecurity, profileId, multicastIp, segmentAdd, segmentDel,
memberSegments, segments, networkFlavor);
}
@@ -323,6 +335,7 @@ public class Network {
&& Objects.equal(this.adminStateUp, that.adminStateUp)
&& Objects.equal(this.shared, that.shared)
&& Objects.equal(this.tenantId, that.tenantId)
+ && Objects.equal(this.availabilityZone, that.availabilityZone)
&& Objects.equal(this.networkType, that.networkType)
&& Objects.equal(this.physicalNetworkName, that.physicalNetworkName)
&& Objects.equal(this.segmentationId, that.segmentationId)
@@ -347,6 +360,7 @@ public class Network {
.add("adminStateUp", adminStateUp)
.add("shared", shared)
.add("tenantId", tenantId)
+ .add("availabilityZone", availabilityZone)
.add("networkType", networkType)
.add("physicalNetworkName", physicalNetworkName)
.add("segmentationId", segmentationId)
@@ -437,6 +451,17 @@ public class Network {
}
/**
+ * Provide the availabilityZone to the Network's Builder.
+ *
+ * @return the Builder.
+ * @see Network#getAvailabilityZone() ()
+ */
+ public ParameterizedBuilderType availabilityZone(String availabilityZone) {
+ network.availabilityZone = availabilityZone;
+ return self();
+ }
+
+ /**
* Provide the networkType to the Network's Builder.
*
* @return the Builder.
http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Networks.java
----------------------------------------------------------------------
diff --git a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Networks.java b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Networks.java
index 9b3bf10..f47e13b 100644
--- a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Networks.java
+++ b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/domain/Networks.java
@@ -17,7 +17,9 @@
package org.jclouds.openstack.neutron.v2.domain;
import java.beans.ConstructorProperties;
+import java.util.Set;
+import com.google.common.base.Predicate;
import org.jclouds.openstack.v2_0.domain.Link;
import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
@@ -33,4 +35,25 @@ public class Networks extends PaginatedCollection<Network> {
protected Networks(Iterable<Network> networks, Iterable<Link> networksLinks) {
super(networks, networksLinks);
}
+
+ public static class Predicates {
+
+ public static Predicate<Network> externalNetworks(final String availabilityZone) {
+ return new Predicate<Network>() {
+ @Override
+ public boolean apply(Network network) {
+ return availabilityZone.equals(network.getAvailabilityZone()) && network.getExternal();
+ }
+ };
+ }
+
+ public static Predicate<Network> namedNetworks(final Set<String> names) {
+ return new Predicate<Network>() {
+ @Override
+ public boolean apply(Network network) {
+ return names.contains(network.getName());
+ }
+ };
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApi.java b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApi.java
deleted file mode 100644
index a00bc04..0000000
--- a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApi.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * 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.neutron.v2.extensions;
-
-import javax.inject.Named;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.core.MediaType;
-
-import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
-import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.collect.PagedIterable;
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest;
-import org.jclouds.openstack.neutron.v2.domain.FloatingIP;
-import org.jclouds.openstack.neutron.v2.domain.FloatingIPs;
-import org.jclouds.openstack.neutron.v2.fallbacks.EmptyFloatingIPsFallback;
-import org.jclouds.openstack.neutron.v2.functions.FloatingIPsToPagedIterable;
-import org.jclouds.openstack.neutron.v2.functions.ParseFloatingIPs;
-import org.jclouds.openstack.v2_0.ServiceType;
-import org.jclouds.openstack.v2_0.options.PaginationOptions;
-import org.jclouds.openstack.v2_0.services.Extension;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.ResponseParser;
-import org.jclouds.rest.annotations.SelectJson;
-import org.jclouds.rest.annotations.Transform;
-import org.jclouds.rest.annotations.WrapWith;
-
-import com.google.common.annotations.Beta;
-
-/**
- * Provides access to Floating IP operations for the OpenStack Networking (Neutron) v2 API.
- * <p/>
- * A floating IP is an IP address on an external network, which is associated with a specific port, and optionally a
- * specific IP address, on a private OpenStack Networking network. Therefore a floating IP allows access to an
- * instance on a private network from an external network. Floating IPs can only be defined on networks for which the
- * attribute floatingip:external (by the external network extension) has been set to True.
- */
-@Beta
-@Path("/floatingips")
-@RequestFilters(AuthenticateRequest.class)
-@Consumes(MediaType.APPLICATION_JSON)
-@Extension(of = ServiceType.NETWORK, namespace = ExtensionNamespaces.L3_ROUTER, name = "Neutron L3 Router", alias = "router")
-public interface FloatingIPApi {
-
- /**
- * Returns a list of floating IPs to which the tenant has access. Default policy settings return only
- * those floating IPs that are owned by the tenant who submits the request, unless the request is submitted by an
- * user with administrative rights.
- *
- * @return the list of all floatingIP references configured for the tenant.
- */
- @Named("floatingip:list")
- @GET
- @Transform(FloatingIPsToPagedIterable.class)
- @ResponseParser(ParseFloatingIPs.class)
- @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
- PagedIterable<FloatingIP> list();
-
- /**
- * @return the list of all floatingIP references configured for the tenant.
- */
- @Named("floatingip:list")
- @GET
- @ResponseParser(ParseFloatingIPs.class)
- @Fallback(EmptyFloatingIPsFallback.class)
- FloatingIPs list(PaginationOptions options);
-
- /**
- * Returns the details for a specific floating IP.
- *
- * @param id the id of the floatingIP to return
- * @return FloatingIPs collection or empty if not found
- */
- @Named("floatingip:get")
- @GET
- @Path("/{id}")
- @SelectJson("floatingip")
- @Fallback(NullOnNotFoundOr404.class)
- @Nullable
- FloatingIP get(@PathParam("id") String id);
-
- /**
- * Creates a floating IP.
- *
- * @param createFloatingIP Options for creating a Floating IP
- * @return the newly created Floating IP
- */
- @Named("floatingip:create")
- @POST
- @SelectJson("floatingip")
- FloatingIP create(@WrapWith("floatingip") FloatingIP.CreateFloatingIP createFloatingIP);
-
- /**
- * Update a Floating IP
- *
- * @param id the id of the Floating IP to update
- * @param updateFloatingIP Contains only the attributes to update
- * @return The modified Floating IP
- */
- @Named("floatingip:update")
- @PUT
- @Path("/{id}")
- @SelectJson("floatingip")
- FloatingIP update(@PathParam("id") String id, @WrapWith("floatingip") FloatingIP.UpdateFloatingIP updateFloatingIP);
-
- /**
- * Deletes the specified floatingIP
- *
- * @param id the id of the floatingIP to delete
- * @return true if delete successful, false if not
- */
- @Named("floatingip:delete")
- @DELETE
- @Path("/{id}")
- @Fallback(FalseOnNotFoundOr404.class)
- boolean delete(@PathParam("id") String id);
-}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/features/FloatingIPApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/features/FloatingIPApi.java b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/features/FloatingIPApi.java
new file mode 100644
index 0000000..43d7b3c
--- /dev/null
+++ b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/features/FloatingIPApi.java
@@ -0,0 +1,136 @@
+/*
+ * 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.neutron.v2.features;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
+import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.collect.PagedIterable;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest;
+import org.jclouds.openstack.neutron.v2.domain.FloatingIP;
+import org.jclouds.openstack.neutron.v2.domain.FloatingIPs;
+import org.jclouds.openstack.neutron.v2.fallbacks.EmptyFloatingIPsFallback;
+import org.jclouds.openstack.neutron.v2.functions.FloatingIPsToPagedIterable;
+import org.jclouds.openstack.neutron.v2.functions.ParseFloatingIPs;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.Transform;
+import org.jclouds.rest.annotations.WrapWith;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Provides access to Floating IP operations for the OpenStack Networking (Neutron) v2 API.
+ * <p/>
+ * A floating IP is an IP address on an external network, which is associated with a specific port, and optionally a
+ * specific IP address, on a private OpenStack Networking network. Therefore a floating IP allows access to an
+ * instance on a private network from an external network. Floating IPs can only be defined on networks for which the
+ * attribute floatingip:external (by the external network extension) has been set to True.
+ */
+@Beta
+@Path("/floatingips")
+@RequestFilters(AuthenticateRequest.class)
+@Consumes(MediaType.APPLICATION_JSON)
+public interface FloatingIPApi {
+
+ /**
+ * Returns a list of floating IPs to which the tenant has access. Default policy settings return only
+ * those floating IPs that are owned by the tenant who submits the request, unless the request is submitted by an
+ * user with administrative rights.
+ *
+ * @return the list of all floatingIP references configured for the tenant.
+ */
+ @Named("floatingip:list")
+ @GET
+ @Transform(FloatingIPsToPagedIterable.class)
+ @ResponseParser(ParseFloatingIPs.class)
+ @Fallback(EmptyPagedIterableOnNotFoundOr404.class)
+ PagedIterable<FloatingIP> list();
+
+ /**
+ * @return the list of all floatingIP references configured for the tenant.
+ */
+ @Named("floatingip:list")
+ @GET
+ @ResponseParser(ParseFloatingIPs.class)
+ @Fallback(EmptyFloatingIPsFallback.class)
+ FloatingIPs list(PaginationOptions options);
+
+ /**
+ * Returns the details for a specific floating IP.
+ *
+ * @param id the id of the floatingIP to return
+ * @return FloatingIPs collection or empty if not found
+ */
+ @Named("floatingip:get")
+ @GET
+ @Path("/{id}")
+ @SelectJson("floatingip")
+ @Fallback(NullOnNotFoundOr404.class)
+ @Nullable
+ FloatingIP get(@PathParam("id") String id);
+
+ /**
+ * Creates a floating IP.
+ *
+ * @param createFloatingIP Options for creating a Floating IP
+ * @return the newly created Floating IP
+ */
+ @Named("floatingip:create")
+ @POST
+ @SelectJson("floatingip")
+ FloatingIP create(@WrapWith("floatingip") FloatingIP.CreateFloatingIP createFloatingIP);
+
+ /**
+ * Update a Floating IP
+ *
+ * @param id the id of the Floating IP to update
+ * @param updateFloatingIP Contains only the attributes to update
+ * @return The modified Floating IP
+ */
+ @Named("floatingip:update")
+ @PUT
+ @Path("/{id}")
+ @SelectJson("floatingip")
+ FloatingIP update(@PathParam("id") String id, @WrapWith("floatingip") FloatingIP.UpdateFloatingIP updateFloatingIP);
+
+ /**
+ * Deletes the specified floatingIP
+ *
+ * @param id the id of the floatingIP to delete
+ * @return true if delete successful, false if not
+ */
+ @Named("floatingip:delete")
+ @DELETE
+ @Path("/{id}")
+ @Fallback(FalseOnNotFoundOr404.class)
+ boolean delete(@PathParam("id") String id);
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/FloatingIPsToPagedIterable.java
----------------------------------------------------------------------
diff --git a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/FloatingIPsToPagedIterable.java b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/FloatingIPsToPagedIterable.java
index 4d54d1f..058ea3f 100644
--- a/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/FloatingIPsToPagedIterable.java
+++ b/apis/openstack-neutron/src/main/java/org/jclouds/openstack/neutron/v2/functions/FloatingIPsToPagedIterable.java
@@ -22,7 +22,7 @@ import org.jclouds.collect.IterableWithMarker;
import org.jclouds.collect.internal.Arg0ToPagedIterable;
import org.jclouds.openstack.neutron.v2.NeutronApi;
import org.jclouds.openstack.neutron.v2.domain.FloatingIP;
-import org.jclouds.openstack.neutron.v2.extensions.FloatingIPApi;
+import org.jclouds.openstack.neutron.v2.features.FloatingIPApi;
import org.jclouds.openstack.v2_0.options.PaginationOptions;
import javax.inject.Inject;
@@ -44,7 +44,7 @@ public class FloatingIPsToPagedIterable extends Arg0ToPagedIterable.FromCaller<F
@Override
protected Function<Object, IterableWithMarker<FloatingIP>> markerToNextForArg0(Optional<Object> arg0) {
String region = arg0.isPresent() ? arg0.get().toString() : null;
- final FloatingIPApi floatingIPApi = api.getFloatingIPApi(region).get();
+ final FloatingIPApi floatingIPApi = api.getFloatingIPApi(region);
return new Function<Object, IterableWithMarker<FloatingIP>>() {
@SuppressWarnings("unchecked")
http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FWaaSApiMockTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FWaaSApiMockTest.java b/apis/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FWaaSApiMockTest.java
index ae84c36..595b22f 100644
--- a/apis/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FWaaSApiMockTest.java
+++ b/apis/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FWaaSApiMockTest.java
@@ -36,6 +36,7 @@ import org.jclouds.openstack.neutron.v2.domain.FloatingIP;
import org.jclouds.openstack.neutron.v2.domain.UpdateFirewall;
import org.jclouds.openstack.neutron.v2.domain.UpdateFirewallPolicy;
import org.jclouds.openstack.neutron.v2.domain.UpdateFirewallRule;
+import org.jclouds.openstack.neutron.v2.features.FloatingIPApi;
import org.jclouds.openstack.neutron.v2.internal.BaseNeutronApiMockTest;
import org.jclouds.openstack.v2_0.domain.PaginatedCollection;
import org.jclouds.openstack.v2_0.options.PaginationOptions;
@@ -130,13 +131,12 @@ public class FWaaSApiMockTest extends BaseNeutronApiMockTest {
public void testListPagedFirewall() throws IOException, InterruptedException, URISyntaxException {
MockWebServer server = mockOpenStackServer();
server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
- server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/extension_list.json"))));
server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(200).setBody(stringFromResource("/floatingip_list_response_paged1.json"))));
server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(200).setBody(stringFromResource("/floatingip_list_response_paged2.json"))));
try {
NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
- FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne").get();
+ FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne");
// Note: Lazy! Have to actually look at the collection.
List<FloatingIP> floatingIPs = api.list().concat().toList();
@@ -144,9 +144,8 @@ public class FWaaSApiMockTest extends BaseNeutronApiMockTest {
/*
* Check request
*/
- assertEquals(server.getRequestCount(), 4);
+ assertEquals(server.getRequestCount(), 3);
assertAuthentication(server);
- assertExtensions(server, uriApiVersion + "");
assertRequest(server.takeRequest(), "GET", uriApiVersion + "/floatingips");
assertRequest(server.takeRequest(), "GET", uriApiVersion + "/floatingips?marker=71c1e68c-171a-4aa2-aca5-50ea153a3718");
http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApiLiveTest.java b/apis/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApiLiveTest.java
deleted file mode 100644
index a3d5f3d..0000000
--- a/apis/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApiLiveTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.neutron.v2.extensions;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
-import java.util.Set;
-
-import org.jclouds.openstack.neutron.v2.domain.FloatingIP;
-import org.jclouds.openstack.neutron.v2.domain.IP;
-import org.jclouds.openstack.neutron.v2.domain.Network;
-import org.jclouds.openstack.neutron.v2.domain.NetworkType;
-import org.jclouds.openstack.neutron.v2.domain.Subnet;
-import org.jclouds.openstack.neutron.v2.features.NetworkApi;
-import org.jclouds.openstack.neutron.v2.features.SubnetApi;
-import org.jclouds.openstack.neutron.v2.internal.BaseNeutronApiLiveTest;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableSet;
-
-/**
- * Tests parsing and Guice wiring of RouterApi
- */
-@Test(groups = "live", testName = "FloatingIPApiLiveTest")
-public class FloatingIPApiLiveTest extends BaseNeutronApiLiveTest {
-
- public void testCreateUpdateAndDeleteFloatingIP() {
- for (String region : api.getConfiguredRegions()) {
-
- SubnetApi subnetApi = api.getSubnetApi(region);
- FloatingIPApi floatingIPApi = api.getFloatingIPApi(region).get();
- NetworkApi networkApi = api.getNetworkApi(region);
-
- FloatingIP floatingIPGet = null;
- String ipv4SubnetId = null;
- Network network = null;
-
- try {
- network = networkApi.create(
- Network.createBuilder("jclouds-network-test").external(true).networkType(NetworkType.LOCAL).build());
- assertNotNull(network);
-
- ipv4SubnetId = subnetApi.create(Subnet.createBuilder(network.getId(), "198.51.100.0/24").ipVersion(4)
- .name("JClouds-Live-IPv4-Subnet").build()).getId();
-
- floatingIPApi.create(FloatingIP.createBuilder(network.getId()).build());
-
- /* List and Get test */
- Set<FloatingIP> floatingIPs = floatingIPApi.list().concat().toSet();
- FloatingIP floatingIPList = floatingIPs.iterator().next();
- floatingIPGet = floatingIPApi.get(floatingIPList.getId());
-
- assertNotNull(floatingIPGet);
- assertEquals(floatingIPGet, floatingIPList);
- }
- finally {
- try {
- assertTrue(floatingIPApi.delete(floatingIPGet.getId()));
- }
- finally {
- try {
- assertTrue(subnetApi.delete(ipv4SubnetId));
- }
- finally {
- assertTrue(networkApi.delete(network.getId()));
- }
- }
- }
- }
- }
-
- public Set<IP> getFixedAddresses(String subnetId) {
- return ImmutableSet.of(IP.builder().subnetId(subnetId).build());
- }
-}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApiMockTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApiMockTest.java b/apis/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApiMockTest.java
deleted file mode 100644
index ea368ee..0000000
--- a/apis/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/extensions/FloatingIPApiMockTest.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * 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.neutron.v2.extensions;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertNull;
-import static org.testng.Assert.assertTrue;
-
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.util.List;
-
-import org.jclouds.openstack.neutron.v2.NeutronApi;
-import org.jclouds.openstack.neutron.v2.domain.FloatingIP;
-import org.jclouds.openstack.neutron.v2.domain.FloatingIPs;
-import org.jclouds.openstack.neutron.v2.internal.BaseNeutronApiMockTest;
-import org.jclouds.openstack.v2_0.options.PaginationOptions;
-import org.testng.annotations.Test;
-
-import com.squareup.okhttp.mockwebserver.MockResponse;
-import com.squareup.okhttp.mockwebserver.MockWebServer;
-
-/**
- * Tests Floating Api Guice wiring and parsing
- *
- */
-@Test
-public class FloatingIPApiMockTest extends BaseNeutronApiMockTest {
-
- public void testCreateFloatingIP() throws IOException, InterruptedException, URISyntaxException {
- MockWebServer server = mockOpenStackServer();
- server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
- server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/extension_list.json"))));
- server.enqueue(addCommonHeaders(
- new MockResponse().setResponseCode(201).setBody(stringFromResource("/floatingip_create_response.json"))));
-
- try {
- NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
- FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne").get();
-
- FloatingIP.CreateFloatingIP createFip = FloatingIP.createBuilder("376da547-b977-4cfe-9cba-275c80debf57")
- .portId("ce705c24-c1ef-408a-bda3-7bbd946164ab")
- .build();
-
- FloatingIP floatingIP = api.create(createFip);
-
- /*
- * Check request
- */
- assertEquals(server.getRequestCount(), 3);
- assertAuthentication(server);
- assertExtensions(server, uriApiVersion + "");
- assertRequest(server.takeRequest(), "POST", uriApiVersion + "/floatingips", "/floatingip_create_request.json");
-
- /*
- * Check response
- */
- assertNotNull(floatingIP);
- assertEquals(floatingIP.getRouterId(), "d23abc8d-2991-4a55-ba98-2aaea84cc72f");
- assertEquals(floatingIP.getTenantId(), "4969c491a3c74ee4af974e6d800c62de");
- assertEquals(floatingIP.getFloatingNetworkId(), "376da547-b977-4cfe-9cba-275c80debf57");
- assertEquals(floatingIP.getFixedIpAddress(), "10.0.0.3");
- assertEquals(floatingIP.getFloatingIpAddress(), "172.24.4.228");
- assertEquals(floatingIP.getPortId(), "ce705c24-c1ef-408a-bda3-7bbd946164ab");
- assertEquals(floatingIP.getId(), "2f245a7b-796b-4f26-9cf9-9e82d248fda7");
-
- } finally {
- server.shutdown();
- }
- }
-
- public void testListSpecificPageFloatingIP() throws IOException, InterruptedException, URISyntaxException {
- MockWebServer server = mockOpenStackServer();
- server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
- server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/extension_list.json"))));
- server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(200).setBody(stringFromResource("/floatingip_list_response_paged1.json"))));
-
- try {
- NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
- FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne").get();
-
- FloatingIPs floatingIPs = api.list(PaginationOptions.Builder.limit(2).marker("abcdefg"));
-
- /*
- * Check request
- */
- assertEquals(server.getRequestCount(), 3);
- assertAuthentication(server);
- assertExtensions(server, uriApiVersion + "");
- assertRequest(server.takeRequest(), "GET", uriApiVersion + "/floatingips?limit=2&marker=abcdefg");
-
- /*
- * Check response
- */
- assertNotNull(floatingIPs);
- assertEquals(floatingIPs.size(), 2);
- assertEquals(floatingIPs.first().get().getId(), "2f245a7b-796b-4f26-9cf9-9e82d248fda7");
- assertEquals(floatingIPs.get(1).getId(), "61cea855-49cb-4846-997d-801b70c71bdd");
- } finally {
- server.shutdown();
- }
- }
-
- public void testListPagedFloatingIP() throws IOException, InterruptedException, URISyntaxException {
- MockWebServer server = mockOpenStackServer();
- server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
- server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/extension_list.json"))));
- server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(200).setBody(stringFromResource("/floatingip_list_response_paged1.json"))));
- server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(200).setBody(stringFromResource("/floatingip_list_response_paged2.json"))));
-
- try {
- NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
- FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne").get();
-
- // Note: Lazy! Have to actually look at the collection.
- List<FloatingIP> floatingIPs = api.list().concat().toList();
-
- /*
- * Check request
- */
- assertEquals(server.getRequestCount(), 4);
- assertAuthentication(server);
- assertExtensions(server, uriApiVersion + "");
- assertRequest(server.takeRequest(), "GET", uriApiVersion + "/floatingips");
- assertRequest(server.takeRequest(), "GET", uriApiVersion + "/floatingips?marker=71c1e68c-171a-4aa2-aca5-50ea153a3718");
-
- /*
- * Check response
- */
- assertNotNull(floatingIPs);
- assertEquals(floatingIPs.size(), 4);
- assertEquals(floatingIPs.get(0).getId(), "2f245a7b-796b-4f26-9cf9-9e82d248fda7");
- assertEquals(floatingIPs.get(3).getId(), "61cea855-49cb-4846-997d-801b70c71bdd2");
- } finally {
- server.shutdown();
- }
- }
-
- public void testGetFloatingIP() throws IOException, InterruptedException, URISyntaxException {
- MockWebServer server = mockOpenStackServer();
- server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
- server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/extension_list.json"))));
- server.enqueue(addCommonHeaders(
- new MockResponse().setResponseCode(201).setBody(stringFromResource("/floatingip_get_response.json"))));
-
- try {
- NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
- FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne").get();
-
- FloatingIP floatingIP = api.get("12345");
-
- /*
- * Check request
- */
- assertEquals(server.getRequestCount(), 3);
- assertAuthentication(server);
- assertExtensions(server, uriApiVersion + "");
- assertRequest(server.takeRequest(), "GET", uriApiVersion + "/floatingips/12345");
-
- /*
- * Check response
- */
- assertNotNull(floatingIP);
- assertEquals(floatingIP.getId(), "2f245a7b-796b-4f26-9cf9-9e82d248fda7");
- assertEquals(floatingIP.getPortId(), "ce705c24-c1ef-408a-bda3-7bbd946164ab");
- assertEquals(floatingIP.getFloatingIpAddress(), "172.24.4.228");
- assertEquals(floatingIP.getFixedIpAddress(), "10.0.0.3");
- assertEquals(floatingIP.getFloatingNetworkId(), "376da547-b977-4cfe-9cba-275c80debf57");
- assertEquals(floatingIP.getRouterId(), "d23abc8d-2991-4a55-ba98-2aaea84cc72f");
- assertEquals(floatingIP.getTenantId(), "4969c491a3c74ee4af974e6d800c62de");
-
- } finally {
- server.shutdown();
- }
- }
-
- public void testUpdateFloatingIP() throws IOException, InterruptedException, URISyntaxException {
- MockWebServer server = mockOpenStackServer();
- server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
- server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/extension_list.json"))));
- server.enqueue(addCommonHeaders(
- new MockResponse().setResponseCode(201).setBody(stringFromResource("/floatingip_update_response.json"))));
-
- try {
- NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
- FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne").get();
-
- FloatingIP.UpdateFloatingIP updateFloatingIP = FloatingIP.updateBuilder()
- .portId("fc861431-0e6c-4842-a0ed-e2363f9bc3a8")
- .build();
-
- FloatingIP floatingIP = api.update("12345", updateFloatingIP);
-
- /*
- * Check request
- */
- assertEquals(server.getRequestCount(), 3);
- assertAuthentication(server);
- assertExtensions(server, uriApiVersion + "");
- assertRequest(server.takeRequest(), "PUT", uriApiVersion + "/floatingips/12345", "/floatingip_update_request.json");
-
- /*
- * Check response
- */
- assertNotNull(floatingIP);
- assertEquals(floatingIP.getPortId(), "fc861431-0e6c-4842-a0ed-e2363f9bc3a8");
-
- } finally {
- server.shutdown();
- }
- }
-
- public void testUpdateFloatingIPDissociate() throws IOException, InterruptedException, URISyntaxException {
- MockWebServer server = mockOpenStackServer();
- server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
- server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/extension_list.json"))));
- server.enqueue(addCommonHeaders(
- new MockResponse().setResponseCode(201).setBody(stringFromResource("/floatingip_update_dissociate_response.json"))));
-
- try {
- NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
- FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne").get();
-
- FloatingIP.UpdateFloatingIP updateFloatingIP = FloatingIP.updateBuilder().build();
-
- FloatingIP floatingIP = api.update("12345", updateFloatingIP);
-
- /*
- * Check request
- */
- assertEquals(server.getRequestCount(), 3);
- assertAuthentication(server);
- assertExtensions(server, uriApiVersion + "");
- assertRequest(server.takeRequest(), "PUT", uriApiVersion + "/floatingips/12345", "/floatingip_update_dissociate_request.json");
-
- /*
- * Check response
- */
- assertNotNull(floatingIP);
- assertNull(floatingIP.getPortId());
-
- } finally {
- server.shutdown();
- }
- }
-
- public void testDeleteFloatingIP() throws IOException, InterruptedException, URISyntaxException {
- MockWebServer server = mockOpenStackServer();
- server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
- server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/extension_list.json"))));
- server.enqueue(addCommonHeaders(
- new MockResponse().setResponseCode(201)));
-
- try {
- NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
- FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne").get();
-
- boolean result = api.delete("12345");
-
- /*
- * Check request
- */
- assertEquals(server.getRequestCount(), 3);
- assertAuthentication(server);
- assertExtensions(server, uriApiVersion + "");
- assertRequest(server.takeRequest(), "DELETE", uriApiVersion + "/floatingips/12345");
-
- /*
- * Check response
- */
- assertTrue(result);
- } finally {
- server.shutdown();
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/FloatingIPApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/FloatingIPApiLiveTest.java b/apis/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/FloatingIPApiLiveTest.java
new file mode 100644
index 0000000..a960884
--- /dev/null
+++ b/apis/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/FloatingIPApiLiveTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.neutron.v2.features;
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Set;
+
+import com.google.common.base.Predicate;
+import org.jclouds.openstack.neutron.v2.domain.FloatingIP;
+import org.jclouds.openstack.neutron.v2.domain.IP;
+import org.jclouds.openstack.neutron.v2.domain.Network;
+import org.jclouds.openstack.neutron.v2.internal.BaseNeutronApiLiveTest;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Tests parsing and Guice wiring of FloatingIPApi
+ */
+@Test(groups = "live", testName = "FloatingIPApiLiveTest")
+public class FloatingIPApiLiveTest extends BaseNeutronApiLiveTest {
+
+ public void testCreateUpdateAndDeleteFloatingIP() {
+ for (String region : api.getConfiguredRegions()) {
+
+ FloatingIPApi floatingIPApi = api.getFloatingIPApi(region);
+ NetworkApi networkApi = api.getNetworkApi(region);
+
+ FloatingIP floatingIPGet = null;
+ Network network;
+
+ try {
+ network = networkApi.list().concat().firstMatch(new Predicate<Network>() {
+ @Override
+ public boolean apply(Network input) {
+ return input.getExternal();
+ }
+ }).orNull();
+
+ if (network == null) Assert.fail("Cannot find a suitable external network. Please add it manually or contact your administrator");
+
+ FloatingIP floatingIP = floatingIPApi.create(FloatingIP.createBuilder(network.getId()).availabilityZone(network.getAvailabilityZone()).build());
+ /* List and Get test */
+ Set<FloatingIP> floatingIPs = floatingIPApi.list().concat().toSet();
+ floatingIPGet = floatingIPApi.get(floatingIP.getId());
+
+ assertNotNull(floatingIPGet);
+ assertTrue(floatingIPs.contains(floatingIP));
+ }
+ finally {
+ assertTrue(floatingIPApi.delete(floatingIPGet.getId()));
+ }
+ }
+ }
+
+ public Set<IP> getFixedAddresses(String subnetId) {
+ return ImmutableSet.of(IP.builder().subnetId(subnetId).build());
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/FloatingIPApiMockTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/FloatingIPApiMockTest.java b/apis/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/FloatingIPApiMockTest.java
new file mode 100644
index 0000000..b34d8ab
--- /dev/null
+++ b/apis/openstack-neutron/src/test/java/org/jclouds/openstack/neutron/v2/features/FloatingIPApiMockTest.java
@@ -0,0 +1,278 @@
+/*
+ * 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.neutron.v2.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.List;
+
+import org.jclouds.openstack.neutron.v2.NeutronApi;
+import org.jclouds.openstack.neutron.v2.domain.FloatingIP;
+import org.jclouds.openstack.neutron.v2.domain.FloatingIPs;
+import org.jclouds.openstack.neutron.v2.internal.BaseNeutronApiMockTest;
+import org.jclouds.openstack.v2_0.options.PaginationOptions;
+import org.testng.annotations.Test;
+
+import com.squareup.okhttp.mockwebserver.MockResponse;
+import com.squareup.okhttp.mockwebserver.MockWebServer;
+
+/**
+ * Tests Floating Api Guice wiring and parsing
+ *
+ */
+@Test
+public class FloatingIPApiMockTest extends BaseNeutronApiMockTest {
+
+ public void testCreateFloatingIP() throws IOException, InterruptedException, URISyntaxException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(
+ new MockResponse().setResponseCode(201).setBody(stringFromResource("/floatingip_create_response.json"))));
+
+ try {
+ NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
+ FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne");
+
+ FloatingIP.CreateFloatingIP createFip = FloatingIP.createBuilder("376da547-b977-4cfe-9cba-275c80debf57")
+ .portId("ce705c24-c1ef-408a-bda3-7bbd946164ab")
+ .build();
+
+ FloatingIP floatingIP = api.create(createFip);
+
+ /*
+ * Check request
+ */
+ assertEquals(server.getRequestCount(), 2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "POST", uriApiVersion + "/floatingips", "/floatingip_create_request.json");
+
+ /*
+ * Check response
+ */
+ assertNotNull(floatingIP);
+ assertEquals(floatingIP.getRouterId(), "d23abc8d-2991-4a55-ba98-2aaea84cc72f");
+ assertEquals(floatingIP.getTenantId(), "4969c491a3c74ee4af974e6d800c62de");
+ assertEquals(floatingIP.getFloatingNetworkId(), "376da547-b977-4cfe-9cba-275c80debf57");
+ assertEquals(floatingIP.getFixedIpAddress(), "10.0.0.3");
+ assertEquals(floatingIP.getFloatingIpAddress(), "172.24.4.228");
+ assertEquals(floatingIP.getPortId(), "ce705c24-c1ef-408a-bda3-7bbd946164ab");
+ assertEquals(floatingIP.getId(), "2f245a7b-796b-4f26-9cf9-9e82d248fda7");
+
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testListSpecificPageFloatingIP() throws IOException, InterruptedException, URISyntaxException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(200).setBody(stringFromResource("/floatingip_list_response_paged1.json"))));
+
+ try {
+ NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
+ FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne");
+
+ FloatingIPs floatingIPs = api.list(PaginationOptions.Builder.limit(2).marker("abcdefg"));
+
+ /*
+ * Check request
+ */
+ assertEquals(server.getRequestCount(), 2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", uriApiVersion + "/floatingips?limit=2&marker=abcdefg");
+
+ /*
+ * Check response
+ */
+ assertNotNull(floatingIPs);
+ assertEquals(floatingIPs.size(), 2);
+ assertEquals(floatingIPs.first().get().getId(), "2f245a7b-796b-4f26-9cf9-9e82d248fda7");
+ assertEquals(floatingIPs.get(1).getId(), "61cea855-49cb-4846-997d-801b70c71bdd");
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testListPagedFloatingIP() throws IOException, InterruptedException, URISyntaxException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(200).setBody(stringFromResource("/floatingip_list_response_paged1.json"))));
+ server.enqueue(addCommonHeaders(new MockResponse().setResponseCode(200).setBody(stringFromResource("/floatingip_list_response_paged2.json"))));
+
+ try {
+ NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
+ FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne");
+
+ // Note: Lazy! Have to actually look at the collection.
+ List<FloatingIP> floatingIPs = api.list().concat().toList();
+
+ /*
+ * Check request
+ */
+ assertEquals(server.getRequestCount(), 3);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", uriApiVersion + "/floatingips");
+ assertRequest(server.takeRequest(), "GET", uriApiVersion + "/floatingips?marker=71c1e68c-171a-4aa2-aca5-50ea153a3718");
+
+ /*
+ * Check response
+ */
+ assertNotNull(floatingIPs);
+ assertEquals(floatingIPs.size(), 4);
+ assertEquals(floatingIPs.get(0).getId(), "2f245a7b-796b-4f26-9cf9-9e82d248fda7");
+ assertEquals(floatingIPs.get(3).getId(), "61cea855-49cb-4846-997d-801b70c71bdd2");
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testGetFloatingIP() throws IOException, InterruptedException, URISyntaxException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(
+ new MockResponse().setResponseCode(201).setBody(stringFromResource("/floatingip_get_response.json"))));
+
+ try {
+ NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
+ FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne");
+
+ FloatingIP floatingIP = api.get("12345");
+
+ /*
+ * Check request
+ */
+ assertEquals(server.getRequestCount(), 2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "GET", uriApiVersion + "/floatingips/12345");
+
+ /*
+ * Check response
+ */
+ assertNotNull(floatingIP);
+ assertEquals(floatingIP.getId(), "2f245a7b-796b-4f26-9cf9-9e82d248fda7");
+ assertEquals(floatingIP.getPortId(), "ce705c24-c1ef-408a-bda3-7bbd946164ab");
+ assertEquals(floatingIP.getFloatingIpAddress(), "172.24.4.228");
+ assertEquals(floatingIP.getFixedIpAddress(), "10.0.0.3");
+ assertEquals(floatingIP.getFloatingNetworkId(), "376da547-b977-4cfe-9cba-275c80debf57");
+ assertEquals(floatingIP.getRouterId(), "d23abc8d-2991-4a55-ba98-2aaea84cc72f");
+ assertEquals(floatingIP.getTenantId(), "4969c491a3c74ee4af974e6d800c62de");
+
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testUpdateFloatingIP() throws IOException, InterruptedException, URISyntaxException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(
+ new MockResponse().setResponseCode(201).setBody(stringFromResource("/floatingip_update_response.json"))));
+
+ try {
+ NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
+ FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne");
+
+ FloatingIP.UpdateFloatingIP updateFloatingIP = FloatingIP.updateBuilder()
+ .portId("fc861431-0e6c-4842-a0ed-e2363f9bc3a8")
+ .build();
+
+ FloatingIP floatingIP = api.update("12345", updateFloatingIP);
+
+ /*
+ * Check request
+ */
+ assertEquals(server.getRequestCount(), 2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "PUT", uriApiVersion + "/floatingips/12345", "/floatingip_update_request.json");
+
+ /*
+ * Check response
+ */
+ assertNotNull(floatingIP);
+ assertEquals(floatingIP.getPortId(), "fc861431-0e6c-4842-a0ed-e2363f9bc3a8");
+
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testUpdateFloatingIPDissociate() throws IOException, InterruptedException, URISyntaxException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(
+ new MockResponse().setResponseCode(201).setBody(stringFromResource("/floatingip_update_dissociate_response.json"))));
+
+ try {
+ NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
+ FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne");
+
+ FloatingIP.UpdateFloatingIP updateFloatingIP = FloatingIP.updateBuilder().build();
+
+ FloatingIP floatingIP = api.update("12345", updateFloatingIP);
+
+ /*
+ * Check request
+ */
+ assertEquals(server.getRequestCount(), 2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "PUT", uriApiVersion + "/floatingips/12345", "/floatingip_update_dissociate_request.json");
+
+ /*
+ * Check response
+ */
+ assertNotNull(floatingIP);
+ assertNull(floatingIP.getPortId());
+
+ } finally {
+ server.shutdown();
+ }
+ }
+
+ public void testDeleteFloatingIP() throws IOException, InterruptedException, URISyntaxException {
+ MockWebServer server = mockOpenStackServer();
+ server.enqueue(addCommonHeaders(new MockResponse().setBody(stringFromResource("/access.json"))));
+ server.enqueue(addCommonHeaders(
+ new MockResponse().setResponseCode(201)));
+
+ try {
+ NeutronApi neutronApi = api(server.getUrl("/").toString(), "openstack-neutron", overrides);
+ FloatingIPApi api = neutronApi.getFloatingIPApi("RegionOne");
+
+ boolean result = api.delete("12345");
+
+ /*
+ * Check request
+ */
+ assertEquals(server.getRequestCount(), 2);
+ assertAuthentication(server);
+ assertRequest(server.takeRequest(), "DELETE", uriApiVersion + "/floatingips/12345");
+
+ /*
+ * Check response
+ */
+ assertTrue(result);
+ } finally {
+ server.shutdown();
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/50ae6828/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/config/NovaComputeServiceContextModule.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/config/NovaComputeServiceContextModule.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/config/NovaComputeServiceContextModule.java
index 4402d47..867f260 100644
--- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/config/NovaComputeServiceContextModule.java
+++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v2_0/compute/config/NovaComputeServiceContextModule.java
@@ -71,7 +71,7 @@ import org.jclouds.openstack.nova.v2_0.compute.loaders.FindSecurityGroupOrCreate
import org.jclouds.openstack.nova.v2_0.compute.loaders.LoadFloatingIpsForInstance;
import org.jclouds.openstack.nova.v2_0.compute.options.NovaTemplateOptions;
import org.jclouds.openstack.nova.v2_0.compute.strategy.ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet;
-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.Server;
import org.jclouds.openstack.nova.v2_0.domain.Server.Status;
import org.jclouds.openstack.nova.v2_0.domain.regionscoped.FlavorInRegion;
@@ -137,7 +137,7 @@ public class NovaComputeServiceContextModule extends
bind(TemplateOptions.class).to(NovaTemplateOptions.class);
- bind(new TypeLiteral<CacheLoader<RegionAndId, Iterable<? extends FloatingIP>>>() {
+ bind(new TypeLiteral<CacheLoader<RegionAndId, Iterable<? extends FloatingIpForServer>>>() {
}).annotatedWith(Names.named("FLOATINGIP")).to(LoadFloatingIpsForInstance.class);
bind(new TypeLiteral<Function<RegionSecurityGroupNameAndPorts, SecurityGroup>>() {
@@ -214,8 +214,8 @@ public class NovaComputeServiceContextModule extends
@Provides
@Singleton
@Named("FLOATINGIP")
- protected final LoadingCache<RegionAndId, Iterable<? extends FloatingIP>> instanceToFloatingIps(
- @Named("FLOATINGIP") CacheLoader<RegionAndId, Iterable<? extends FloatingIP>> in) {
+ protected final LoadingCache<RegionAndId, Iterable<? extends FloatingIpForServer>> instanceToFloatingIps(
+ @Named("FLOATINGIP") CacheLoader<RegionAndId, Iterable<? extends FloatingIpForServer>> in) {
return CacheBuilder.newBuilder().build(in);
}
@@ -313,7 +313,7 @@ public class NovaComputeServiceContextModule extends
@Override
public boolean apply(RegionAndId regionAndId) {
- checkNotNull(regionAndId, "regionAndId");
+ checkNotNull(regionAndId, "serverId");
Server server = api.getServerApi(regionAndId.getRegion()).get(regionAndId.getId());
if (server == null) {
throw new IllegalStateException(String.format("Server %s not found.", regionAndId.getId()));
@@ -333,7 +333,7 @@ public class NovaComputeServiceContextModule extends
@Override
public boolean apply(RegionAndId regionAndId) {
- checkNotNull(regionAndId, "regionAndId");
+ checkNotNull(regionAndId, "serverId");
Server server = api.getServerApi(regionAndId.getRegion()).get(regionAndId.getId());
return server == null;
}
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/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 ed41190..80663ab 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
@@ -25,19 +25,29 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
+import javax.annotation.Nullable;
import javax.annotation.Resource;
-import javax.inject.Inject;
import javax.inject.Named;
+import com.google.common.collect.Sets;
+import org.jclouds.Context;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
+import org.jclouds.openstack.neutron.v2.NeutronApi;
+import org.jclouds.openstack.neutron.v2.domain.Network;
+import org.jclouds.openstack.neutron.v2.domain.Networks;
+import org.jclouds.openstack.neutron.v2.domain.Port;
+import org.jclouds.openstack.neutron.v2.features.NetworkApi;
+import org.jclouds.openstack.neutron.v2.features.PortApi;
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.FloatingIpForServer;
import org.jclouds.openstack.nova.v2_0.domain.regionscoped.RegionAndId;
import org.jclouds.openstack.nova.v2_0.extensions.FloatingIPApi;
+import org.jclouds.rest.ApiContext;
import org.jclouds.rest.InsufficientResourcesException;
import org.jclouds.rest.ResourceNotFoundException;
@@ -45,30 +55,38 @@ import com.google.common.base.Function;
import com.google.common.base.MoreObjects;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
+import com.google.inject.Inject;
/**
* A function for adding and allocating an ip to a node
*/
-public class AllocateAndAddFloatingIpToNode implements
- Function<AtomicReference<NodeAndNovaTemplateOptions>, AtomicReference<NodeMetadata>> {
+public class AllocateAndAddFloatingIpToNode
+ implements Function<AtomicReference<NodeAndNovaTemplateOptions>, AtomicReference<NodeMetadata>> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
+ @Inject(optional = true)
+ @Named("openstack-neutron")
+ private Supplier<Context> neutronContextSupplier;
+
private final Predicate<AtomicReference<NodeMetadata>> nodeRunning;
private final NovaApi novaApi;
- private final LoadingCache<RegionAndId, Iterable<? extends FloatingIP>> floatingIpCache;
+ private final LoadingCache<RegionAndId, Iterable<? extends FloatingIpForServer>> floatingIpCache;
private final CleanupResources cleanupResources;
@Inject
- public AllocateAndAddFloatingIpToNode(@Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>> nodeRunning,
- NovaApi novaApi, @Named("FLOATINGIP") LoadingCache<RegionAndId, Iterable<? extends FloatingIP>> floatingIpCache, CleanupResources cleanupResources) {
+ public AllocateAndAddFloatingIpToNode(
+ @Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>> nodeRunning, NovaApi novaApi,
+ @Named("FLOATINGIP") LoadingCache<RegionAndId, Iterable<? extends FloatingIpForServer>> floatingIpCache,
+ CleanupResources cleanupResources) {
this.nodeRunning = checkNotNull(nodeRunning, "nodeRunning");
this.novaApi = checkNotNull(novaApi, "novaApi");
this.floatingIpCache = checkNotNull(floatingIpCache, "floatingIpCache");
@@ -78,37 +96,80 @@ public class AllocateAndAddFloatingIpToNode implements
@Override
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();
+ final NodeMetadata node = input.get().getNodeMetadata().get();
// node's location is a host
String regionId = node.getLocation().getParent().getId();
- FloatingIPApi floatingIpApi = novaApi.getFloatingIPApi(regionId).get();
Optional<Set<String>> poolNames = input.get().getNovaTemplateOptions().get().getFloatingIpPoolNames();
- Optional<FloatingIP> ip = allocateFloatingIPForNode(floatingIpApi, poolNames, node.getId());
- if (!ip.isPresent()) {
- cleanupResources.apply(node);
- 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());
+ String availabilityZone = getAvailabilityZoneFromTemplateOptionsOrDefault(input, regionId);
+
+ if (isNeutronLinked()) {
+ org.jclouds.openstack.neutron.v2.features.FloatingIPApi neutronFloatingApi = getFloatingIPApi(regionId);
+ final Optional<Port> optionalPort = getPortApi(regionId).list().concat().firstMatch(new Predicate<Port>() {
+ @Override
+ public boolean apply(@Nullable Port input) {
+ return input.getDeviceId().equals(node.getProviderId());
+ }
+ });
+ if (optionalPort.isPresent()) {
+ Optional<org.jclouds.openstack.neutron.v2.domain.FloatingIP> floatingIPOptional = tryFindExistingFloatingIp(neutronFloatingApi, availabilityZone);
+ org.jclouds.openstack.neutron.v2.domain.FloatingIP floatingIP;
+ if (floatingIPOptional.isPresent()) {
+ floatingIP = floatingIPOptional.get();
+ } else {
+ floatingIP = createFloatingIpUsingNeutron(neutronFloatingApi, node, poolNames, availabilityZone);
+ }
+
+ org.jclouds.openstack.neutron.v2.domain.FloatingIP ip = neutronFloatingApi.update(floatingIP.getId(),
+ org.jclouds.openstack.neutron.v2.domain.FloatingIP.UpdateFloatingIP
+ .updateBuilder()
+ .portId(optionalPort.get().getId())
+ .build());
- floatingIpApi.addToServer(ip.get().getIp(), node.getProviderId());
+ input.get().getNodeMetadata().set(NodeMetadataBuilder.fromNodeMetadata(node).publicAddresses(ImmutableSet.of(ip.getFloatingIpAddress())).build());
+ } else {
+ logger.error("Node %s doesn't have a port to attach a floating IP", node);
+ throw new IllegalStateException("Missing required port in node: " + node);
+ }
+ } else { // try nova
+ FloatingIPApi floatingIpApi = novaApi.getFloatingIPApi(regionId).get();
+
+ Optional<FloatingIP> ip = allocateFloatingIPForNodeOnNova(floatingIpApi, poolNames, node.getId());
+ if (!ip.isPresent()) {
+ cleanupResources.apply(node);
+ 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());
- input.get().getNodeMetadata().set(NodeMetadataBuilder.fromNodeMetadata(node).publicAddresses(ImmutableSet.of(ip.get().getIp())).build());
- floatingIpCache.asMap().putIfAbsent(RegionAndId.fromSlashEncoded(node.getId()), ImmutableList.of(ip.get()));
+ floatingIpApi.addToServer(ip.get().getIp(), node.getProviderId());
+ input.get().getNodeMetadata().set(NodeMetadataBuilder.fromNodeMetadata(node).publicAddresses(ImmutableSet.of(ip.get().getIp())).build());
+ floatingIpCache.asMap().put(RegionAndId.fromSlashEncoded(node.getId()), ImmutableList.of(FloatingIpForServer.create(RegionAndId.fromSlashEncoded(node.getId()), ip.get().getId(), ip.get().getIp())));
+ }
return input.get().getNodeMetadata();
}
+ private String getAvailabilityZoneFromTemplateOptionsOrDefault(AtomicReference<NodeAndNovaTemplateOptions> input, String regionId) {
+ return MoreObjects.firstNonNull(input.get().getNovaTemplateOptions().get().getAvailabilityZone(),
+ Iterables.get(novaApi.getAvailabilityZoneApi(regionId).get().listAvailabilityZones(), 0).getName());
+ }
+
/**
* 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
+ * @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 synchronized Optional<FloatingIP> allocateFloatingIPForNode(FloatingIPApi floatingIpApi, Optional<Set<String>> poolNames, String nodeID) {
+ private synchronized Optional<FloatingIP> allocateFloatingIPForNodeOnNova(FloatingIPApi floatingIpApi,
+ Optional<Set<String>> poolNames, String nodeID) {
- FloatingIP ip = null;
+ FloatingIP ip;
// 1.) Attempt to allocate from optionally passed poolNames
if (poolNames.isPresent()) {
@@ -118,9 +179,11 @@ public class AllocateAndAddFloatingIpToNode implements
ip = floatingIpApi.allocateFromPool(poolName);
return Optional.of(ip);
} catch (ResourceNotFoundException ex) {
- logger.trace("<< [%s] failed to allocate floating IP from pool %s for node(%s)", ex.getMessage(), poolName, nodeID);
+ logger.trace("<< [%s] failed to allocate floating IP from pool %s for node(%s)", ex.getMessage(),
+ poolName, nodeID);
} catch (InsufficientResourcesException ire) {
- logger.trace("<< [%s] failed to allocate floating IP from pool %s for node(%s)", ire.getMessage(), poolName, nodeID);
+ logger.trace("<< [%s] failed to allocate floating IP from pool %s for node(%s)", ire.getMessage(),
+ poolName, nodeID);
}
}
}
@@ -136,17 +199,18 @@ public class AllocateAndAddFloatingIpToNode implements
logger.trace("<< [%s] failed to create floating IP for node(%s)", ire.getMessage(), nodeID);
}
- // 3.) If no IP was found make final attempt by searching through list of available IP's
+ // 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>() {
+ List<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.
if (unassignedIps.isEmpty()) {
return Optional.absent();
@@ -156,8 +220,72 @@ public class AllocateAndAddFloatingIpToNode implements
return Optional.fromNullable(ip);
}
+ private Optional<org.jclouds.openstack.neutron.v2.domain.FloatingIP> tryFindExistingFloatingIp(org.jclouds.openstack.neutron.v2.features.FloatingIPApi neutronFloatingApi, final String availabilityZone) {
+ Optional<org.jclouds.openstack.neutron.v2.domain.FloatingIP> floatingIPOptional = neutronFloatingApi.list().concat().firstMatch(new Predicate<org.jclouds.openstack.neutron.v2.domain.FloatingIP>() {
+ @Override
+ public boolean apply(@Nullable org.jclouds.openstack.neutron.v2.domain.FloatingIP input) {
+ return input.getPortId() == null && input.getAvailabilityZone().equals(availabilityZone);
+ }
+ });
+ return floatingIPOptional;
+ }
+
+ private org.jclouds.openstack.neutron.v2.domain.FloatingIP createFloatingIpUsingNeutron(org.jclouds.openstack.neutron.v2.features.FloatingIPApi neutronFloatingApi,
+ NodeMetadata node, Optional<Set<String>> poolNames, final String availabilityZone) {
+ String regionId = node.getLocation().getParent().getId();
+ List<Network> networks = getSuitableNetworks(regionId, availabilityZone, poolNames.or(Sets.<String>newHashSet()));
+ org.jclouds.openstack.neutron.v2.domain.FloatingIP floatingIP = null;
+ for (Network network : networks) {
+ try {
+ logger.debug(">> allocating floating IP from network %s for node(%s)", network, node);
+ org.jclouds.openstack.neutron.v2.domain.FloatingIP createFloatingIP = org.jclouds.openstack.neutron.v2.domain.FloatingIP.CreateFloatingIP.createBuilder(network.getId()).availabilityZone(network.getAvailabilityZone()).build();
+ floatingIP = neutronFloatingApi.create((org.jclouds.openstack.neutron.v2.domain.FloatingIP.CreateFloatingIP) createFloatingIP);
+ logger.debug(">> allocated floating IP(%s) from network(%s) for node(%s)", floatingIP, network, node);
+ floatingIpCache.asMap().put(RegionAndId.fromSlashEncoded(node.getId()), ImmutableList.of(FloatingIpForServer.create(RegionAndId.fromSlashEncoded(node.getId()), floatingIP.getId(), floatingIP.getFloatingIpAddress())));
+ return floatingIP;
+ } catch (Exception ex) {
+ logger.trace("<< [%s] failed to allocate a floating IP from network %s for node(%s)", ex.getMessage(), network, node);
+ }
+ }
+
+ throw new IllegalStateException("Failed to allocate a floating IP for node " + node + ".\n" +
+ "Failed to find suitable external networks or to allocate from poolNames specified: "
+ + Iterables.toString(poolNames.get()));
+
+ }
+
+
+ /**
+ * Get all suitable networks to allocate a floating ip
+ *
+ * It will prefer networks specified using the poolNames first and then the external networks in the given availability zone
+ */
+ private List<Network> getSuitableNetworks(String regionId, final String availabilityZone, final Set<String> poolNames) {
+ List<Network> allNetworks = getNetworkApi(regionId).list().concat().toList();
+ Iterable<Network> externalNetworks = Iterables.filter(allNetworks, Networks.Predicates.externalNetworks(availabilityZone));
+ Iterable<Network> networksFromPoolName = Iterables.filter(allNetworks, Networks.Predicates.namedNetworks(poolNames));
+ return Lists.newArrayList(Iterables.concat(networksFromPoolName, externalNetworks));
+ }
+
+ 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);
+ }
+
+ private PortApi getPortApi(String regionId) {
+ return ((ApiContext<NeutronApi>) neutronContextSupplier.get()).getApi().getPortApi(regionId);
+ }
+
+ private NetworkApi getNetworkApi(String regionId) {
+ return ((ApiContext<NeutronApi>) neutronContextSupplier.get()).getApi().getNetworkApi(regionId);
+ }
+
@Override
public String toString() {
return MoreObjects.toStringHelper("AllocateAndAddFloatingIpToNode").toString();
}
+
}