diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaAsyncClient.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaAsyncClient.java index 9f5d32b035..d00d5cce54 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaAsyncClient.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaAsyncClient.java @@ -28,6 +28,7 @@ import org.jclouds.openstack.nova.v1_1.extensions.HostAdministrationAsyncClient; import org.jclouds.openstack.nova.v1_1.extensions.KeyPairAsyncClient; import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupAsyncClient; import org.jclouds.openstack.nova.v1_1.extensions.SimpleTenantUsageAsyncClient; +import org.jclouds.openstack.nova.v1_1.extensions.VirtualInterfaceAsyncClient; import org.jclouds.openstack.nova.v1_1.extensions.VolumeAsyncClient; import org.jclouds.openstack.nova.v1_1.features.ExtensionAsyncClient; import org.jclouds.openstack.nova.v1_1.features.FlavorAsyncClient; @@ -127,4 +128,11 @@ public interface NovaAsyncClient { @Delegate Optional getVolumeExtensionForZone( @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); + + /** + * Provides asynchronous access to Virtual Interface features. + */ + @Delegate + Optional getVirtualInterfaceExtensionForZone( + @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); } diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaClient.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaClient.java index 37dc81e228..866351c539 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaClient.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaClient.java @@ -30,6 +30,7 @@ import org.jclouds.openstack.nova.v1_1.extensions.HostAdministrationClient; import org.jclouds.openstack.nova.v1_1.extensions.KeyPairClient; import org.jclouds.openstack.nova.v1_1.extensions.SecurityGroupClient; import org.jclouds.openstack.nova.v1_1.extensions.SimpleTenantUsageClient; +import org.jclouds.openstack.nova.v1_1.extensions.VirtualInterfaceClient; import org.jclouds.openstack.nova.v1_1.extensions.VolumeClient; import org.jclouds.openstack.nova.v1_1.features.ExtensionClient; import org.jclouds.openstack.nova.v1_1.features.FlavorClient; @@ -131,4 +132,11 @@ public interface NovaClient { Optional getVolumeExtensionForZone( @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); + /** + * Provides synchronous access to Virtual Interface features. + */ + @Delegate + Optional getVirtualInterfaceExtensionForZone( + @EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone); + } diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaRestClientModule.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaRestClientModule.java index 8a9a6e20bc..f2956abe61 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaRestClientModule.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaRestClientModule.java @@ -74,6 +74,7 @@ public class NovaRestClientModule extends RestClientModule builder() { + return new ConcreteBuilder(); + } + + public Builder toBuilder() { + return new ConcreteBuilder().fromVirtualInterface(this); + } + + public static abstract class Builder> { + protected abstract T self(); + + private String id; + private String macAddress; + + /** + * @see VirtualInterface#getId() + */ + public T id(String id) { + this.id = id; + return self(); + } + + /** + * @see VirtualInterface#getMacAddress() + */ + public T macAddress(String macAddress) { + this.macAddress = macAddress; + return self(); + } + + public VirtualInterface build() { + return new VirtualInterface(this); + } + + public T fromVirtualInterface(VirtualInterface in) { + return this + .id(in.getId()) + .macAddress(in.getMacAddress()) + ; + } + + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + private final String id; + @SerializedName(value="mac_address") + private final String macAddress; + + protected VirtualInterface(Builder builder) { + this.id = checkNotNull(builder.id, "id"); + this.macAddress = checkNotNull(builder.macAddress, "macAddress"); + } + + public String getId() { + return this.id; + } + + public String getMacAddress() { + return this.macAddress; + } + + @Override + public int hashCode() { + return Objects.hashCode(id, macAddress); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + VirtualInterface that = VirtualInterface.class.cast(obj); + return Objects.equal(this.id, that.id) + && Objects.equal(this.macAddress, that.macAddress) + ; + } + + protected ToStringHelper string() { + return Objects.toStringHelper("") + .add("id", id) + .add("macAddress", macAddress) + ; + } + + @Override + public String toString() { + return string().toString(); + } + +} \ No newline at end of file diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/VirtualInterfaceAsyncClient.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/VirtualInterfaceAsyncClient.java new file mode 100644 index 0000000000..4cd07f6737 --- /dev/null +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/VirtualInterfaceAsyncClient.java @@ -0,0 +1,60 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.v1_1.extensions; + +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.MediaType; + +import org.jclouds.openstack.filters.AuthenticateRequest; +import org.jclouds.openstack.nova.v1_1.domain.VirtualInterface; +import org.jclouds.openstack.services.Extension; +import org.jclouds.openstack.services.ServiceType; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SelectJson; +import org.jclouds.rest.annotations.SkipEncoding; +import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides asynchronous access to Virtual Interface features (VIFs). + * + * @see VirtualInterfaceClient + * @author Adam Lowe + */ +@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VIRTUAL_INTERFACES) +@SkipEncoding({'/', '='}) +@RequestFilters(AuthenticateRequest.class) +public interface VirtualInterfaceAsyncClient { + /** + * @see VirtualInterfaceClient#listVirtualInterfacesForServer(String) + */ + @GET + @SelectJson("virtual_interfaces") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/servers/{server_id}/os-virtual-interfaces") + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listVirtualInterfacesForServer(@PathParam("server_id") String serverId); +} diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/VirtualInterfaceClient.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/VirtualInterfaceClient.java new file mode 100644 index 0000000000..acf7692228 --- /dev/null +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/extensions/VirtualInterfaceClient.java @@ -0,0 +1,46 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.v1_1.extensions; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.openstack.nova.v1_1.domain.VirtualInterface; +import org.jclouds.openstack.services.Extension; +import org.jclouds.openstack.services.ServiceType; + +/** + * Provides synchronous access to Virtual Interface features (VIFs). + * + * @see VirtualInterfaceAsyncClient + * @author Adam Lowe + */ +@Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.VIRTUAL_INTERFACES) +@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS) +public interface VirtualInterfaceClient { + + /** + * Returns the list of Virtual Interfaces for a given instance. + * + * @return the list of snapshots + */ + Set listVirtualInterfacesForServer(String serverId); + +} diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/functions/PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/functions/PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.java index 85406b5e4c..b55e0830f2 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/functions/PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/functions/PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.java @@ -68,6 +68,8 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio URI.create("http://docs.openstack.org/compute/ext/hosts/api/v1.1")) .put(URI.create(ExtensionNamespaces.VOLUMES), URI.create("http://docs.openstack.org/compute/ext/volumes/api/v1.1")) + .put(URI.create(ExtensionNamespaces.VIRTUAL_INTERFACES), + URI.create("http://docs.openstack.org/compute/ext/virtual_interfaces/api/v1.1")) .build(); @Inject diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/VirtualInterfaceClientExpectTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/VirtualInterfaceClientExpectTest.java new file mode 100644 index 0000000000..553be0dac1 --- /dev/null +++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/VirtualInterfaceClientExpectTest.java @@ -0,0 +1,65 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.v1_1.extensions; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +import java.net.URI; + +import org.jclouds.openstack.nova.v1_1.domain.VirtualInterface; +import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientExpectTest; +import org.testng.annotations.Test; + +import com.google.common.collect.Iterables; + +/** + * Tests parsing and guice wiring of VirtualInterfaceClient + * + * @author Adam Lowe + */ +@Test(groups = "live", testName = "VirtualInterfaceClientLiveTest") +public class VirtualInterfaceClientExpectTest extends BaseNovaClientExpectTest { + + public void testListVirtualInterfaces() { + URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/os-virtual-interfaces"); + VirtualInterfaceClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, + responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse, + standardRequestBuilder(endpoint).build(), + standardResponseBuilder(200).payload(payloadFromResource("/virtual_interfaces_list.json")).build() + ).getVirtualInterfaceExtensionForZone("az-1.region-a.geo-1").get(); + + VirtualInterface vif = Iterables.getOnlyElement(client.listVirtualInterfacesForServer("1")); + assertEquals(vif.getId(), "02315827-b05c-4668-9c05-75c68838074a"); + assertEquals(vif.getMacAddress(), "fa:16:3e:09:71:34"); + } + + public void testListVirtualInterfacesFailNotFound() { + URI endpoint = URI.create("https://compute.north.host/v1.1/3456/servers/1/os-virtual-interfaces"); + VirtualInterfaceClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, + responseWithKeystoneAccess, extensionsOfNovaRequest, extensionsOfNovaResponse, + standardRequestBuilder(endpoint).build(), + standardResponseBuilder(404).build() + ).getVirtualInterfaceExtensionForZone("az-1.region-a.geo-1").get(); + + assertTrue(client.listVirtualInterfacesForServer("1").isEmpty()); + } +} \ No newline at end of file diff --git a/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/VirtualInterfaceClientLiveTest.java b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/VirtualInterfaceClientLiveTest.java new file mode 100644 index 0000000000..9190502fe9 --- /dev/null +++ b/apis/openstack-nova/src/test/java/org/jclouds/openstack/nova/v1_1/extensions/VirtualInterfaceClientLiveTest.java @@ -0,0 +1,70 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.v1_1.extensions; + +import static org.testng.Assert.assertNotNull; + +import java.util.Set; + +import org.jclouds.openstack.nova.v1_1.domain.Server; +import org.jclouds.openstack.nova.v1_1.domain.VirtualInterface; +import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import com.google.common.base.Optional; +import com.google.common.collect.Iterables; + +/** + * Tests behavior of VirtualInterfaceClient + * + * @author Adam Lowe + */ +@Test(groups = "live", testName = "VirtualInterfaceClientLiveTest", singleThreaded = true) +public class VirtualInterfaceClientLiveTest extends BaseNovaClientLiveTest { + private Optional clientOption; + private String zone; + + + @BeforeClass(groups = {"integration", "live"}) + @Override + public void setupContext() { + super.setupContext(); + zone = Iterables.getLast(novaContext.getApi().getConfiguredZones(), "nova"); + clientOption = novaContext.getApi().getVirtualInterfaceExtensionForZone(zone); + } + + public void testListVirtualInterfaces() { + if (clientOption.isPresent()) { + Server testServer = null; + try { + testServer = createServerInZone(zone); + Set results = clientOption.get().listVirtualInterfacesForServer(testServer.getId()); + for (VirtualInterface vif : results) { + assertNotNull(vif.getId()); + assertNotNull(vif.getMacAddress()); + } + } finally { + if (testServer != null) { + novaContext.getApi().getServerClientForZone(zone).deleteServer(testServer.getId()); + } + } + } +} +} diff --git a/apis/openstack-nova/src/test/resources/virtual_interfaces_list.json b/apis/openstack-nova/src/test/resources/virtual_interfaces_list.json new file mode 100644 index 0000000000..7df0182f03 --- /dev/null +++ b/apis/openstack-nova/src/test/resources/virtual_interfaces_list.json @@ -0,0 +1 @@ +{"virtual_interfaces": [{"id": "02315827-b05c-4668-9c05-75c68838074a", "mac_address": "fa:16:3e:09:71:34"}]} \ No newline at end of file