diff --git a/common/openstack/src/main/java/org/jclouds/openstack/services/ServiceType.java b/common/openstack/src/main/java/org/jclouds/openstack/services/ServiceType.java index 4d97aec0fd..abd5f667af 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/services/ServiceType.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/services/ServiceType.java @@ -45,4 +45,8 @@ public interface ServiceType { * Identity Service (Keystone) */ public static final String IDENTITY = "identity"; + /** + * Network Service (Quantum) + */ + public static final String NETWORK = "network"; } \ No newline at end of file diff --git a/common/openstack/src/test/java/org/jclouds/openstack/keystone/v2_0/parse/ParseAccessTest.java b/common/openstack/src/test/java/org/jclouds/openstack/keystone/v2_0/parse/ParseAccessTest.java index 2a95cb6947..b4dd8e8277 100644 --- a/common/openstack/src/test/java/org/jclouds/openstack/keystone/v2_0/parse/ParseAccessTest.java +++ b/common/openstack/src/test/java/org/jclouds/openstack/keystone/v2_0/parse/ParseAccessTest.java @@ -95,8 +95,19 @@ public class ParseAccessTest extends BaseItemParserTest { .tenantId("3456") .publicURL(URI.create("https://az-3.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456")) .region("az-3.region-a.geo-1") - .versionId("1.1").build()).build() - ).build(); + .versionId("1.1").build()).build(), + + Service.builder().name("Quantum Service").type("network").endpoints( + Endpoint.builder() + .tenantId("3456") + .publicURL(URI.create("https://csnode.jclouds.org:9696/v1.0/tenants/3456")) + .internalURL(URI.create("https://csnode.jclouds.org:9696/v1.0/tenants/3456")) + .adminURL(URI.create("https://csnode.jclouds.org:9696/v1.0")) + .region("region-a.geo-1") + .versionId("1.0").build() + ).build()) + + .build(); } } diff --git a/common/openstack/src/test/resources/keystoneAuthResponse.json b/common/openstack/src/test/resources/keystoneAuthResponse.json index a781a32a89..33b0ccd2c1 100644 --- a/common/openstack/src/test/resources/keystoneAuthResponse.json +++ b/common/openstack/src/test/resources/keystoneAuthResponse.json @@ -109,6 +109,20 @@ "versionList": "https:\/\/az-3.region-a.geo-1.compute.hpcloudsvc.com" } ] - } + }, + { + "type": "network", + "name": "Quantum Service", + "endpoints": [{ + "tenantId": "3456", + "adminURL": "https://csnode.jclouds.org:9696/v1.0", + "region": "region-a.geo-1", + "versionId": "1.0", + "publicURL": "https://csnode.jclouds.org:9696/v1.0/tenants/3456", + "internalURL": "https://csnode.jclouds.org:9696/v1.0/tenants/3456" + }], + "endpoints_links": [] + } ] +} } \ No newline at end of file diff --git a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java index a0268d6b9a..101d863ba0 100644 --- a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java +++ b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java @@ -409,7 +409,9 @@ public class RestAnnotationProcessor { } this.caller = caller; try { - callerEndpoint = getEndpointFor(caller.getMethod(), caller.getArgs(), injector); + UriBuilder builder = uriBuilderProvider.get().uri(getEndpointFor(caller.getMethod(), caller.getArgs(), injector)); + Multimap tokenValues = addPathAndGetTokens(caller.getMethod().getDeclaringClass(), caller.getMethod(), caller.getArgs(), builder); + callerEndpoint = builder.buildFromEncodedMap(Maps2.convertUnsafe(tokenValues)); } catch (IllegalStateException e) { } catch (ExecutionException e) { Throwables.propagate(e); @@ -785,7 +787,7 @@ public class RestAnnotationProcessor { } public static URI addHostIfMissing(URI original, URI withHost) { - checkNotNull(withHost, "URI witHost cannot be null"); + checkNotNull(withHost, "URI withHost cannot be null"); checkArgument(withHost.getHost() != null, "URI withHost must have host:" + withHost); if (original == null) diff --git a/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java b/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java index cd979810a5..996a6c2163 100644 --- a/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java +++ b/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java @@ -223,6 +223,10 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest { @Delegate public Optional getOptionalCallee(@EndpointParam URI endpoint); + + @Delegate + @Path("/testing/testing/{wibble}") + public Callee getCalleeWithPath(@EndpointParam URI endpoint, @PathParam("wibble") String wibble); } @Timeout(duration = 10, timeUnit = TimeUnit.NANOSECONDS) @@ -253,6 +257,10 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest { @Delegate public Optional getOptionalCallee(@EndpointParam URI endpoint); + + @Delegate + @Path("/testing/testing/{wibble}") + public AsyncCallee getCalleeWithPath(@EndpointParam URI endpoint, @PathParam("wibble") String wibble); } public void testAsyncDelegateIsLazyLoadedAndRequestIncludesVersionAndPath() throws InterruptedException, @@ -330,6 +338,30 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest { } + public void testAsyncDelegateWithPathParamIsLazyLoadedAndRequestIncludesEndpointVersionAndPath() throws InterruptedException, + ExecutionException { + Injector child = injectorForCaller(new HttpCommandExecutorService() { + + @Override + public Future submit(HttpCommand command) { + assertEquals(command.getCurrentRequest().getRequestLine(), "GET http://howdyboys/testing/testing/thepathparam/client/1/foo HTTP/1.1"); + return Futures.immediateFuture(HttpResponse.builder().build()); + } + + }); + + try { + child.getInstance(AsyncCallee.class); + assert false : "Callee shouldn't be bound yet"; + } catch (ConfigurationException e) { + + } + + child.getInstance(AsyncCaller.class).getCalleeWithPath(URI.create("http://howdyboys"), "thepathparam").onePath("foo").get(); + + assertEquals(child.getInstance(AsyncCaller.class).getURI(), URI.create("http://localhost:1111")); + } + public void testAsyncDelegateIsLazyLoadedAndRequestIncludesEndpointVersionAndPathOptionalPresent() throws InterruptedException, ExecutionException { Injector child = injectorForCaller(new HttpCommandExecutorService() { diff --git a/labs/openstack-quantum/pom.xml b/labs/openstack-quantum/pom.xml new file mode 100644 index 0000000000..39b4ff1922 --- /dev/null +++ b/labs/openstack-quantum/pom.xml @@ -0,0 +1,139 @@ + + + + 4.0.0 + + org.jclouds + jclouds-project + 1.5.0-SNAPSHOT + ../../project/pom.xml + + org.jclouds.labs + openstack-quantum + jcloud openstack-quantum api + jclouds components to access an implementation of OpenStack Quantum + bundle + + + + http://localhost:5000 + + 1.0 + + FIXME_IDENTITY + FIXME_CREDENTIALS + passwordCredentials + + + + + org.jclouds.common + openstack-common + ${project.version} + + + org.jclouds + jclouds-core + ${project.version} + + + org.jclouds + jclouds-core + ${project.version} + test-jar + test + + + org.jclouds.common + openstack-common + ${project.version} + test-jar + test + + + org.jclouds.driver + jclouds-slf4j + ${project.version} + test + + + ch.qos.logback + logback-classic + 1.0.0 + test + + + + + + live + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration + integration-test + + test + + + + ${test.openstack-quantum.endpoint} + ${test.openstack-quantum.api-version} + ${test.openstack-quantum.build-version} + ${test.openstack-quantum.identity} + ${test.openstack-quantum.credential} + ${test.jclouds.keystone.credential-type} + + + + + + + + + + + + + + org.apache.felix + maven-bundle-plugin + + + ${project.artifactId} + org.jclouds.openstack.quantum.v1_0*;version="${project.version}" + + org.jclouds.rest.internal;version="${project.version}", + org.jclouds*;version="${project.version}", + * + + + + + + + + diff --git a/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/QuantumApiMetadata.java b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/QuantumApiMetadata.java new file mode 100644 index 0000000000..6511ee029e --- /dev/null +++ b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/QuantumApiMetadata.java @@ -0,0 +1,99 @@ +/** + * 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.quantum.v1_0; + +import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE; + +import java.net.URI; +import java.util.Properties; + +import org.jclouds.apis.ApiMetadata; +import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties; +import org.jclouds.openstack.quantum.v1_0.config.QuantumRestClientModule; +import org.jclouds.openstack.services.ServiceType; +import org.jclouds.rest.RestContext; +import org.jclouds.rest.internal.BaseRestApiMetadata; + +import com.google.common.collect.ImmutableSet; +import com.google.common.reflect.TypeToken; +import com.google.inject.Module; + +/** + * Implementation of {@link ApiMetadata} for Quantum 1.0 API + * + * @author Adam Lowe + */ +public class QuantumApiMetadata extends BaseRestApiMetadata { + /** The serialVersionUID */ + private static final long serialVersionUID = -7273686435105663195L; + + public static final TypeToken> CONTEXT_TOKEN = new TypeToken>() { + private static final long serialVersionUID = -3493117927790861884L; + }; + + @Override + public Builder toBuilder() { + return new Builder().fromApiMetadata(this); + } + + public QuantumApiMetadata() { + this(new Builder()); + } + + protected QuantumApiMetadata(Builder builder) { + super(builder); + } + + public static Properties defaultProperties() { + Properties properties = BaseRestApiMetadata.defaultProperties(); + properties.setProperty(SERVICE_TYPE, ServiceType.NETWORK); + // TODO: this doesn't actually do anything yet. + properties.setProperty(KeystoneProperties.VERSION, "2.0"); + return properties; + } + + public static class Builder extends BaseRestApiMetadata.Builder { + + protected Builder() { + super(QuantumClient.class, QuantumAsyncClient.class); + id("openstack-quantum") + .name("OpenStack Quantum API") + .identityName("tenantId:user") + .credentialName("password") + .documentation(URI.create("http://docs.openstack.org/api/openstack-network/1.0/content/")) + .version("1.0") + .defaultEndpoint("http://localhost:5000") + .defaultProperties(QuantumApiMetadata.defaultProperties()) + .defaultModules(ImmutableSet.>of(QuantumRestClientModule.class)); + } + + @Override + public QuantumApiMetadata build() { + return new QuantumApiMetadata(this); + } + + @Override + public Builder fromApiMetadata(ApiMetadata in) { + super.fromApiMetadata(in); + return this; + } + + } + +} diff --git a/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/QuantumAsyncClient.java b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/QuantumAsyncClient.java new file mode 100644 index 0000000000..98ffeb386c --- /dev/null +++ b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/QuantumAsyncClient.java @@ -0,0 +1,66 @@ +/** + * 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.quantum.v1_0; + +import java.util.Set; + +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; + +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.location.Region; +import org.jclouds.location.functions.RegionToEndpoint; +import org.jclouds.openstack.quantum.v1_0.features.NetworkAsyncClient; +import org.jclouds.openstack.quantum.v1_0.features.PortAsyncClient; +import org.jclouds.rest.annotations.Delegate; +import org.jclouds.rest.annotations.EndpointParam; + +import com.google.inject.Provides; + +/** + * Provides asynchronous access to Quantum via their REST API. + *

+ * + * @see QuantumClient + * @see api doc + * @author Adam Lowe + */ +public interface QuantumAsyncClient { + /** + * + * @return the Region codes configured + */ + @Provides + @Region + Set getConfiguredRegions(); + + /** + * Provides asynchronous access to Network features. + */ + @Delegate + NetworkAsyncClient getNetworkClientForRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region); + + /** + * Provides asynchronous access to Port features. + */ + @Delegate + @Path("/networks/{net}") + PortAsyncClient getPortClientForRegionAndNetwork(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region, + @PathParam("net") String networkId); +} diff --git a/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/QuantumClient.java b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/QuantumClient.java new file mode 100644 index 0000000000..d670036eb8 --- /dev/null +++ b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/QuantumClient.java @@ -0,0 +1,68 @@ +/** + * 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.quantum.v1_0; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.location.Region; +import org.jclouds.location.functions.RegionToEndpoint; +import org.jclouds.openstack.quantum.v1_0.features.NetworkClient; +import org.jclouds.openstack.quantum.v1_0.features.PortClient; +import org.jclouds.rest.annotations.Delegate; +import org.jclouds.rest.annotations.EndpointParam; + +import com.google.inject.Provides; + +/** + * Provides synchronous access to Quantum. + *

+ * + * @author Adam Lowe + * @see QuantumAsyncClient + * @see api doc + */ +@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) +public interface QuantumClient { + /** + * @return the Region codes configured + */ + @Provides + @Region + Set getConfiguredRegions(); + + /** + * Provides synchronous access to Network features. + */ + @Delegate + NetworkClient getNetworkClientForRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region); + + /** + * Provides synchronous access to Port features. + */ + @Delegate + @Path("/networks/{net}") + PortClient getPortClientForRegionAndNetwork(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region, + @PathParam("net") String networkId); +} diff --git a/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/config/QuantumProperties.java b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/config/QuantumProperties.java new file mode 100644 index 0000000000..2577b7c9a7 --- /dev/null +++ b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/config/QuantumProperties.java @@ -0,0 +1,28 @@ +/** + * 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.quantum.v1_0.config; + +/** + * Configuration properties and constants used in openstack Quantum connections. + * + * @author Adam Lowe + */ +public class QuantumProperties { + +} diff --git a/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/config/QuantumRestClientModule.java b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/config/QuantumRestClientModule.java new file mode 100644 index 0000000000..4017df5257 --- /dev/null +++ b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/config/QuantumRestClientModule.java @@ -0,0 +1,82 @@ +/** + * 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.quantum.v1_0.config; + +import java.util.Map; + +import org.jclouds.http.HttpErrorHandler; +import org.jclouds.http.annotation.ClientError; +import org.jclouds.http.annotation.Redirection; +import org.jclouds.http.annotation.ServerError; +import org.jclouds.json.config.GsonModule.DateAdapter; +import org.jclouds.json.config.GsonModule.Iso8601DateAdapter; +import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule; +import org.jclouds.openstack.quantum.v1_0.QuantumAsyncClient; +import org.jclouds.openstack.quantum.v1_0.QuantumClient; +import org.jclouds.openstack.quantum.v1_0.features.NetworkAsyncClient; +import org.jclouds.openstack.quantum.v1_0.features.NetworkClient; +import org.jclouds.openstack.quantum.v1_0.features.PortAsyncClient; +import org.jclouds.openstack.quantum.v1_0.features.PortClient; +import org.jclouds.openstack.quantum.v1_0.handlers.QuantumErrorHandler; +import org.jclouds.rest.ConfiguresRestClient; +import org.jclouds.rest.config.RestClientModule; + +import com.google.common.collect.ImmutableMap; + +/** + * Configures the Quantum connection. + * + * @author Adam Lowe + */ +@ConfiguresRestClient +public class QuantumRestClientModule extends RestClientModule { + + public static final Map, Class> DELEGATE_MAP = ImmutableMap., Class> builder() + .put(NetworkClient.class, NetworkAsyncClient.class) + .put(PortClient.class, PortAsyncClient.class) + .build(); + + public QuantumRestClientModule() { + super(DELEGATE_MAP); + } + + @Override + protected void configure() { + bind(DateAdapter.class).to(Iso8601DateAdapter.class); + super.configure(); + } + + @Override + protected void installLocations() { + // TODO: select this from KeystoneProperties.VERSION; note you select from + // a guice provided + // property, so it will have to come from somewhere else, maybe we move + // this to the the + // ContextBuilder + install(KeystoneAuthenticationModule.forRegions()); + super.installLocations(); + } + + @Override + protected void bindErrorHandlers() { + bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(QuantumErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(QuantumErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(QuantumErrorHandler.class); + } +} diff --git a/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/domain/Attachment.java b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/domain/Attachment.java new file mode 100644 index 0000000000..9ff5920725 --- /dev/null +++ b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/domain/Attachment.java @@ -0,0 +1,63 @@ +/** + * 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.quantum.v1_0.domain; + +/** + * A Quantum attachment + * + * @author Adam Lowe + * @see api doc + */ +public class Attachment extends Reference { + + public static Builder builder() { + return new ConcreteBuilder(); + } + + public Builder toBuilder() { + return new ConcreteBuilder().fromAttachment(this); + } + + public static abstract class Builder> extends Reference.Builder { + protected abstract T self(); + + public Attachment build() { + return new Attachment(this); + } + + public T fromAttachment(Attachment in) { + return super.fromReference(in); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + protected Attachment(Builder builder) { + super(builder); + } + + protected Attachment() { + // for GSON + } +} \ No newline at end of file diff --git a/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/domain/Network.java b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/domain/Network.java new file mode 100644 index 0000000000..fd3e3cf850 --- /dev/null +++ b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/domain/Network.java @@ -0,0 +1,105 @@ +/** + * 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.quantum.v1_0.domain; + +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * A Quantum network + * + * @author Adam Lowe + * @see api doc + */ +public class Network extends Reference { + + public static Builder builder() { + return new ConcreteBuilder(); + } + + public Builder toBuilder() { + return new ConcreteBuilder().fromNetwork(this); + } + + public static abstract class Builder> extends Reference.Builder { + protected abstract T self(); + + private String name; + + /** + * @see Network#getName() + */ + public T name(String name) { + this.name = name; + return self(); + } + + public Network build() { + return new Network(this); + } + + public T fromNetwork(Network in) { + return super.fromReference(in).name(in.getName()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + private final String name; + + protected Network(Builder builder) { + super(builder); + this.name = checkNotNull(builder.name, "name"); + } + + protected Network() { + // for GSON + this.name = null; + } + + /** + */ + public String getName() { + return this.name; + } + + @Override + public int hashCode() { + return Objects.hashCode(super.hashCode(), name); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + Network that = Network.class.cast(obj); + return super.equals(that) && Objects.equal(this.name, that.name); + } + + protected ToStringHelper string() { + return super.string().add("name", name); + } +} \ No newline at end of file diff --git a/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/domain/NetworkDetails.java b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/domain/NetworkDetails.java new file mode 100644 index 0000000000..8d76a0b04e --- /dev/null +++ b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/domain/NetworkDetails.java @@ -0,0 +1,112 @@ +/** + * 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.quantum.v1_0.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Collections; +import java.util.Set; + +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; +import com.google.common.collect.ImmutableSet; + +/** + * Details of a Quantum network + * + * @author Adam Lowe + * @see api doc + */ +public class NetworkDetails extends Network { + + public static Builder builder() { + return new ConcreteBuilder(); + } + + public Builder toBuilder() { + return new ConcreteBuilder().fromNetworkDetails(this); + } + + public static abstract class Builder> extends Network.Builder { + private Set ports = ImmutableSet.of(); + + /** + * @see NetworkDetails#getPorts() + */ + public T ports(Set ports) { + this.ports = ports; + return self(); + } + + public T ports(Port... in) { + return ports(ImmutableSet.copyOf(in)); + } + + public NetworkDetails build() { + return new NetworkDetails(this); + } + + public T fromNetworkDetails(NetworkDetails in) { + return super.fromNetwork(in).ports(in.getPorts()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + private final Set ports; + + protected NetworkDetails(Builder builder) { + super(builder); + this.ports = ImmutableSet.copyOf(checkNotNull(builder.ports, "ports")); + } + + protected NetworkDetails() { + // for GSON + this.ports = ImmutableSet.of(); + } + + /** + */ + public Set getPorts() { + return Collections.unmodifiableSet(this.ports); + } + + @Override + public int hashCode() { + return Objects.hashCode(ports); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + NetworkDetails that = NetworkDetails.class.cast(obj); + return super.equals(that) && Objects.equal(this.ports, that.ports); + } + + protected ToStringHelper string() { + return super.string().add("ports", ports); + } + +} \ No newline at end of file diff --git a/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/domain/Port.java b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/domain/Port.java new file mode 100644 index 0000000000..41b156620e --- /dev/null +++ b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/domain/Port.java @@ -0,0 +1,107 @@ +/** + * 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.quantum.v1_0.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; + +/** + * A Quantum port + * + * @author Adam Lowe + * @see api doc + */ +public class Port extends Reference { + + public static enum State { + ACTIVE, DOWN + } + + public static Builder builder() { + return new ConcreteBuilder(); + } + + public Builder toBuilder() { + return new ConcreteBuilder().fromPort(this); + } + + public static abstract class Builder> extends Reference.Builder { + protected abstract T self(); + + private Port.State state; + + /** + * @see Port#getState() + */ + public T state(Port.State state) { + this.state = state; + return self(); + } + + public Port build() { + return new Port(this); + } + + public T fromPort(Port in) { + return fromReference(in).state(in.getState()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + private final Port.State state; + + protected Port(Builder builder) { + super(builder); + this.state = checkNotNull(builder.state, "state"); + } + + protected Port() { + // for GSON + this.state = null; + } + + public Port.State getState() { + return this.state; + } + + @Override + public int hashCode() { + return Objects.hashCode(super.hashCode(), state); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + Port that = Port.class.cast(obj); + return super.equals(that) && Objects.equal(this.state, that.state); + } + + protected ToStringHelper string() { + return super.string().add("state", state); + } +} \ No newline at end of file diff --git a/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/domain/PortDetails.java b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/domain/PortDetails.java new file mode 100644 index 0000000000..df5474f79b --- /dev/null +++ b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/domain/PortDetails.java @@ -0,0 +1,104 @@ +/** + * 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.quantum.v1_0.domain; + +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; + +/** + * Details of a Quantum Port + * + * @author Adam Lowe + * @see api doc + */ +public class PortDetails extends Port { + + public static Builder builder() { + return new ConcreteBuilder(); + } + + public Builder toBuilder() { + return new ConcreteBuilder().fromPortDetails(this); + } + + public static abstract class Builder> extends Port.Builder { + private Attachment attachment; + + /** + * @see PortDetails#getAttachment() + */ + public T attachment(Attachment attachment) { + this.attachment = attachment; + return self(); + } + + public PortDetails build() { + return new PortDetails(this); + } + + public T fromPortDetails(PortDetails in) { + return super.fromPort(in).attachment(in.getAttachment()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + @Nullable + private final Attachment attachment; + + protected PortDetails(Builder builder) { + super(builder); + this.attachment = builder.attachment; + } + + protected PortDetails() { + // for GSON + this.attachment = null; + } + + @Nullable + public Attachment getAttachment() { + return this.attachment; + } + + @Override + public int hashCode() { + return Objects.hashCode(attachment); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + PortDetails that = PortDetails.class.cast(obj); + return super.equals(that) && Objects.equal(this.attachment, that.attachment); + } + + protected ToStringHelper string() { + return super.string().add("attachment", attachment); + } + +} \ No newline at end of file diff --git a/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/domain/Reference.java b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/domain/Reference.java new file mode 100644 index 0000000000..1f6e8a2af2 --- /dev/null +++ b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/domain/Reference.java @@ -0,0 +1,111 @@ +/** + * 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.quantum.v1_0.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; + +/** + * A wrapper around an id in the quantum api + * + * @author Adam Lowe + * @see api doc + */ +public class Reference { + + public static Builder builder() { + return new ConcreteBuilder(); + } + + public Builder toBuilder() { + return new ConcreteBuilder().fromReference(this); + } + + public static abstract class Builder> { + protected abstract T self(); + + private String id; + + /** + * @see org.jclouds.openstack.quantum.v1_0.domain.Reference#getId() + */ + public T id(String id) { + this.id = id; + return self(); + } + + public Reference build() { + return new Reference(this); + } + + public T fromReference(Reference in) { + return this.id(in.getId()); + } + } + + private static class ConcreteBuilder extends Builder { + @Override + protected ConcreteBuilder self() { + return this; + } + } + + private final String id; + + protected Reference(Builder builder) { + this.id = checkNotNull(builder.id, "id"); + } + + protected Reference() { + // for GSON + this.id = null; + } + + /** + */ + public String getId() { + return this.id; + } + + + @Override + public int hashCode() { + return Objects.hashCode(id); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + Reference that = Reference.class.cast(obj); + return Objects.equal(this.id, that.id); + } + + protected ToStringHelper string() { + return Objects.toStringHelper("").add("id", id); + } + + @Override + public String toString() { + return string().toString(); + } + +} \ No newline at end of file diff --git a/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/features/NetworkAsyncClient.java b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/features/NetworkAsyncClient.java new file mode 100644 index 0000000000..b0d114e0c8 --- /dev/null +++ b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/features/NetworkAsyncClient.java @@ -0,0 +1,121 @@ +/** + * 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.quantum.v1_0.features; + +import java.util.Set; + +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.Produces; +import javax.ws.rs.core.MediaType; + +import org.jclouds.openstack.filters.AuthenticateRequest; +import org.jclouds.openstack.quantum.v1_0.domain.Network; +import org.jclouds.openstack.quantum.v1_0.domain.NetworkDetails; +import org.jclouds.openstack.quantum.v1_0.domain.Reference; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.PayloadParam; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SelectJson; +import org.jclouds.rest.annotations.SkipEncoding; +import org.jclouds.rest.annotations.WrapWith; +import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides asynchronous access to Network operations on the openstack quantum API. + * + * @author Adam Lowe + * @see org.jclouds.openstack.quantum.v1_0.features.NetworkClient + * @see api doc + */ +@SkipEncoding({'/', '='}) +@RequestFilters(AuthenticateRequest.class) +@Consumes(MediaType.APPLICATION_JSON) +@Path("/networks") +public interface NetworkAsyncClient { + + /** + * @see NetworkClient#listReferences + */ + @GET + @SelectJson("networks") + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listReferences(); + + /** + * @see NetworkClient#list + */ + @GET + @SelectJson("networks") + @Path("/detail") + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> list(); + + /** + * @see NetworkClient#get + */ + @GET + @SelectJson("network") + @Path("/{id}") + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture get(@PathParam("id") String id); + + /** + * @see NetworkClient#getDetails + */ + @GET + @SelectJson("network") + @Path("/{id}/detail") + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getDetails(@PathParam("id") String id); + + /** + * @see NetworkClient#create + */ + @POST + @SelectJson("network") + @Produces(MediaType.APPLICATION_JSON) + @WrapWith("network") + ListenableFuture create(@PayloadParam("name") String name); + + /** + * @see NetworkClient#rename + */ + @PUT + @Produces(MediaType.APPLICATION_JSON) + @Path("/{id}") + @WrapWith("network") + ListenableFuture rename(@PathParam("id") String id, @PayloadParam("name") String name); + + /** + * @see NetworkClient#delete + */ + @DELETE + @Path("/{id}") + ListenableFuture delete(@PathParam("id") String id); + +} diff --git a/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/features/NetworkClient.java b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/features/NetworkClient.java new file mode 100644 index 0000000000..70c93a136f --- /dev/null +++ b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/features/NetworkClient.java @@ -0,0 +1,81 @@ +/** + * 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.quantum.v1_0.features; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.openstack.quantum.v1_0.domain.Network; +import org.jclouds.openstack.quantum.v1_0.domain.NetworkDetails; +import org.jclouds.openstack.quantum.v1_0.domain.Reference; + +/** + * Provides synchronous access to Network operations on the openstack quantum API. + *

+ * Each tenant can define one or more networks. A network is a virtual isolated layer-2 broadcast domain reserved to the + * tenant. A tenant can create several ports for a network, and plug virtual interfaces into these ports. + * + * @author Adam Lowe + * @see org.jclouds.openstack.quantum.v1_0.features.NetworkAsyncClient + * @see api doc + */ +@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS) +public interface NetworkClient { + + /** + * Returns the list of all networks currently defined in Quantum for the current tenant. The list provides the unique + * identifier of each network configured for the tenant. + */ + Set listReferences(); + + /** + * Returns all networks currently defined in Quantum for the current tenant. + */ + Set list(); + + /** + * Returns the specific network. + */ + Network get(String id); + + /** + * Returns the details of the specific network. + */ + NetworkDetails getDetails(String id); + + /** + * Create a new network with the specified symbolic name + */ + Reference create(String name); + + /** + * Adjusts the symbolic name of a network + * + * @param id the id of the Network to modify + * @param name the new name for the Network + */ + boolean rename(String id, String name); + + /** + * Deletes the specified network + */ + boolean delete(String id); +} diff --git a/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/features/PortAsyncClient.java b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/features/PortAsyncClient.java new file mode 100644 index 0000000000..9535bc6bf5 --- /dev/null +++ b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/features/PortAsyncClient.java @@ -0,0 +1,152 @@ +/** + * 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.quantum.v1_0.features; + +import java.util.Set; + +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.openstack.filters.AuthenticateRequest; +import org.jclouds.openstack.quantum.v1_0.domain.Attachment; +import org.jclouds.openstack.quantum.v1_0.domain.Port; +import org.jclouds.openstack.quantum.v1_0.domain.PortDetails; +import org.jclouds.openstack.quantum.v1_0.domain.Reference; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.PayloadParam; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SelectJson; +import org.jclouds.rest.annotations.SkipEncoding; +import org.jclouds.rest.annotations.WrapWith; +import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides asynchronous access to Network operations on the openstack quantum API. + * + * @author Adam Lowe + * @see PortClient + * @see api doc + */ +@SkipEncoding({'/', '='}) +@RequestFilters(AuthenticateRequest.class) +@Consumes(MediaType.APPLICATION_JSON) +@Path("/ports") +public interface PortAsyncClient { + + /** + * @see PortClient#listReferences + */ + @GET + @SelectJson("ports") + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listReferences(); + + /** + * @see PortClient#list + */ + @GET + @SelectJson("ports") + @Path("/detail") + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> list(); + + /** + * @see PortClient#get + */ + @GET + @SelectJson("port") + @Path("/{id}") + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture get(@PathParam("id") String id); + + /** + * @see PortClient#getDetails + */ + @GET + @SelectJson("port") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/{id}/detail") + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getDetails(@PathParam("id") String id); + + /** + * @see PortClient#create() + */ + @POST + @SelectJson("port") + ListenableFuture create(); + + /** + * @see PortClient#create(org.jclouds.openstack.quantum.v1_0.domain.Port.State) + */ + @POST + @SelectJson("port") + @WrapWith("port") + ListenableFuture create(@PayloadParam("state") Port.State state); + + /** + * @see PortClient#updateState + */ + @PUT + @Path("/{id}") + @WrapWith("port") + ListenableFuture updateState(@PathParam("id") String id, @PayloadParam("state") Port.State state); + + /** + * @see PortClient#delete + */ + @DELETE + @Path("/{id}") + ListenableFuture delete(@PathParam("id") String id); + + /** + * @see PortClient#showAttachment + */ + @GET + @SelectJson("attachment") + @Path("/{id}/attachment") + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture showAttachment(@PathParam("id") String portId); + + /** + * @see PortClient#plugAttachment + */ + @PUT + @Path("/{id}/attachment") + @WrapWith("attachment") + ListenableFuture plugAttachment(@PathParam("id") String portId, + @PayloadParam("id") String attachmentId); + + /** + * @see PortClient#unplugAttachment + */ + @DELETE + @Path("{id}/attachment") + ListenableFuture unplugAttachment(@PathParam("id") String portId); + +} diff --git a/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/features/PortClient.java b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/features/PortClient.java new file mode 100644 index 0000000000..9666da697c --- /dev/null +++ b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/features/PortClient.java @@ -0,0 +1,98 @@ +/** + * 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.quantum.v1_0.features; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.openstack.quantum.v1_0.domain.Attachment; +import org.jclouds.openstack.quantum.v1_0.domain.Port; +import org.jclouds.openstack.quantum.v1_0.domain.PortDetails; +import org.jclouds.openstack.quantum.v1_0.domain.Reference; + +/** + * Provides synchronous access to Port operations on the openstack quantum API. + *

+ * A port represents a virtual switch port on a logical network switch where all the interfaces attached to a given network are connected. + *

+ * A port has an administrative state which is either 'DOWN' or 'ACTIVE'. Ports which are administratively down will not be able to receive/send traffic. + * + * @author Adam Lowe + * @see PortAsyncClient + * @see api doc + */ +@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS) +public interface PortClient { + /** + * Returns the list of all ports currently defined in Quantum for the requested network + */ + Set listReferences(); + + /** + * Returns the set of ports currently defined in Quantum for the requested network. + */ + Set list(); + + /** + * Returns a specific port. + */ + Port get(String id); + + /** + * Returns a specific port in detail. + */ + PortDetails getDetails(String id); + + /** + * Create a new port on the specified network + */ + Reference create(); + + /** + * Create a new port on the specified network, with the requested state + */ + Reference create(Port.State state); + + /** + * Updates the state of a port + */ + boolean updateState(String id, Port.State state); + + /** + * Deletes a port from a network + */ + boolean delete(String id); + + /** + * Returns the attachment for the specified port. + */ + Attachment showAttachment(String portId); + + /** + * Plugs an attachment into the specified port + */ + boolean plugAttachment(String portId, String attachmentId); + + /** + * Unplugs the attachment currently plugged into the specified port + */ + boolean unplugAttachment(String portId); +} diff --git a/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/handlers/QuantumErrorHandler.java b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/handlers/QuantumErrorHandler.java new file mode 100644 index 0000000000..661bcd55eb --- /dev/null +++ b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/handlers/QuantumErrorHandler.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.quantum.v1_0.handlers; + +import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream; + +import javax.inject.Singleton; + +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpErrorHandler; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.HttpResponseException; +import org.jclouds.rest.AuthorizationException; +import org.jclouds.rest.ResourceNotFoundException; + +/** + * This will parse and set an appropriate exception on the command object. + * + * @author Adam Lowe + * + */ +// TODO: is there error spec someplace? let's type errors, etc. +@Singleton +public class QuantumErrorHandler implements HttpErrorHandler { + public void handleError(HttpCommand command, HttpResponse response) { + // it is important to always read fully and close streams + byte[] data = closeClientButKeepContentStream(response); + String message = data != null ? new String(data) : null; + + Exception exception = message != null ? new HttpResponseException(command, response, message) + : new HttpResponseException(command, response); + message = message != null ? message : String.format("%s -> %s", command.getCurrentRequest().getRequestLine(), + response.getStatusLine()); + switch (response.getStatusCode()) { + case 400: + break; + case 401: + case 403: + exception = new AuthorizationException(message, exception); + break; + case 404: + if (!command.getCurrentRequest().getMethod().equals("DELETE")) { + exception = new ResourceNotFoundException(message, exception); + } + break; + } + command.setException(exception); + } +} diff --git a/labs/openstack-quantum/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata b/labs/openstack-quantum/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata new file mode 100644 index 0000000000..ebd176c892 --- /dev/null +++ b/labs/openstack-quantum/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata @@ -0,0 +1 @@ +org.jclouds.openstack.quantum.v1_0.QuantumApiMetadata diff --git a/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/QuantumApiMetadataTest.java b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/QuantumApiMetadataTest.java new file mode 100644 index 0000000000..ce08db29fd --- /dev/null +++ b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/QuantumApiMetadataTest.java @@ -0,0 +1,37 @@ +/** + * 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.quantum.v1_0; + +import org.jclouds.View; +import org.jclouds.apis.internal.BaseApiMetadataTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; +import com.google.common.reflect.TypeToken; + +/** + * + * @author Adam Lowe + */ +@Test(groups = "unit", testName = "QuantumApiMetadataTest") +public class QuantumApiMetadataTest extends BaseApiMetadataTest { + public QuantumApiMetadataTest() { + super(new QuantumApiMetadata(), ImmutableSet.> of()); + } +} diff --git a/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/features/NetworkClientExpectTest.java b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/features/NetworkClientExpectTest.java new file mode 100644 index 0000000000..0fc695e5f7 --- /dev/null +++ b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/features/NetworkClientExpectTest.java @@ -0,0 +1,236 @@ +/** + * 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 1.1 (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-1.1 + * + * 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.quantum.v1_0.features; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; + +import java.util.Set; + +import javax.ws.rs.core.MediaType; + +import org.jclouds.openstack.quantum.v1_0.domain.Network; +import org.jclouds.openstack.quantum.v1_0.domain.NetworkDetails; +import org.jclouds.openstack.quantum.v1_0.domain.Reference; +import org.jclouds.openstack.quantum.v1_0.internal.BaseQuantumClientExpectTest; +import org.jclouds.openstack.quantum.v1_0.parse.ParseNetworkDetailsTest; +import org.jclouds.openstack.quantum.v1_0.parse.ParseNetworkTest; +import org.jclouds.rest.AuthorizationException; +import org.jclouds.rest.ResourceNotFoundException; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; + +/** + * Tests parsing and Guice wiring of NetworkClient + * + * @author Adam Lowe + */ +@Test(groups="unit", testName = "NetworkClientExpectTest") +public class NetworkClientExpectTest extends BaseQuantumClientExpectTest { + + public void testListReferencesReturns2xx() { + NetworkClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/list_network_refs.json", APPLICATION_JSON)).build()) + .getNetworkClientForRegion("region-a.geo-1"); + + Set nets = client.listReferences(); + assertEquals(nets, listOfNetworkRefs()); + } + + public void testListReferencesReturns4xx() { + NetworkClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks").build(), + standardResponseBuilder(404).build()) + .getNetworkClientForRegion("region-a.geo-1"); + + assertTrue(client.listReferences().isEmpty()); + } + + public void testListReturns2xx() { + NetworkClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/detail").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/list_networks.json", APPLICATION_JSON)).build()) + .getNetworkClientForRegion("region-a.geo-1"); + + Set nets = client.list(); + assertEquals(nets, listOfNetworks()); + } + + public void testListReturns4xx() { + NetworkClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/detail").build(), + standardResponseBuilder(404).build()) + .getNetworkClientForRegion("region-a.geo-1"); + + assertTrue(client.list().isEmpty()); + } + + public void testShowReturns2xx() { + NetworkClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/16dba3bc-f3fa-4775-afdc-237e12c72f6a").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/network.json", APPLICATION_JSON)).build()) + .getNetworkClientForRegion("region-a.geo-1"); + + Network net = client.get("16dba3bc-f3fa-4775-afdc-237e12c72f6a"); + assertEquals(net, new ParseNetworkTest().expected()); + } + + public void testShowReturns4xx() { + NetworkClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/16dba3bc-f3fa-4775-afdc-237e12c72f6a").build(), + standardResponseBuilder(404).build()) + .getNetworkClientForRegion("region-a.geo-1"); + + assertNull(client.get("16dba3bc-f3fa-4775-afdc-237e12c72f6a")); + } + + public void testShowDetailsReturns2xx() { + NetworkClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/16dba3bc-f3fa-4775-afdc-237e12c72f6a/detail").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/network_details.json", APPLICATION_JSON)).build()) + .getNetworkClientForRegion("region-a.geo-1"); + + NetworkDetails net = client.getDetails("16dba3bc-f3fa-4775-afdc-237e12c72f6a"); + assertEquals(net, new ParseNetworkDetailsTest().expected()); + } + + public void testShowDetailsReturns4xx() { + NetworkClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/16dba3bc-f3fa-4775-afdc-237e12c72f6a/detail").build(), + standardResponseBuilder(404).build()) + .getNetworkClientForRegion("region-a.geo-1"); + + assertNull(client.getDetails("16dba3bc-f3fa-4775-afdc-237e12c72f6a")); + } + + public void testCreateReturns2xx() { + NetworkClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks").method("POST") + .payload(payloadFromStringWithContentType("{\"network\":{\"name\":\"another-test\"}}", MediaType.APPLICATION_JSON)).build(), + standardResponseBuilder(200).payload(payloadFromStringWithContentType("{\"network\":{\"id\":\"12345\"}}", APPLICATION_JSON)).build()) + .getNetworkClientForRegion("region-a.geo-1"); + + Reference net = client.create("another-test"); + assertEquals(net, Reference.builder().id("12345").build()); + } + + @Test(expectedExceptions = AuthorizationException.class) + public void testCreateReturns4xx() { + NetworkClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks").method("POST") + .payload(payloadFromStringWithContentType("{\"network\":{\"name\":\"another-test\"}}", MediaType.APPLICATION_JSON)).build(), + standardResponseBuilder(401).build()) + .getNetworkClientForRegion("region-a.geo-1"); + + client.create("another-test"); + } + + public void testUpdateReturns2xx() { + NetworkClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/12345").method("PUT") + .payload(payloadFromStringWithContentType("{\"network\":{\"name\":\"another-test\"}}", MediaType.APPLICATION_JSON)).build(), + standardResponseBuilder(200).build()) + .getNetworkClientForRegion("region-a.geo-1"); + + assertTrue(client.rename("12345", "another-test")); + } + + @Test(expectedExceptions = ResourceNotFoundException.class) + public void testUpdateReturns4xx() { + NetworkClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/12345").method("PUT") + .payload(payloadFromStringWithContentType("{\"network\":{\"name\":\"another-test\"}}", MediaType.APPLICATION_JSON)).build(), + standardResponseBuilder(404).build()) + .getNetworkClientForRegion("region-a.geo-1"); + + client.rename("12345", "another-test"); + } + + public void testDeleteReturns2xx() { + NetworkClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/12345").method("DELETE").build(), + standardResponseBuilder(200).build()) + .getNetworkClientForRegion("region-a.geo-1"); + + assertTrue(client.delete("12345")); + } + + @Test(expectedExceptions = AuthorizationException.class) + public void testDeleteReturns4xx() { + NetworkClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/12345").method("DELETE").build(), + standardResponseBuilder(403).build()) + .getNetworkClientForRegion("region-a.geo-1"); + + client.delete("12345"); + } + + protected Set listOfNetworkRefs() { + return ImmutableSet.of( + Reference.builder().id("16dba3bc-f3fa-4775-afdc-237e12c72f6a").build(), + Reference.builder().id("1a104cf5-cb18-4d35-9407-2fd2646d9d0b").build(), + Reference.builder().id("31083ae2-420d-48b2-ac98-9f7a4fd8dbdc").build(), + Reference.builder().id("49c6d6fa-ff2a-459d-b975-75a8d31c9a89").build(), + Reference.builder().id("5cb3d6f4-62cb-41c9-b964-ba7d9df79e4e").build(), + Reference.builder().id("5d51d012-3491-4db7-b1b5-6f254015015d").build(), + Reference.builder().id("5f9cf7dc-22ca-4097-8e49-1cc8b23faf17").build(), + Reference.builder().id("6319ecad-6bff-48b2-9b53-02ede8cb7588").build(), + Reference.builder().id("6ba4c788-661f-49ab-9bf8-5f10cbbb2f57").build(), + Reference.builder().id("74ed170b-5069-4353-ab38-9719766dc57e").build(), + Reference.builder().id("b71fcac1-e864-4031-8c5b-edbecd9ece36").build(), + Reference.builder().id("c7681895-d84d-4650-9ca0-82c72036b855").build() + ); + } + + protected Set listOfNetworks() { + return ImmutableSet.of( + Network.builder().name("jclouds-port-test").id("16dba3bc-f3fa-4775-afdc-237e12c72f6a").build(), + Network.builder().name("wibble").id("1a104cf5-cb18-4d35-9407-2fd2646d9d0b").build(), + Network.builder().name("jclouds-test").id("31083ae2-420d-48b2-ac98-9f7a4fd8dbdc").build(), + Network.builder().name("jclouds-test").id("49c6d6fa-ff2a-459d-b975-75a8d31c9a89").build(), + Network.builder().name("wibble").id("5cb3d6f4-62cb-41c9-b964-ba7d9df79e4e").build(), + Network.builder().name("jclouds-port-test").id("5d51d012-3491-4db7-b1b5-6f254015015d").build(), + Network.builder().name("wibble").id("5f9cf7dc-22ca-4097-8e49-1cc8b23faf17").build(), + Network.builder().name("jclouds-test").id("6319ecad-6bff-48b2-9b53-02ede8cb7588").build(), + Network.builder().name("jclouds-port-test").id("6ba4c788-661f-49ab-9bf8-5f10cbbb2f57").build(), + Network.builder().name("jclouds-test").id("74ed170b-5069-4353-ab38-9719766dc57e").build(), + Network.builder().name("wibble").id("b71fcac1-e864-4031-8c5b-edbecd9ece36").build(), + Network.builder().name("jclouds-port-test").id("c7681895-d84d-4650-9ca0-82c72036b855").build() + ); + } + +} diff --git a/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/features/NetworkClientLiveTest.java b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/features/NetworkClientLiveTest.java new file mode 100644 index 0000000000..d807888dd8 --- /dev/null +++ b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/features/NetworkClientLiveTest.java @@ -0,0 +1,92 @@ +/** + * 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 1.1 (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-1.1 + * + * 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.quantum.v1_0.features; + +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.quantum.v1_0.domain.Network; +import org.jclouds.openstack.quantum.v1_0.domain.NetworkDetails; +import org.jclouds.openstack.quantum.v1_0.domain.Reference; +import org.jclouds.openstack.quantum.v1_0.internal.BaseQuantumClientLiveTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; + +/** + * Tests NetworkClient + * + * @author Adam Lowe + */ +@Test(groups = "live", testName = "NetworkClientLiveTest", singleThreaded = true) +public class NetworkClientLiveTest extends BaseQuantumClientLiveTest { + + public void testListNetworks() { + for (String regionId : quantumContext.getApi().getConfiguredRegions()) { + Set ids = quantumContext.getApi().getNetworkClientForRegion(regionId).listReferences(); + Set networks = quantumContext.getApi().getNetworkClientForRegion(regionId).list(); + assertNotNull(ids); + assertEquals(ids.size(), networks.size()); + for (Network network : networks) { + assertNotNull(network.getName()); + assertTrue(ids.contains(Reference.builder().id(network.getId()).build())); + } + } + } + + public void testCreateUpdateAndDeleteNetwork() { + for (String regionId : quantumContext.getApi().getConfiguredRegions()) { + NetworkClient client = quantumContext.getApi().getNetworkClientForRegion(regionId); + Reference net = client.create("jclouds-test"); + assertNotNull(net); + + Network network = client.get(net.getId()); + NetworkDetails details = client.getDetails(net.getId()); + + for(Network checkme : ImmutableList.of(network, details)) { + assertEquals(checkme.getId(), net.getId()); + assertEquals(checkme.getName(), "jclouds-test"); + } + + assertTrue(details.getPorts().isEmpty()); + + assertTrue(client.rename(net.getId(), "jclouds-live-test")); + + // Grab the updated metadata + network = client.get(net.getId()); + details = client.getDetails(net.getId()); + + for(Network checkme : ImmutableList.of(network, details)) { + assertEquals(checkme.getId(), net.getId()); + assertEquals(checkme.getName(), "jclouds-live-test"); + } + + assertTrue(details.getPorts().isEmpty()); + + Reference net2 = client.create("jclouds-test2"); + assertNotNull(net2); + + assertTrue(client.delete(net.getId())); + assertTrue(client.delete(net2.getId())); + } + } +} \ No newline at end of file diff --git a/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/features/PortClientExpectTest.java b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/features/PortClientExpectTest.java new file mode 100644 index 0000000000..80434441ec --- /dev/null +++ b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/features/PortClientExpectTest.java @@ -0,0 +1,246 @@ +/** + * 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 1.1 (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-1.1 + * + * 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.quantum.v1_0.features; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; + +import java.util.Set; + +import javax.ws.rs.core.MediaType; + +import org.jclouds.openstack.quantum.v1_0.domain.Attachment; +import org.jclouds.openstack.quantum.v1_0.domain.Port; +import org.jclouds.openstack.quantum.v1_0.domain.PortDetails; +import org.jclouds.openstack.quantum.v1_0.domain.Reference; +import org.jclouds.openstack.quantum.v1_0.internal.BaseQuantumClientExpectTest; +import org.jclouds.openstack.quantum.v1_0.parse.ParsePortDetailsTest; +import org.jclouds.openstack.quantum.v1_0.parse.ParsePortTest; +import org.jclouds.rest.AuthorizationException; +import org.jclouds.rest.ResourceNotFoundException; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; + +/** + * Tests parsing and Guice wiring of PortClient + * + * @author Adam Lowe + */ +@Test(groups="unit", testName = "PortClientExpectTest") +public class PortClientExpectTest extends BaseQuantumClientExpectTest { + + public void testListReferencesReturns2xx() { + PortClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/1a104cf5-cb18-4d35-9407-2fd2646d9d0b/ports").build(), + standardResponseBuilder(200).payload(payloadFromStringWithContentType("{\"ports\": [{\"id\": \"a6058a59-fa8c-46cc-bac8-08904e6ff0a5\"}]}", APPLICATION_JSON)).build()) + .getPortClientForRegionAndNetwork("region-a.geo-1", "1a104cf5-cb18-4d35-9407-2fd2646d9d0b"); + + Set nets = client.listReferences(); + assertEquals(nets, ImmutableSet.of(Reference.builder().id("a6058a59-fa8c-46cc-bac8-08904e6ff0a5").build())); + } + + public void testListReferencesReturns4xx() { + PortClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/1a104cf5-cb18-4d35-9407-2fd2646d9d0b/ports").build(), + standardResponseBuilder(404).build()) + .getPortClientForRegionAndNetwork("region-a.geo-1", "1a104cf5-cb18-4d35-9407-2fd2646d9d0b"); + + assertTrue(client.listReferences().isEmpty()); + } + + public void testListReturns2xx() { + PortClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/1a104cf5-cb18-4d35-9407-2fd2646d9d0b/ports/detail").build(), + standardResponseBuilder(200).payload(payloadFromStringWithContentType("{\"ports\": [{\"state\": \"DOWN\", \"id\": \"814ae4bb-33d9-425f-8ee2-13a5c90b1465\"}]}", APPLICATION_JSON)).build()) + .getPortClientForRegionAndNetwork("region-a.geo-1", "1a104cf5-cb18-4d35-9407-2fd2646d9d0b"); + + Set nets = client.list(); + assertEquals(nets, ImmutableSet.of(Port.builder().state(Port.State.DOWN).id("814ae4bb-33d9-425f-8ee2-13a5c90b1465").build())); + } + + public void testListReturns4xx() { + PortClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/1a104cf5-cb18-4d35-9407-2fd2646d9d0b/ports/detail").build(), + standardResponseBuilder(404).build()) + .getPortClientForRegionAndNetwork("region-a.geo-1", "1a104cf5-cb18-4d35-9407-2fd2646d9d0b"); + + assertTrue(client.list().isEmpty()); + } + + public void testShowReturns2xx() { + PortClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/16dba3bc-f3fa-4775-afdc-237e12c72f6a/ports/646c123b-871a-4124-9fa2-a94f04a582df").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/port.json", APPLICATION_JSON)).build()) + .getPortClientForRegionAndNetwork("region-a.geo-1", "16dba3bc-f3fa-4775-afdc-237e12c72f6a"); + + Port port = client.get("646c123b-871a-4124-9fa2-a94f04a582df"); + assertEquals(port, new ParsePortTest().expected()); + } + + public void testShowReturns4xx() { + PortClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/16dba3bc-f3fa-4775-afdc-237e12c72f6a/ports/646c123b-871a-4124-9fa2-a94f04a582df").build(), + standardResponseBuilder(404).build()) + .getPortClientForRegionAndNetwork("region-a.geo-1", "16dba3bc-f3fa-4775-afdc-237e12c72f6a"); + + assertNull(client.get("646c123b-871a-4124-9fa2-a94f04a582df")); + } + + public void testShowDetailsReturns2xx() { + PortClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/16dba3bc-f3fa-4775-afdc-237e12c72f6a/ports/646c123b-871a-4124-9fa2-a94f04a582df/detail").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/port_details.json", APPLICATION_JSON)).build()) + .getPortClientForRegionAndNetwork("region-a.geo-1", "16dba3bc-f3fa-4775-afdc-237e12c72f6a"); + + PortDetails net = client.getDetails("646c123b-871a-4124-9fa2-a94f04a582df"); + assertEquals(net, new ParsePortDetailsTest().expected()); + } + + public void testShowDetailsReturns4xx() { + PortClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/16dba3bc-f3fa-4775-afdc-237e12c72f6a/ports/646c123b-871a-4124-9fa2-a94f04a582df/detail").build(), + standardResponseBuilder(404).build()) + .getPortClientForRegionAndNetwork("region-a.geo-1", "16dba3bc-f3fa-4775-afdc-237e12c72f6a"); + + assertNull(client.getDetails("646c123b-871a-4124-9fa2-a94f04a582df")); + } + + public void testCreateReturns2xx() { + PortClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/16dba3bc-f3fa-4775-afdc-237e12c72f6a/ports").method("POST").build(), + standardResponseBuilder(200).payload(payloadFromStringWithContentType("{\"port\":{\"id\":\"12345\"}}", APPLICATION_JSON)).build()) + .getPortClientForRegionAndNetwork("region-a.geo-1", "16dba3bc-f3fa-4775-afdc-237e12c72f6a"); + + Reference port = client.create(); + assertEquals(port, Reference.builder().id("12345").build()); + } + + @Test(expectedExceptions = ResourceNotFoundException.class) + public void testCreateReturns4xx() { + PortClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/16dba3bc-f3fa-4775-afdc-237e12c72f6a/ports").method("POST").build(), + standardResponseBuilder(404).build()) + .getPortClientForRegionAndNetwork("region-a.geo-1", "16dba3bc-f3fa-4775-afdc-237e12c72f6a"); + + client.create(); + } + + public void testUpdateReturns2xx() { + PortClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/16dba3bc-f3fa-4775-afdc-237e12c72f6a/ports/77777").method("PUT") + .payload(payloadFromStringWithContentType("{\"port\":{\"state\":\"ACTIVE\"}}", MediaType.APPLICATION_JSON)).build(), + standardResponseBuilder(200).build()) + .getPortClientForRegionAndNetwork("region-a.geo-1", "16dba3bc-f3fa-4775-afdc-237e12c72f6a"); + + assertTrue(client.updateState("77777", Port.State.ACTIVE)); + } + + @Test(expectedExceptions = AuthorizationException.class) + public void testUpdateReturns4xx() { + PortClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/16dba3bc-f3fa-4775-afdc-237e12c72f6a/ports/77777").method("PUT") + .payload(payloadFromStringWithContentType("{\"port\":{\"state\":\"ACTIVE\"}}", MediaType.APPLICATION_JSON)).build(), + standardResponseBuilder(401).build()) + .getPortClientForRegionAndNetwork("region-a.geo-1", "16dba3bc-f3fa-4775-afdc-237e12c72f6a"); + + client.updateState("77777", Port.State.ACTIVE); + } + + public void testShowAttachment() { + PortClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/16dba3bc-f3fa-4775-afdc-237e12c72f6a/ports/77777/attachment").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/attachment.json", APPLICATION_JSON)).build()) + .getPortClientForRegionAndNetwork("region-a.geo-1", "16dba3bc-f3fa-4775-afdc-237e12c72f6a"); + + Attachment attachment = client.showAttachment("77777"); + assertEquals(attachment, Attachment.builder().id("jclouds-live-test").build()); + } + + public void testShowAttachmentReturns4xx() { + PortClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/16dba3bc-f3fa-4775-afdc-237e12c72f6a/ports/77777/attachment").build(), + standardResponseBuilder(404).build()) + .getPortClientForRegionAndNetwork("region-a.geo-1", "16dba3bc-f3fa-4775-afdc-237e12c72f6a"); + + assertNull(client.showAttachment("77777")); + } + + public void testPlugAttachment() { + PortClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/16dba3bc-f3fa-4775-afdc-237e12c72f6a/ports/77777/attachment") + .payload(payloadFromStringWithContentType("{\"attachment\":{\"id\":\"jclouds-live-test\"}}", MediaType.APPLICATION_JSON)) + .method("PUT").build(), + standardResponseBuilder(200).build()) + .getPortClientForRegionAndNetwork("region-a.geo-1", "16dba3bc-f3fa-4775-afdc-237e12c72f6a"); + + assertTrue(client.plugAttachment("77777", "jclouds-live-test")); + } + + @Test(expectedExceptions = AuthorizationException.class) + public void testPlugAttachmentReturns4xx() { + PortClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/16dba3bc-f3fa-4775-afdc-237e12c72f6a/ports/77777/attachment") + .payload(payloadFromStringWithContentType("{\"attachment\":{\"id\":\"jclouds-live-test\"}}", MediaType.APPLICATION_JSON)) + .method("PUT").build(), + standardResponseBuilder(403).build()) + .getPortClientForRegionAndNetwork("region-a.geo-1", "16dba3bc-f3fa-4775-afdc-237e12c72f6a"); + + client.plugAttachment("77777", "jclouds-live-test"); + } + public void testUnplugAttachment() { + PortClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/16dba3bc-f3fa-4775-afdc-237e12c72f6a/ports/77777/attachment").method("DELETE").build(), + standardResponseBuilder(200).build()) + .getPortClientForRegionAndNetwork("region-a.geo-1", "16dba3bc-f3fa-4775-afdc-237e12c72f6a"); + + assertTrue(client.unplugAttachment("77777")); + } + + @Test(expectedExceptions = ResourceNotFoundException.class) + public void testUnplugAttachmentReturns4xx() { + PortClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/tenants/3456/networks/16dba3bc-f3fa-4775-afdc-237e12c72f6a/ports/77777/attachment").method("DELETE").build(), + standardResponseBuilder(404).build()) + .getPortClientForRegionAndNetwork("region-a.geo-1", "16dba3bc-f3fa-4775-afdc-237e12c72f6a"); + + client.unplugAttachment("77777"); + } + +} diff --git a/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/features/PortClientLiveTest.java b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/features/PortClientLiveTest.java new file mode 100644 index 0000000000..dfab804255 --- /dev/null +++ b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/features/PortClientLiveTest.java @@ -0,0 +1,138 @@ +/** + * 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 1.1 (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-1.1 + * + * 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.quantum.v1_0.features; + +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.quantum.v1_0.domain.Attachment; +import org.jclouds.openstack.quantum.v1_0.domain.NetworkDetails; +import org.jclouds.openstack.quantum.v1_0.domain.Port; +import org.jclouds.openstack.quantum.v1_0.domain.PortDetails; +import org.jclouds.openstack.quantum.v1_0.domain.Reference; +import org.jclouds.openstack.quantum.v1_0.internal.BaseQuantumClientLiveTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; + +/** + * Tests PortClient + * + * @author Adam Lowe + */ +@Test(groups = "live", testName = "PortClientLiveTest", singleThreaded = true) +public class PortClientLiveTest extends BaseQuantumClientLiveTest { + + public void testListPorts() { + for (String regionId : quantumContext.getApi().getConfiguredRegions()) { + NetworkClient netClient = quantumContext.getApi().getNetworkClientForRegion(regionId); + Set nets = netClient.listReferences(); + for(Reference net : nets) { + PortClient portClient = quantumContext.getApi().getPortClientForRegionAndNetwork(regionId, net.getId()); + Set portRefs = portClient.listReferences(); + Set ports = portClient.list(); + + assertEquals(portRefs.size(), ports.size()); + for (Port port : ports) { + assertTrue(portRefs.contains(Reference.builder().id(port.getId()).build())); + } + } + } + } + + public void testCreateUpdateAndDeletePort() { + for (String regionId : quantumContext.getApi().getConfiguredRegions()) { + NetworkClient netClient = quantumContext.getApi().getNetworkClientForRegion(regionId); + Reference net = netClient.create("jclouds-port-test"); + assertNotNull(net); + PortClient portClient = quantumContext.getApi().getPortClientForRegionAndNetwork(regionId, net.getId()); + + Reference portRef = portClient.create(); + assertNotNull(portRef); + + Port port = portClient.get(portRef.getId()); + PortDetails portDetails = portClient.getDetails(portRef.getId()); + NetworkDetails networkDetails = netClient.getDetails(net.getId()); + + assertEquals(port.getState(), portDetails.getState()); + + for(Port checkme : ImmutableList.of(port, portDetails, Iterables.getOnlyElement(networkDetails.getPorts()))) { + assertEquals(checkme.getId(), portRef.getId()); + } + + assertTrue(portClient.updateState(portRef.getId(), Port.State.DOWN)); + + port = portClient.get(portRef.getId()); + portDetails = portClient.getDetails(portRef.getId()); + + for(Port checkme : ImmutableList.of(port, portDetails)) { + assertEquals(checkme.getId(), portRef.getId()); + assertEquals(checkme.getState(), Port.State.DOWN); + } + + assertTrue(portClient.plugAttachment(port.getId(), "jclouds-live-test")); + + Attachment attachment = portClient.showAttachment(port.getId()); + portDetails = portClient.getDetails(portRef.getId()); + + for(Attachment checkme : ImmutableList.of(attachment, portDetails.getAttachment())) { + assertNotNull(checkme); + assertEquals(checkme.getId(), "jclouds-live-test"); + } + + assertTrue(portClient.unplugAttachment(port.getId())); + + assertTrue(portClient.delete(portRef.getId())); + assertTrue(netClient.delete(net.getId())); + } + } + + @Test(enabled=false) // assuming attachmentId matters in the wild + public void testAttachAndDetachPort() { + for (String regionId : quantumContext.getApi().getConfiguredRegions()) { + NetworkClient netClient = quantumContext.getApi().getNetworkClientForRegion(regionId); + Reference net = netClient.create("jclouds-attach-test"); + assertNotNull(net); + + PortClient portClient = quantumContext.getApi().getPortClientForRegionAndNetwork(regionId, net.getId()); + + Reference port = portClient.create(); + assertNotNull(port); + + assertTrue(portClient.plugAttachment(port.getId(), "jclouds-live-test")); + + Attachment attachment = portClient.showAttachment(port.getId()); + PortDetails portDetails = portClient.getDetails(port.getId()); + + for(Attachment checkme : ImmutableList.of(attachment, portDetails.getAttachment())) { + assertNotNull(checkme); + assertEquals(checkme.getId(), "jclouds-live-test"); + } + + assertTrue(portClient.unplugAttachment(port.getId())); + + assertTrue(portClient.delete(port.getId())); + assertTrue(netClient.delete(net.getId())); + } + } +} \ No newline at end of file diff --git a/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/internal/BaseQuantumClientExpectTest.java b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/internal/BaseQuantumClientExpectTest.java new file mode 100644 index 0000000000..3204f17834 --- /dev/null +++ b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/internal/BaseQuantumClientExpectTest.java @@ -0,0 +1,49 @@ +/** + * 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.quantum.v1_0.internal; + +import java.net.URI; + +import javax.ws.rs.core.MediaType; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.openstack.quantum.v1_0.QuantumClient; + +import com.google.common.collect.ImmutableMultimap; + +/** + * Base class for writing Quantum Rest Client Expect tests + * + * @author Adam Lowe + */ +public class BaseQuantumClientExpectTest extends BaseQuantumExpectTest { + protected String endpoint = "https://csnode.jclouds.org:9696/v1.0"; + + protected HttpRequest.Builder standardRequestBuilder(String endpoint) { + return HttpRequest.builder().method("GET") + .headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken)) + .endpoint(URI.create(endpoint)); + } + + protected HttpResponse.Builder standardResponseBuilder(int status) { + return HttpResponse.builder().statusCode(status); + } + +} diff --git a/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/internal/BaseQuantumClientLiveTest.java b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/internal/BaseQuantumClientLiveTest.java new file mode 100644 index 0000000000..02e8d5b2bd --- /dev/null +++ b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/internal/BaseQuantumClientLiveTest.java @@ -0,0 +1,74 @@ +/** + * 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.quantum.v1_0.internal; + +import java.util.Properties; + +import org.jclouds.apis.BaseContextLiveTest; +import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties; +import org.jclouds.openstack.quantum.v1_0.QuantumApiMetadata; +import org.jclouds.openstack.quantum.v1_0.QuantumAsyncClient; +import org.jclouds.openstack.quantum.v1_0.QuantumClient; +import org.jclouds.rest.RestContext; +import org.testng.annotations.AfterGroups; +import org.testng.annotations.BeforeGroups; +import org.testng.annotations.Test; + +import com.google.common.reflect.TypeToken; + +/** + * Tests behavior of {@code QuantumClient} + * + * @author Adam Lowe + */ +@Test(groups = "live") +public class BaseQuantumClientLiveTest extends BaseContextLiveTest> { + + public BaseQuantumClientLiveTest() { + provider = "openstack-quantum"; + } + + protected RestContext quantumContext; + + @BeforeGroups(groups = { "integration", "live" }) + @Override + public void setupContext() { + super.setupContext(); + quantumContext = context; + } + + @Override + protected Properties setupProperties() { + Properties props = super.setupProperties(); + setIfTestSystemPropertyPresent(props, KeystoneProperties.CREDENTIAL_TYPE); + return props; + } + + @AfterGroups(groups = "live") + protected void tearDown() { + if (quantumContext != null) + quantumContext.close(); + } + + @Override + protected TypeToken> contextType() { + return QuantumApiMetadata.CONTEXT_TOKEN; + } + +} diff --git a/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/internal/BaseQuantumExpectTest.java b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/internal/BaseQuantumExpectTest.java new file mode 100644 index 0000000000..282fdc369f --- /dev/null +++ b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/internal/BaseQuantumExpectTest.java @@ -0,0 +1,49 @@ +/** + * 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.quantum.v1_0.internal; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.openstack.keystone.v2_0.internal.KeystoneFixture; +import org.jclouds.rest.internal.BaseRestClientExpectTest; + +/** + * Base class for writing Quantum Expect tests + * + * @author Adam Lowe + */ +public class BaseQuantumExpectTest extends BaseRestClientExpectTest { + protected HttpRequest keystoneAuthWithUsernameAndPassword; + protected HttpRequest keystoneAuthWithAccessKeyAndSecretKey; + protected String authToken; + protected HttpResponse responseWithKeystoneAccess; + + public BaseQuantumExpectTest() { + provider = "openstack-quantum"; + keystoneAuthWithUsernameAndPassword = KeystoneFixture.INSTANCE.initialAuthWithUsernameAndPassword(identity, + credential); + keystoneAuthWithAccessKeyAndSecretKey = KeystoneFixture.INSTANCE.initialAuthWithAccessKeyAndSecretKey(identity, + credential); + + authToken = KeystoneFixture.INSTANCE.getAuthToken(); + responseWithKeystoneAccess = KeystoneFixture.INSTANCE.responseWithAccess(); + // now, createContext arg will need tenant prefix + identity = KeystoneFixture.INSTANCE.getTenantName() + ":" + identity; + } +} diff --git a/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/parse/ParseAttachmentTest.java b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/parse/ParseAttachmentTest.java new file mode 100644 index 0000000000..68d240b744 --- /dev/null +++ b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/parse/ParseAttachmentTest.java @@ -0,0 +1,47 @@ +/** + * 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.quantum.v1_0.parse; + +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; + +import org.jclouds.json.BaseItemParserTest; +import org.jclouds.openstack.quantum.v1_0.domain.Attachment; +import org.jclouds.rest.annotations.SelectJson; +import org.testng.annotations.Test; + +/** + * + * @author Adam Lowe + */ +@Test(groups = "unit", testName = "ParseAttachmentTest") +public class ParseAttachmentTest extends BaseItemParserTest { + + @Override + public String resource() { + return "/attachment.json"; + } + + @Override + @SelectJson("attachment") + @Consumes(MediaType.APPLICATION_JSON) + public Attachment expected() { + return Attachment.builder().id("jclouds-live-test").build(); + } +} diff --git a/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/parse/ParseNetworkDetailsTest.java b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/parse/ParseNetworkDetailsTest.java new file mode 100644 index 0000000000..bb2ecf703e --- /dev/null +++ b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/parse/ParseNetworkDetailsTest.java @@ -0,0 +1,51 @@ +/** + * 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.quantum.v1_0.parse; + +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; + +import org.jclouds.json.BaseItemParserTest; +import org.jclouds.openstack.quantum.v1_0.domain.NetworkDetails; +import org.jclouds.openstack.quantum.v1_0.domain.Port; +import org.jclouds.rest.annotations.SelectJson; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adam Lowe + */ +@Test(groups = "unit", testName = "ParseNetworkDetailsTest") +public class ParseNetworkDetailsTest extends BaseItemParserTest { + + @Override + public String resource() { + return "/network_details.json"; + } + + @Override + @SelectJson("network") + @Consumes(MediaType.APPLICATION_JSON) + public NetworkDetails expected() { + return NetworkDetails.builder().name("jclouds-port-test").id("25e3e0f8-f1f0-4850-97a3-8d5393c3385b") + .ports(ImmutableSet.of(Port.builder().state(Port.State.DOWN).id("908391f6-ef3c-4bc6-acec-46582f9b231d").build())).build(); + } +} diff --git a/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/parse/ParseNetworkTest.java b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/parse/ParseNetworkTest.java new file mode 100644 index 0000000000..3af65aac8f --- /dev/null +++ b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/parse/ParseNetworkTest.java @@ -0,0 +1,47 @@ +/** + * 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.quantum.v1_0.parse; + +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; + +import org.jclouds.json.BaseItemParserTest; +import org.jclouds.openstack.quantum.v1_0.domain.Network; +import org.jclouds.rest.annotations.SelectJson; +import org.testng.annotations.Test; + +/** + * + * @author Adam Lowe + */ +@Test(groups = "unit", testName = "ParseNetworkTest") +public class ParseNetworkTest extends BaseItemParserTest { + + @Override + public String resource() { + return "/network.json"; + } + + @Override + @SelectJson("network") + @Consumes(MediaType.APPLICATION_JSON) + public Network expected() { + return Network.builder().name("jclouds-wibble").id("624312ff-d14b-4ba3-9834-1c78d23d574d").build(); + } +} diff --git a/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/parse/ParsePortDetailsTest.java b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/parse/ParsePortDetailsTest.java new file mode 100644 index 0000000000..ac740d49e7 --- /dev/null +++ b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/parse/ParsePortDetailsTest.java @@ -0,0 +1,49 @@ +/** + * 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.quantum.v1_0.parse; + +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; + +import org.jclouds.json.BaseItemParserTest; +import org.jclouds.openstack.quantum.v1_0.domain.Attachment; +import org.jclouds.openstack.quantum.v1_0.domain.Port; +import org.jclouds.openstack.quantum.v1_0.domain.PortDetails; +import org.jclouds.rest.annotations.SelectJson; +import org.testng.annotations.Test; + +/** + * @author Adam Lowe + */ +@Test(groups = "unit", testName = "ParsePortDetailsTest") +public class ParsePortDetailsTest extends BaseItemParserTest { + + @Override + public String resource() { + return "/port_details.json"; + } + + @Override + @SelectJson("port") + @Consumes(MediaType.APPLICATION_JSON) + public PortDetails expected() { + return PortDetails.builder().id("0ccbe514-e36b-475b-91c9-208dfd96d3ac").state(Port.State.DOWN) + .attachment(Attachment.builder().id("jclouds-live-test").build()).build(); + } +} diff --git a/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/parse/ParsePortTest.java b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/parse/ParsePortTest.java new file mode 100644 index 0000000000..ffc5011fd1 --- /dev/null +++ b/labs/openstack-quantum/src/test/java/org/jclouds/openstack/quantum/v1_0/parse/ParsePortTest.java @@ -0,0 +1,47 @@ +/** + * 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.quantum.v1_0.parse; + +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; + +import org.jclouds.json.BaseItemParserTest; +import org.jclouds.openstack.quantum.v1_0.domain.Port; +import org.jclouds.rest.annotations.SelectJson; +import org.testng.annotations.Test; + +/** + * + * @author Adam Lowe + */ +@Test(groups = "unit", testName = "ParsePortTest") +public class ParsePortTest extends BaseItemParserTest { + + @Override + public String resource() { + return "/port.json"; + } + + @Override + @SelectJson("port") + @Consumes(MediaType.APPLICATION_JSON) + public Port expected() { + return Port.builder().id("646c123b-871a-4124-9fa2-a94f04a582df").state(Port.State.DOWN).build(); + } +} diff --git a/labs/openstack-quantum/src/test/resources/attachment.json b/labs/openstack-quantum/src/test/resources/attachment.json new file mode 100644 index 0000000000..e13505594c --- /dev/null +++ b/labs/openstack-quantum/src/test/resources/attachment.json @@ -0,0 +1 @@ +{"attachment":{"id":"jclouds-live-test"}} \ No newline at end of file diff --git a/labs/openstack-quantum/src/test/resources/list_network_refs.json b/labs/openstack-quantum/src/test/resources/list_network_refs.json new file mode 100644 index 0000000000..d6daf8d74d --- /dev/null +++ b/labs/openstack-quantum/src/test/resources/list_network_refs.json @@ -0,0 +1,14 @@ +{"networks": [ + {"id": "16dba3bc-f3fa-4775-afdc-237e12c72f6a"}, + {"id": "1a104cf5-cb18-4d35-9407-2fd2646d9d0b"}, + {"id": "31083ae2-420d-48b2-ac98-9f7a4fd8dbdc"}, + {"id": "49c6d6fa-ff2a-459d-b975-75a8d31c9a89"}, + {"id": "5cb3d6f4-62cb-41c9-b964-ba7d9df79e4e"}, + {"id": "5d51d012-3491-4db7-b1b5-6f254015015d"}, + {"id": "5f9cf7dc-22ca-4097-8e49-1cc8b23faf17"}, + {"id": "6319ecad-6bff-48b2-9b53-02ede8cb7588"}, + {"id": "6ba4c788-661f-49ab-9bf8-5f10cbbb2f57"}, + {"id": "74ed170b-5069-4353-ab38-9719766dc57e"}, + {"id": "b71fcac1-e864-4031-8c5b-edbecd9ece36"}, + {"id": "c7681895-d84d-4650-9ca0-82c72036b855"} +]} \ No newline at end of file diff --git a/labs/openstack-quantum/src/test/resources/list_networks.json b/labs/openstack-quantum/src/test/resources/list_networks.json new file mode 100644 index 0000000000..b5c78393ec --- /dev/null +++ b/labs/openstack-quantum/src/test/resources/list_networks.json @@ -0,0 +1,14 @@ +{"networks": [ + {"name": "jclouds-port-test", "id": "16dba3bc-f3fa-4775-afdc-237e12c72f6a"}, + {"name": "wibble", "id": "1a104cf5-cb18-4d35-9407-2fd2646d9d0b"}, + {"name": "jclouds-test", "id": "31083ae2-420d-48b2-ac98-9f7a4fd8dbdc"}, + {"name": "jclouds-test", "id": "49c6d6fa-ff2a-459d-b975-75a8d31c9a89"}, + {"name": "wibble", "id": "5cb3d6f4-62cb-41c9-b964-ba7d9df79e4e"}, + {"name": "jclouds-port-test", "id": "5d51d012-3491-4db7-b1b5-6f254015015d"}, + {"name": "wibble", "id": "5f9cf7dc-22ca-4097-8e49-1cc8b23faf17"}, + {"name": "jclouds-test", "id": "6319ecad-6bff-48b2-9b53-02ede8cb7588"}, + {"name": "jclouds-port-test", "id": "6ba4c788-661f-49ab-9bf8-5f10cbbb2f57"}, + {"name": "jclouds-test", "id": "74ed170b-5069-4353-ab38-9719766dc57e"}, + {"name": "wibble", "id": "b71fcac1-e864-4031-8c5b-edbecd9ece36"}, + {"name": "jclouds-port-test", "id": "c7681895-d84d-4650-9ca0-82c72036b855"} +] \ No newline at end of file diff --git a/labs/openstack-quantum/src/test/resources/logback.xml b/labs/openstack-quantum/src/test/resources/logback.xml new file mode 100644 index 0000000000..e4ba99b357 --- /dev/null +++ b/labs/openstack-quantum/src/test/resources/logback.xml @@ -0,0 +1,51 @@ + + + + target/test-data/jclouds.log + + + %d %-5p [%c] [%thread] %m%n + + + + + target/test-data/jclouds-wire.log + + + %d %-5p [%c] [%thread] %m%n + + + + + target/test-data/jclouds-blobstore.log + + + %d %-5p [%c] [%thread] %m%n + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/labs/openstack-quantum/src/test/resources/network.json b/labs/openstack-quantum/src/test/resources/network.json new file mode 100644 index 0000000000..fec734d654 --- /dev/null +++ b/labs/openstack-quantum/src/test/resources/network.json @@ -0,0 +1 @@ +{"network": {"name": "jclouds-wibble", "id": "624312ff-d14b-4ba3-9834-1c78d23d574d"}} \ No newline at end of file diff --git a/labs/openstack-quantum/src/test/resources/network_details.json b/labs/openstack-quantum/src/test/resources/network_details.json new file mode 100644 index 0000000000..0ee7025da3 --- /dev/null +++ b/labs/openstack-quantum/src/test/resources/network_details.json @@ -0,0 +1 @@ +{"network": {"ports": [{"state": "DOWN", "id": "908391f6-ef3c-4bc6-acec-46582f9b231d"}], "name": "jclouds-port-test", "id": "25e3e0f8-f1f0-4850-97a3-8d5393c3385b"}} \ No newline at end of file diff --git a/labs/openstack-quantum/src/test/resources/port.json b/labs/openstack-quantum/src/test/resources/port.json new file mode 100644 index 0000000000..371fcb4697 --- /dev/null +++ b/labs/openstack-quantum/src/test/resources/port.json @@ -0,0 +1 @@ +{"port": {"state": "DOWN", "id": "646c123b-871a-4124-9fa2-a94f04a582df"}} \ No newline at end of file diff --git a/labs/openstack-quantum/src/test/resources/port_details.json b/labs/openstack-quantum/src/test/resources/port_details.json new file mode 100644 index 0000000000..5481135bac --- /dev/null +++ b/labs/openstack-quantum/src/test/resources/port_details.json @@ -0,0 +1 @@ +{"port": {"state": "DOWN", "id": "0ccbe514-e36b-475b-91c9-208dfd96d3ac", "attachment": {"id": "jclouds-live-test"}}} \ No newline at end of file diff --git a/labs/pom.xml b/labs/pom.xml index 521a07e677..a976fc93d1 100644 --- a/labs/pom.xml +++ b/labs/pom.xml @@ -47,5 +47,6 @@ openstack-glance joyent-sdc openstack-keystone + openstack-quantum