diff --git a/.gitignore b/.gitignore index 1ce93e0405..5b734bc1be 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ bin/ *.DS_STORE TAGS .metadata/ +atlassian-ide-plugin.xml diff --git a/apis/cloudloadbalancers/src/test/java/org/jclouds/cloudloadbalancers/internal/BaseCloudLoadBalancersClientLiveTest.java b/apis/cloudloadbalancers/src/test/java/org/jclouds/cloudloadbalancers/internal/BaseCloudLoadBalancersClientLiveTest.java index 72e734af0c..70e77f8aab 100644 --- a/apis/cloudloadbalancers/src/test/java/org/jclouds/cloudloadbalancers/internal/BaseCloudLoadBalancersClientLiveTest.java +++ b/apis/cloudloadbalancers/src/test/java/org/jclouds/cloudloadbalancers/internal/BaseCloudLoadBalancersClientLiveTest.java @@ -28,12 +28,12 @@ import org.jclouds.cloudloadbalancers.predicates.LoadBalancerActive; import org.jclouds.cloudloadbalancers.predicates.LoadBalancerDeleted; import org.jclouds.loadbalancer.LoadBalancerServiceContext; import org.jclouds.logging.log4j.config.Log4JLoggingModule; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.rest.RestContext; import org.testng.annotations.BeforeGroups; import com.google.common.base.Predicate; +import com.google.common.net.HostAndPort; import com.google.common.reflect.TypeToken; import com.google.inject.Guice; import com.google.inject.Injector; @@ -51,7 +51,7 @@ public class BaseCloudLoadBalancersClientLiveTest extends BaseViewLiveTest lbContext; protected String[] regions = {}; - protected Predicate socketTester; + protected Predicate socketTester; protected RetryablePredicate loadBalancerActive; protected RetryablePredicate loadBalancerDeleted; diff --git a/apis/cloudservers/src/test/java/org/jclouds/cloudservers/CloudServersClientLiveTest.java b/apis/cloudservers/src/test/java/org/jclouds/cloudservers/CloudServersClientLiveTest.java index eca7ef3d62..1dcefe6553 100644 --- a/apis/cloudservers/src/test/java/org/jclouds/cloudservers/CloudServersClientLiveTest.java +++ b/apis/cloudservers/src/test/java/org/jclouds/cloudservers/CloudServersClientLiveTest.java @@ -49,7 +49,6 @@ import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest; import org.jclouds.domain.LoginCredentials; import org.jclouds.http.HttpResponseException; import org.jclouds.io.Payload; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.predicates.SocketOpen; import org.jclouds.ssh.SshClient; @@ -63,6 +62,7 @@ import com.google.common.base.Predicate; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; +import com.google.common.net.HostAndPort; import com.google.inject.Injector; /** @@ -79,7 +79,7 @@ public class CloudServersClientLiveTest extends BaseComputeServiceContextLiveTes protected CloudServersClient client; protected SshClient.Factory sshFactory; - protected Predicate socketTester; + protected Predicate socketTester; @BeforeGroups(groups = { "integration", "live" }) @Override @@ -89,7 +89,7 @@ public class CloudServersClientLiveTest extends BaseComputeServiceContextLiveTes client = injector.getInstance(CloudServersClient.class); sshFactory = injector.getInstance(SshClient.Factory.class); SocketOpen socketOpen = injector.getInstance(SocketOpen.class); - socketTester = new RetryablePredicate(socketOpen, 120, 1, TimeUnit.SECONDS); + socketTester = new RetryablePredicate(socketOpen, 120, 1, TimeUnit.SECONDS); injector.injectMembers(socketOpen); // add logger } @@ -374,7 +374,7 @@ public class CloudServersClientLiveTest extends BaseComputeServiceContextLiveTes } private void doCheckPass(Server newDetails, String pass) throws IOException { - IPSocket socket = new IPSocket(Iterables.get(newDetails.getAddresses().getPublicAddresses(), 0), 22); + HostAndPort socket = HostAndPort.fromParts(Iterables.get(newDetails.getAddresses().getPublicAddresses(), 0), 22); socketTester.apply(socket); SshClient client = sshFactory.create(socket, LoginCredentials.builder().user("root").password(pass).build()); @@ -390,7 +390,7 @@ public class CloudServersClientLiveTest extends BaseComputeServiceContextLiveTes } private ExecResponse exec(Server details, String pass, String command) throws IOException { - IPSocket socket = new IPSocket(Iterables.get(details.getAddresses().getPublicAddresses(), 0), 22); + HostAndPort socket = HostAndPort.fromParts(Iterables.get(details.getAddresses().getPublicAddresses(), 0), 22); socketTester.apply(socket); SshClient client = sshFactory.create(socket, LoginCredentials.builder().user("root").password(pass).build()); try { diff --git a/apis/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java b/apis/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java index e8b0a729ff..1a639fc980 100644 --- a/apis/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java +++ b/apis/cloudsigma/src/test/java/org/jclouds/cloudsigma/CloudSigmaClientLiveTest.java @@ -46,7 +46,6 @@ import org.jclouds.cloudsigma.util.Servers; import org.jclouds.compute.domain.ExecResponse; import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest; import org.jclouds.domain.LoginCredentials; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.InetSocketAddressConnect; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.rest.RestContext; @@ -61,6 +60,7 @@ import com.google.common.base.Predicates; import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.net.HostAndPort; import com.google.gson.Gson; import com.google.inject.Guice; @@ -81,7 +81,7 @@ public class CloudSigmaClientLiveTest extends BaseComputeServiceContextLiveTest protected String vncPassword = "Il0veVNC"; protected CloudSigmaClient client; protected RestContext cloudSigmaContext; - protected Predicate socketTester; + protected Predicate socketTester; protected Predicate driveNotClaimed; @@ -94,7 +94,7 @@ public class CloudSigmaClientLiveTest extends BaseComputeServiceContextLiveTest client = cloudSigmaContext.getApi(); driveNotClaimed = new RetryablePredicate(Predicates.not(new DriveClaimed(client)), maxDriveImageTime, 1, TimeUnit.SECONDS); - socketTester = new RetryablePredicate(new InetSocketAddressConnect(), maxDriveImageTime, 1, + socketTester = new RetryablePredicate(new InetSocketAddressConnect(), maxDriveImageTime, 1, TimeUnit.SECONDS); if (Strings.emptyToNull(imageId) == null) { @@ -329,9 +329,9 @@ public class CloudSigmaClientLiveTest extends BaseComputeServiceContextLiveTest @Test(dependsOnMethods = "testCreateAndStartServer") public void testConnectivity() throws Exception { Logger.getAnonymousLogger().info("awaiting vnc"); - assert socketTester.apply(new IPSocket(server.getVnc().getIp(), 5900)) : server; + assert socketTester.apply(HostAndPort.fromParts(server.getVnc().getIp(), 5900)) : server; Logger.getAnonymousLogger().info("awaiting ssh"); - assert socketTester.apply(new IPSocket(server.getNics().get(0).getDhcp(), 22)) : server; + assert socketTester.apply(HostAndPort.fromParts(server.getNics().get(0).getDhcp(), 22)) : server; doConnectViaSsh(server, getSshCredentials(server)); } @@ -389,7 +389,7 @@ public class CloudSigmaClientLiveTest extends BaseComputeServiceContextLiveTest protected void doConnectViaSsh(Server server, LoginCredentials creds) throws IOException { SshClient ssh = Guice.createInjector(new SshjSshClientModule()).getInstance(SshClient.Factory.class) - .create(new IPSocket(server.getVnc().getIp(), 22), creds); + .create(HostAndPort.fromParts(server.getVnc().getIp(), 22), creds); try { ssh.connect(); ExecResponse hello = ssh.exec("echo hello"); diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/CloudStackClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/CloudStackClientLiveTest.java index eb1e7ccc07..299f5a3da6 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/CloudStackClientLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/CloudStackClientLiveTest.java @@ -32,7 +32,7 @@ //import org.jclouds.cloudstack.options.CreateInstanceOptions; //import org.jclouds.domain.Credentials; //import org.jclouds.http.HttpRequest; -//import org.jclouds.net.IPSocket; +//import com.google.common.net.HostAndPort; //import org.jclouds.ssh.SshClient; //import org.jclouds.ssh.jsch.config.JschSshClientModule; //import org.testng.annotations.AfterGroups; @@ -79,7 +79,7 @@ // public void testConnectivity() throws Exception { // Logger.getAnonymousLogger().info("awaiting ssh"); // // TODO -// // assert socketTester.apply(new IPSocket(Iterables.get(instance.getPublicAddresses(), 0), +// // assert socketTester.apply(HostAndPort.fromParts(Iterables.get(instance.getPublicAddresses(), 0), // // 22)) : instance; // // doConnectViaSsh(instance, getSshCredentials(instance)); // } @@ -119,7 +119,7 @@ // // protected void doConnectViaSsh(Instance instance, Credentials creds) throws IOException { // SshClient ssh = Guice.createInjector(new JschSshClientModule()).getInstance(SshClient.Factory.class) -// .create(new IPSocket(Iterables.get(instance.getPublicAddresses(), 0), 22), creds); +// .create(HostAndPort.fromParts(Iterables.get(instance.getPublicAddresses(), 0), 22), creds); // try { // ssh.connect(); // ExecResponse hello = ssh.exec("echo hello"); diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterLiveTest.java index 41a32cc956..71fbbc9d30 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/compute/CloudStackComputeServiceAdapterLiveTest.java @@ -53,14 +53,13 @@ import org.jclouds.cloudstack.suppliers.GetCurrentUser; import org.jclouds.cloudstack.suppliers.NetworksForCurrentUser; import org.jclouds.cloudstack.suppliers.ZoneIdToZoneSupplier; import org.jclouds.collect.Memoized; -import org.jclouds.compute.ComputeTestUtils; import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials; +import org.jclouds.compute.ComputeTestUtils; import org.jclouds.compute.domain.Template; import org.jclouds.compute.functions.DefaultCredentialsFromImageOrOverridingCredentials; import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate; import org.jclouds.domain.Credentials; import org.jclouds.logging.log4j.config.Log4JLoggingModule; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.rest.annotations.Identity; import org.testng.annotations.AfterGroups; @@ -74,6 +73,7 @@ import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; +import com.google.common.net.HostAndPort; import com.google.common.net.InetAddresses; import com.google.inject.AbstractModule; import com.google.inject.Guice; @@ -180,7 +180,7 @@ public class CloudStackComputeServiceAdapterLiveTest extends BaseCloudStackClien loginCredentials = prioritizeCredentialsFromTemplate.apply(template, vm.getCredentials()); assert InetAddresses.isInetAddress(address) : vm; - IPSocket socket = new IPSocket(address, 22); + HostAndPort socket = HostAndPort.fromParts(address, 22); checkSSH(socket); } diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/BaseCloudStackClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/BaseCloudStackClientLiveTest.java index f750cca75c..d6f71d31e6 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/BaseCloudStackClientLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/BaseCloudStackClientLiveTest.java @@ -52,7 +52,6 @@ import org.jclouds.cloudstack.strategy.BlockUntilJobCompletesAndReturnResult; import org.jclouds.compute.ComputeService; import org.jclouds.compute.domain.ExecResponse; import org.jclouds.compute.internal.BaseGenericComputeServiceContextLiveTest; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.InetSocketAddressConnect; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.rest.RestContext; @@ -65,6 +64,7 @@ import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; +import com.google.common.net.HostAndPort; import com.google.common.reflect.TypeToken; import com.google.inject.Guice; import com.google.inject.Injector; @@ -156,7 +156,7 @@ public class BaseCloudStackClientLiveTest extends BaseGenericComputeServiceConte protected CloudStackClient adminClient; protected User user; - protected Predicate socketTester; + protected Predicate socketTester; protected RetryablePredicate jobComplete; protected RetryablePredicate adminJobComplete; protected RetryablePredicate virtualMachineRunning; @@ -181,7 +181,7 @@ public class BaseCloudStackClientLiveTest extends BaseGenericComputeServiceConte protected CloudStackGlobalClient globalAdminClient; protected User globalAdminUser; - protected void checkSSH(IPSocket socket) { + protected void checkSSH(HostAndPort socket) { socketTester.apply(socket); SshClient client = sshFactory.create(socket, loginCredentials); try { @@ -224,7 +224,7 @@ public class BaseCloudStackClientLiveTest extends BaseGenericComputeServiceConte injector = Guice.createInjector(setupModules()); sshFactory = injector.getInstance(SshClient.Factory.class); - socketTester = new RetryablePredicate(new InetSocketAddressConnect(), 180, 1, 1, TimeUnit.SECONDS); + socketTester = new RetryablePredicate(new InetSocketAddressConnect(), 180, 1, 1, TimeUnit.SECONDS); injector.injectMembers(socketTester); jobComplete = new RetryablePredicate(new JobComplete(client), 1200, 1, 5, TimeUnit.SECONDS); injector.injectMembers(jobComplete); diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/FirewallClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/FirewallClientLiveTest.java index 089af5bb70..11eeeb9948 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/FirewallClientLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/FirewallClientLiveTest.java @@ -36,13 +36,13 @@ import org.jclouds.cloudstack.domain.PublicIPAddress; import org.jclouds.cloudstack.domain.VirtualMachine; import org.jclouds.cloudstack.options.CreateFirewallRuleOptions; import org.jclouds.logging.Logger; -import org.jclouds.net.IPSocket; import org.testng.annotations.AfterGroups; import org.testng.annotations.BeforeGroups; import org.testng.annotations.Test; import com.google.common.base.Predicate; import com.google.common.base.Predicates; +import com.google.common.net.HostAndPort; /** * Tests behavior of {@code FirewallClientLiveTest} @@ -112,7 +112,7 @@ public class FirewallClientLiveTest extends BaseCloudStackClientLiveTest { assertEquals(portForwardingRule.getProtocol(), PortForwardingRule.Protocol.TCP); checkPortForwardingRule(portForwardingRule); - checkSSH(new IPSocket(ip.getIPAddress(), 22)); + checkSSH(HostAndPort.fromParts(ip.getIPAddress(), 22)); } @Test(dependsOnMethods = "testCreatePortForwardingRule") diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerClientLiveTest.java index 441a0d8b8a..52453aba9f 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerClientLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/LoadBalancerClientLiveTest.java @@ -35,13 +35,12 @@ import javax.annotation.Nullable; import org.jclouds.cloudstack.domain.AsyncJob; import org.jclouds.cloudstack.domain.JobResult; import org.jclouds.cloudstack.domain.LoadBalancerRule; +import org.jclouds.cloudstack.domain.LoadBalancerRule.Algorithm; +import org.jclouds.cloudstack.domain.LoadBalancerRule.State; import org.jclouds.cloudstack.domain.Network; import org.jclouds.cloudstack.domain.PublicIPAddress; import org.jclouds.cloudstack.domain.VirtualMachine; -import org.jclouds.cloudstack.domain.LoadBalancerRule.Algorithm; -import org.jclouds.cloudstack.domain.LoadBalancerRule.State; import org.jclouds.cloudstack.predicates.LoadBalancerRuleActive; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.ssh.SshException; import org.testng.annotations.AfterGroups; @@ -50,6 +49,7 @@ import org.testng.annotations.Test; import com.google.common.base.Predicate; import com.google.common.base.Predicates; +import com.google.common.net.HostAndPort; /** * Tests behavior of {@code LoadBalancerClientLiveTest} @@ -155,7 +155,7 @@ public class LoadBalancerClientLiveTest extends BaseCloudStackClientLiveTest { private void loopAndCheckSSH() throws IOException { for (int i = 0; i < 5; i++) {// retry loop TODO replace with predicate. try { - checkSSH(new IPSocket(ip.getIPAddress(), 22)); + checkSSH(HostAndPort.fromParts(ip.getIPAddress(), 22)); return; } catch (SshException e) { e.printStackTrace(); @@ -176,7 +176,7 @@ public class LoadBalancerClientLiveTest extends BaseCloudStackClientLiveTest { rule.getId(), vm.getId()))); assertEquals(client.getLoadBalancerClient().listVirtualMachinesAssignedToLoadBalancerRule(rule.getId()).size(), 0); assertEquals(rule.getState(), State.ADD); - checkSSH(new IPSocket(ip.getIPAddress(), 22)); + checkSSH(HostAndPort.fromParts(ip.getIPAddress(), 22)); } @AfterGroups(groups = "live") diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SecurityGroupClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SecurityGroupClientLiveTest.java index fd44fd9723..78c584bbf4 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SecurityGroupClientLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/SecurityGroupClientLiveTest.java @@ -33,7 +33,6 @@ import org.jclouds.cloudstack.domain.Zone; import org.jclouds.cloudstack.options.AccountInDomainOptions; import org.jclouds.cloudstack.options.DeployVirtualMachineOptions; import org.jclouds.cloudstack.options.ListSecurityGroupsOptions; -import org.jclouds.net.IPSocket; import org.jclouds.util.Strings2; import org.testng.annotations.AfterGroups; import org.testng.annotations.Test; @@ -41,6 +40,7 @@ import org.testng.annotations.Test; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; +import com.google.common.net.HostAndPort; /** * Tests behavior of {@code SecurityGroupClient} @@ -178,7 +178,7 @@ public class SecurityGroupClientLiveTest extends BaseCloudStackClientLiveTest { if (vm.getPassword() != null && !loginCredentials.hasPasswordOption()) loginCredentials = loginCredentials.toBuilder().password(vm.getPassword()).build(); // ingress port 22 - checkSSH(new IPSocket(vm.getIPAddress(), 22)); + checkSSH(HostAndPort.fromParts(vm.getIPAddress(), 22)); // ingress icmp disabled as this is platform dependent and may actually // just try tcp port 7 // assert InetAddress.getByName(vm.getIPAddress()).isReachable(1000) : vm; diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineClientLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineClientLiveTest.java index 6b8e7ce3c3..ab7cec7a6d 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineClientLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/features/VirtualMachineClientLiveTest.java @@ -53,7 +53,6 @@ import org.jclouds.cloudstack.options.ListNetworkOfferingsOptions; import org.jclouds.cloudstack.options.ListNetworksOptions; import org.jclouds.cloudstack.options.ListTemplatesOptions; import org.jclouds.cloudstack.options.ListVirtualMachinesOptions; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.util.InetAddresses2; import org.testng.annotations.AfterGroups; @@ -67,6 +66,7 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.common.collect.Ordering; +import com.google.common.net.HostAndPort; import com.google.common.net.HostSpecifier; /** @@ -282,7 +282,7 @@ public class VirtualMachineClientLiveTest extends BaseCloudStackClientLiveTest { assert HostSpecifier.isValid(vm.getIPAddress()); if (!InetAddresses2.isPrivateIPAddress(vm.getIPAddress())) { // not sure if the network is public or not, so we have to test - IPSocket socket = new IPSocket(vm.getIPAddress(), 22); + HostAndPort socket = HostAndPort.fromParts(vm.getIPAddress(), 22); System.err.printf("testing socket %s%n", socket); System.err.printf("testing ssh %s%n", socket); checkSSH(socket); diff --git a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/functions/StaticNATVirtualMachineInNetworkLiveTest.java b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/functions/StaticNATVirtualMachineInNetworkLiveTest.java index c0308fac3d..1b167a7205 100644 --- a/apis/cloudstack/src/test/java/org/jclouds/cloudstack/functions/StaticNATVirtualMachineInNetworkLiveTest.java +++ b/apis/cloudstack/src/test/java/org/jclouds/cloudstack/functions/StaticNATVirtualMachineInNetworkLiveTest.java @@ -37,7 +37,6 @@ import org.jclouds.cloudstack.features.NATClientLiveTest; import org.jclouds.cloudstack.features.VirtualMachineClientLiveTest; import org.jclouds.cloudstack.predicates.NetworkPredicates; import org.jclouds.cloudstack.strategy.BlockUntilJobCompletesAndReturnResult; -import org.jclouds.net.IPSocket; import org.testng.annotations.AfterGroups; import org.testng.annotations.BeforeGroups; import org.testng.annotations.Test; @@ -45,6 +44,7 @@ import org.testng.annotations.Test; import com.google.common.base.Predicate; import com.google.common.cache.CacheBuilder; import com.google.common.collect.ImmutableSet; +import com.google.common.net.HostAndPort; /** * Tests behavior of {@code StaticNATVirtualMachineInNetwork} @@ -106,7 +106,7 @@ public class StaticNATVirtualMachineInNetworkLiveTest extends NATClientLiveTest assertEquals(rule.getStartPort(), 22); assertEquals(rule.getProtocol(), "tcp"); checkRule(rule); - IPSocket socket = new IPSocket(ip.getIPAddress(), 22); + HostAndPort socket = HostAndPort.fromParts(ip.getIPAddress(), 22); checkSSH(socket); } diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatch.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatch.java new file mode 100644 index 0000000000..e544a8a411 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatch.java @@ -0,0 +1,87 @@ +/** + * 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.cloudwatch; + +import com.google.common.collect.AbstractIterator; +import org.jclouds.cloudwatch.domain.ListMetricsResponse; +import org.jclouds.cloudwatch.domain.Metric; +import org.jclouds.cloudwatch.features.MetricClient; +import org.jclouds.cloudwatch.options.ListMetricsOptions; + +import java.util.Iterator; + +/** + * Utilities for using CloudWatch. + * + * @author Jeremy Whitlock + */ +public class CloudWatch { + + /** + * List metrics based on the criteria in the {@link ListMetricsOptions} passed in. + * + * @param cloudWatchClient the CloudWatch client + * @param region the region to list metrics in + * @param options the options describing the ListMetrics request + * + * @return iterable of metrics fitting the criteria + */ + public static Iterable listMetrics(CloudWatchClient cloudWatchClient, String region, + final ListMetricsOptions options) { + final MetricClient metricClientForRegion = cloudWatchClient.getMetricClientForRegion(region); + return new Iterable() { + public Iterator iterator() { + return new AbstractIterator() { + + private ListMetricsOptions lastOptions = options; + private ListMetricsResponse response = metricClientForRegion.listMetrics(lastOptions); + private Iterator iterator = response.iterator(); + + /** + * {@inheritDoc} + */ + @Override + protected Metric computeNext() { + while (true) { + if (iterator == null) { + lastOptions = ListMetricsOptions.builder() + .dimensions(lastOptions.getDimensions()) + .metricName(lastOptions.getMetricName()) + .namespace(lastOptions.getNamespace()) + .nextToken(response.getNextToken()) + .build(); + response = metricClientForRegion.listMetrics(lastOptions); + iterator = response.iterator(); + } + if (iterator.hasNext()) { + return iterator.next(); + } + if (response.getNextToken() == null) { + return endOfData(); + } + iterator = null; + } + } + + }; + } + }; + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchApiMetadata.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchApiMetadata.java index d40bd4ee25..726aab070e 100644 --- a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchApiMetadata.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchApiMetadata.java @@ -73,7 +73,7 @@ public class CloudWatchApiMetadata extends BaseRestApiMetadata { .name("Amazon CloudWatch Api") .identityName("Access Key ID") .credentialName("Secret Access Key") - .version(CloudWatchAsyncClient.VERSION) + .version("2010-08-01") .documentation(URI.create("http://docs.amazonwebservices.com/AmazonCloudWatch/latest/APIReference/")) .defaultEndpoint("https://monitoring.us-east-1.amazonaws.com") .defaultProperties(CloudWatchApiMetadata.defaultProperties()) diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchAsyncClient.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchAsyncClient.java index 25b9978ba3..a609bc6e7c 100644 --- a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchAsyncClient.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchAsyncClient.java @@ -28,11 +28,14 @@ import javax.ws.rs.Path; import org.jclouds.aws.filters.FormSigner; import org.jclouds.cloudwatch.domain.Datapoint; import org.jclouds.cloudwatch.domain.Statistics; +import org.jclouds.cloudwatch.features.MetricAsyncClient; import org.jclouds.cloudwatch.functions.ISO8601Format; import org.jclouds.cloudwatch.options.GetMetricStatisticsOptions; import org.jclouds.cloudwatch.xml.GetMetricStatisticsResponseHandler; import org.jclouds.javax.annotation.Nullable; +import org.jclouds.location.Region; import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull; +import org.jclouds.rest.annotations.Delegate; import org.jclouds.rest.annotations.EndpointParam; import org.jclouds.rest.annotations.FormParams; import org.jclouds.rest.annotations.ParamParser; @@ -41,24 +44,32 @@ import org.jclouds.rest.annotations.VirtualHost; import org.jclouds.rest.annotations.XMLResponseParser; import com.google.common.util.concurrent.ListenableFuture; +import com.google.inject.Provides; /** * Provides access to Amazon CloudWatch via the Query API *

* * @see * @author Adrian Cole */ @RequestFilters(FormSigner.class) @VirtualHost public interface CloudWatchAsyncClient { - public static final String VERSION = "2010-08-01"; - /** - * @see CloudWatchClient#getMetricStatisticsInRegion + * + * @return the Region codes configured */ + @Provides + @Region + Set getConfiguredRegions(); + + /** + * @see MetricAsyncClient#getMetricStatistics + */ + @Deprecated @POST @Path("/") @XMLResponseParser(GetMetricStatisticsResponseHandler.class) @@ -72,4 +83,11 @@ public interface CloudWatchAsyncClient { @FormParam("Period") int period, @FormParam("Statistics.member.1") Statistics statistics, GetMetricStatisticsOptions... options); + + /** + * Provides asynchronous access to Metric features. + */ + @Delegate + MetricAsyncClient getMetricClientForRegion(@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region); + } diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchClient.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchClient.java index 341e099711..2633563111 100644 --- a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchClient.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/CloudWatchClient.java @@ -24,22 +24,36 @@ import java.util.concurrent.TimeUnit; import org.jclouds.cloudwatch.domain.Datapoint; import org.jclouds.cloudwatch.domain.Statistics; +import org.jclouds.cloudwatch.features.MetricClient; import org.jclouds.cloudwatch.options.GetMetricStatisticsOptions; import org.jclouds.concurrent.Timeout; import org.jclouds.javax.annotation.Nullable; +import org.jclouds.location.Region; +import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull; +import org.jclouds.rest.annotations.Delegate; +import org.jclouds.rest.annotations.EndpointParam; + +import com.google.inject.Provides; /** * Provides access to Amazon CloudWatch via the Query API *

* * @see * @author Adrian Cole */ @Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) public interface CloudWatchClient { - + /** + * + * @return the Region codes configured + */ + @Provides + @Region + Set getConfiguredRegions(); + /** * This call returns data for one or more statistics of given a metric. For more information, see * Statistic and Metric. @@ -76,8 +90,15 @@ public interface CloudWatchClient { * The statistics to be returned for the given metric. ex. Average * @param options * more filtering options (e.g. instance ID) + * @see MetricsClient#getMetricStatistics */ + @Deprecated Set getMetricStatisticsInRegion(@Nullable String region, String metricName, String namespace, - Date startTime, Date endTime, int period, Statistics statistics, GetMetricStatisticsOptions... options); - + Date startTime, Date endTime, int period, Statistics statistics, GetMetricStatisticsOptions... options); + + /** + * Provides synchronous access to Metric features. + */ + @Delegate + MetricClient getMetricClientForRegion(@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region); } diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/binders/GetMetricStatisticsBinder.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/binders/GetMetricStatisticsBinder.java new file mode 100644 index 0000000000..1e2b6f49c7 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/binders/GetMetricStatisticsBinder.java @@ -0,0 +1,80 @@ +/** + * 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.cloudwatch.binders; + +import javax.inject.Inject; + +import org.jclouds.cloudwatch.domain.Dimension; +import org.jclouds.cloudwatch.domain.GetMetricStatistics; +import org.jclouds.cloudwatch.domain.Statistics; +import org.jclouds.date.DateService; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.utils.ModifyRequest; + +import com.google.common.annotations.Beta; +import com.google.common.collect.ImmutableMultimap; + +/** + * Binds the metrics request to the http request + * + * @see + * + * @author Jeremy Whitlock, Adrian Cole + */ +@Beta +public class GetMetricStatisticsBinder implements org.jclouds.rest.Binder { + + private final DateService dateService; + + @Inject + protected GetMetricStatisticsBinder(DateService dateService){ + this.dateService =dateService; + } + + @Override + public R bindToRequest(R request, Object payload) { + GetMetricStatistics getRequest = GetMetricStatistics.class.cast(payload); + int dimensionIndex = 1; + int statisticIndex = 1; + + ImmutableMultimap.Builder formParameters = ImmutableMultimap. builder(); + for (Dimension dimension : getRequest.getDimensions()) { + formParameters.put("Dimensions.member." + dimensionIndex + ".Name", dimension.getName()); + formParameters.put("Dimensions.member." + dimensionIndex + ".Value", dimension.getValue()); + dimensionIndex++; + } + + formParameters.put("EndTime", dateService.iso8601SecondsDateFormat(getRequest.getEndTime())); + formParameters.put("MetricName", getRequest.getMetricName()); + formParameters.put("Namespace", getRequest.getNamespace()); + formParameters.put("Period", Integer.toString(getRequest.getPeriod())); + formParameters.put("StartTime", dateService.iso8601SecondsDateFormat(getRequest + .getStartTime())); + + for (Statistics statistic : getRequest.getStatistics()) { + formParameters.put("Statistics.member." + statisticIndex, statistic.toString()); + statisticIndex++; + } + + formParameters.put("Unit", getRequest.getUnit().toString()); + + return ModifyRequest.putFormParams(request, formParameters.build()); + } +} \ No newline at end of file diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/config/CloudWatchRestClientModule.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/config/CloudWatchRestClientModule.java index 7905335acb..15efa04983 100644 --- a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/config/CloudWatchRestClientModule.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/config/CloudWatchRestClientModule.java @@ -18,11 +18,18 @@ */ package org.jclouds.cloudwatch.config; +import java.util.Map; + import org.jclouds.aws.config.FormSigningRestClientModule; import org.jclouds.cloudwatch.CloudWatchAsyncClient; import org.jclouds.cloudwatch.CloudWatchClient; +import org.jclouds.cloudwatch.features.MetricAsyncClient; +import org.jclouds.cloudwatch.features.MetricClient; import org.jclouds.rest.ConfiguresRestClient; +import com.google.common.collect.ImmutableMap; +import com.google.common.reflect.TypeToken; + /** * Configures the Monitoring connection. * @@ -30,5 +37,12 @@ import org.jclouds.rest.ConfiguresRestClient; */ @ConfiguresRestClient public class CloudWatchRestClientModule extends FormSigningRestClientModule { + public static final Map, Class> DELEGATE_MAP = ImmutableMap., Class> builder()// + .put(MetricClient.class, MetricAsyncClient.class) + .build(); + + public CloudWatchRestClientModule() { + super(TypeToken.of(CloudWatchClient.class), TypeToken.of(CloudWatchAsyncClient.class), DELEGATE_MAP); + } } diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/AutoScalingConstants.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/AutoScalingConstants.java new file mode 100644 index 0000000000..c2f1a88da7 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/AutoScalingConstants.java @@ -0,0 +1,48 @@ +/** + * 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.cloudwatch.domain; + +/** + * Constants interface for the AWS AutoScaling dimensions and metric names as of 2012-04-24. + * + * @see + * + * @author Jeremy Whitlock + */ +public interface AutoScalingConstants { + + public static class Dimension { + + public static final String AUTO_SCALING_GROUP_NAME = "AutoScalingGroupName"; + + } + + public static class MetricName { + + public static final String GROUP_DESIRED_CAPACITY = "GroupDesiredCapacity"; + public static final String GROUP_IN_SERVICE_INSTANCES = "GroupInServiceInstances"; + public static final String GROUP_MAX_SIZE = "GroupMaxSize"; + public static final String GROUP_MIN_SIZE = "GroupMinSize"; + public static final String GROUP_PENDING_INSTANCES = "GroupPendingInstances"; + public static final String GROUP_TERMINATING_INSTANCES = "GroupTerminatingInstances"; + public static final String GROUP_TOTAL_INSTANCES = "GroupTotalInstances"; + + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Datapoint.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Datapoint.java index 9548321cb3..f430a647a4 100644 --- a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Datapoint.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Datapoint.java @@ -18,12 +18,13 @@ */ package org.jclouds.cloudwatch.domain; -import java.util.Date; - +import com.google.common.base.Objects; import org.jclouds.javax.annotation.Nullable; +import java.util.Date; + /** - * @see * * @author Adrian Cole @@ -118,17 +119,7 @@ public class Datapoint { @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((average == null) ? 0 : average.hashCode()); - result = prime * result + ((customUnit == null) ? 0 : customUnit.hashCode()); - result = prime * result + ((maximum == null) ? 0 : maximum.hashCode()); - result = prime * result + ((minimum == null) ? 0 : minimum.hashCode()); - result = prime * result + ((samples == null) ? 0 : samples.hashCode()); - result = prime * result + ((sum == null) ? 0 : sum.hashCode()); - result = prime * result + ((timestamp == null) ? 0 : timestamp.hashCode()); - result = prime * result + ((unit == null) ? 0 : unit.hashCode()); - return result; + return Objects.hashCode(average, customUnit, maximum, minimum, samples, sum, timestamp, unit); } @Override @@ -140,53 +131,27 @@ public class Datapoint { if (getClass() != obj.getClass()) return false; Datapoint other = (Datapoint) obj; - if (average == null) { - if (other.average != null) - return false; - } else if (!average.equals(other.average)) - return false; - if (customUnit == null) { - if (other.customUnit != null) - return false; - } else if (!customUnit.equals(other.customUnit)) - return false; - if (maximum == null) { - if (other.maximum != null) - return false; - } else if (!maximum.equals(other.maximum)) - return false; - if (minimum == null) { - if (other.minimum != null) - return false; - } else if (!minimum.equals(other.minimum)) - return false; - if (samples == null) { - if (other.samples != null) - return false; - } else if (!samples.equals(other.samples)) - return false; - if (sum == null) { - if (other.sum != null) - return false; - } else if (!sum.equals(other.sum)) - return false; - if (timestamp == null) { - if (other.timestamp != null) - return false; - } else if (!timestamp.equals(other.timestamp)) - return false; - if (unit == null) { - if (other.unit != null) - return false; - } else if (!unit.equals(other.unit)) - return false; - return true; + return Objects.equal(this.average, other.average) && + Objects.equal(this.customUnit, other.customUnit) && + Objects.equal(this.maximum, other.maximum) && + Objects.equal(this.minimum, other.minimum) && + Objects.equal(this.samples, other.samples) && + Objects.equal(this.sum, other.sum) && + Objects.equal(this.timestamp, other.timestamp) && + Objects.equal(this.unit, other.unit); } @Override public String toString() { - return "[average=" + average + ", customUnit=" + customUnit + ", maximum=" + maximum + ", minimum=" + minimum - + ", samples=" + samples + ", sum=" + sum + ", timestamp=" + timestamp + ", unit=" + unit + "]"; + return Objects.toStringHelper(this) + .add("timestamp", timestamp) + .add("customUnit", customUnit) + .add("maximum", maximum) + .add("minimum", minimum) + .add("average", average) + .add("sum", sum) + .add("samples", samples) + .add("unit", unit).toString(); } } diff --git a/core/src/main/java/org/jclouds/net/IPSocket.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Dimension.java similarity index 50% rename from core/src/main/java/org/jclouds/net/IPSocket.java rename to apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Dimension.java index 315086641a..6fe8228c84 100644 --- a/core/src/main/java/org/jclouds/net/IPSocket.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Dimension.java @@ -16,45 +16,50 @@ * specific language governing permissions and limitations * under the License. */ -package org.jclouds.net; +package org.jclouds.cloudwatch.domain; -import java.io.Serializable; +import com.google.common.base.Objects; /** - * As google appengine prohibits use of java.net classes, this will serve as a replacement. - * - * @author Adrian Cole + * @see + * + * @author Jeremy Whitlock */ -public class IPSocket implements Serializable { +public class Dimension { - /** The serialVersionUID */ - private static final long serialVersionUID = 2978329372952402188L; + private final String name; + private final String value; - private final String address; - private final int port; - - public IPSocket(String address, int port) { - this.address = address; - this.port = port; + public Dimension(String name, String value) { + this.name = name; + this.value = value; } - public String getAddress() { - return address; + /** + * return the dimension name. + */ + public String getName() { + return name; } - public int getPort() { - return port; + /** + * return the dimension value. + */ + public String getValue() { + return value; } + /** + * {@inheritDoc} + */ @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((address == null) ? 0 : address.hashCode()); - result = prime * result + port; - return result; + return Objects.hashCode(name, value); } + /** + * {@inheritDoc} + */ @Override public boolean equals(Object obj) { if (this == obj) @@ -63,20 +68,19 @@ public class IPSocket implements Serializable { return false; if (getClass() != obj.getClass()) return false; - IPSocket other = (IPSocket) obj; - if (address == null) { - if (other.address != null) - return false; - } else if (!address.equals(other.address)) - return false; - if (port != other.port) - return false; - return true; + Dimension other = (Dimension)obj; + return Objects.equal(this.name, other.name) && + Objects.equal(this.value, other.value); } + /** + * {@inheritDoc} + */ @Override public String toString() { - return "[address=" + address + ", port=" + port + "]"; + return Objects.toStringHelper(this) + .add("name", name) + .add("value", value).toString(); } } diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/DynamoDBConstants.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/DynamoDBConstants.java new file mode 100644 index 0000000000..2481e7288e --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/DynamoDBConstants.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.cloudwatch.domain; + +/** + * Constants interface for the AWS AutoScaling dimensions and metric names as of 2012-04-24. + * + * @see + * + * @author Jeremy Whitlock + */ +public interface DynamoDBConstants { + + public static class Dimension { + + public static final String OPERATION = "Operation"; + public static final String TABLE_NAME = "TableName"; + + } + + public static class MetricName { + + public static final String CONSUMED_READ_CAPACITY_UNITS = "ConsumedReadCapacityUnits"; + public static final String CONSUMED_WRITE_CAPACITY_UNITS = "ConsumedWriteCapacityUnits"; + public static final String SUCCESSFUL_REQUEST_LATENCY = "SuccessfulRequestLatency"; + public static final String RETURNED_ITEM_COUNT = "ReturnedItemCount"; + public static final String SYSTEM_ERRORS = "SystemErrors"; + public static final String THROTTLED_REQUESTS = "ThrottledRequests"; + public static final String USER_ERRORS = "UserErrors"; + + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/EBSConstants.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/EBSConstants.java new file mode 100644 index 0000000000..d8b601ec72 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/EBSConstants.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.cloudwatch.domain; + +/** + * Constants interface for the AWS AutoScaling dimensions and metric names as of 2012-04-24. + * + * @see + * + * @author Jeremy Whitlock + */ +public interface EBSConstants { + + public static class Dimension { + + public static final String VOLUME_ID = "VolumeId"; + + } + + public static class MetricName { + + public static final String VOLUME_IDLE_TIME = "VolumeIdleTime"; + public static final String VOLUME_QUEUE_LENGTH = "VolumeQueueLength"; + public static final String VOLUME_READ_BYTES = "VolumeReadBytes"; + public static final String VOLUME_READ_OPS = "VolumeReadOps"; + public static final String VOLUME_TOTAL_READ_TIME = "VolumeTotalReadTime"; + public static final String VOLUME_TOTAL_WRITE_TIME = "VolumeTotalWriteTime"; + public static final String VOLUME_WRITE_BYTES = "VolumeWriteBytes"; + public static final String VOLUME_WRITE_OPS = "VolumeWriteOps"; + + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/EC2Constants.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/EC2Constants.java new file mode 100644 index 0000000000..544fcfc307 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/EC2Constants.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.cloudwatch.domain; + +/** + * Constants interface for the AWS AutoScaling dimensions and metric names as of 2012-04-24. + * + * @see + * + * @author Jeremy Whitlock + */ +public interface EC2Constants { + + public static class Dimension { + + public static final String AUTO_SCALING_GROUP_NAME = "AutoScalingGroupName"; + public static final String IMAGE_ID = "ImageId"; + public static final String INSTANCE_ID = "InstanceId"; + public static final String INSTANCE_TYPE = "InstanceType"; + + } + + public static class MetricName { + + public static final String CPU_UTILIZATION = "CPUUtilization"; + public static final String DISK_READ_BYTES = "DiskReadBytes"; + public static final String DISK_READ_OPS = "DiskReadOps"; + public static final String DISK_WRITE_BYTES = "DiskWriteBytes"; + public static final String DISK_WRITE_OPS = "DiskWriteOps"; + public static final String NETWORK_IN = "NetworkIn"; + public static final String NETWORK_OUT = "NetworkOut"; + + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/ELBConstants.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/ELBConstants.java new file mode 100644 index 0000000000..25fc8974f4 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/ELBConstants.java @@ -0,0 +1,52 @@ +/** + * 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.cloudwatch.domain; + +/** + * Constants interface for the AWS AutoScaling dimensions and metric names as of 2012-04-24. + * + * @see + * + * @author Jeremy Whitlock + */ +public interface ELBConstants { + + public static class Dimension { + + public static final String AVAILABILITY_ZONE = "AvailabilityZone"; + public static final String LOAD_BALANCER_NAME = "LoadBalancerName"; + + } + + public static class MetricName { + + public static final String HEALTHY_HOST_COUNT = "HealthyHostCount"; + public static final String HTTP_CODE_BACKEND_2XX = "HTTPCode_Backend_2XX"; + public static final String HTTP_CODE_BACKEND_3XX = "HTTPCode_Backend_3XX"; + public static final String HTTP_CODE_BACKEND_4XX = "HTTPCode_Backend_4XX"; + public static final String HTTP_CODE_BACKEND_5XX = "HTTPCode_Backend_5XX"; + public static final String HTTP_CODE_ELB_4XX = "HTTPCode_ELB_4XX"; + public static final String HTTP_CODE_ELB_5XX = "HTTPCode_ELB_5XX"; + public static final String LATENCY = "Latency"; + public static final String REQUEST_COUNT = "RequestCount"; + public static final String UNHEALTHY_HOST_COUNT = "UnHealthyHostCount"; + + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/EMRConstants.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/EMRConstants.java new file mode 100644 index 0000000000..4623146a32 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/EMRConstants.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.cloudwatch.domain; + +/** + * Constants interface for the AWS AutoScaling dimensions and metric names as of 2012-04-24. + * + * @see + * + * @author Jeremy Whitlock + */ +public interface EMRConstants { + + public static class Dimension { + + public static final String JOB_FLOW_ID = "JobFlowId"; + public static final String JOB_ID = "JobId"; + + } + + public static class MetricName { + + public static final String CORE_NODES_PENDING = "CoreNodesPending"; + public static final String CORE_NODES_RUNNING = "CoreNodesRunning"; + public static final String HDFS_BYTES_READ = "HDFSBytesRead"; + public static final String HDFS_BYTES_WRITTEN = "HDFSBytesWritten"; + public static final String HDFS_UTILIZATION = "HDFSUtilization"; + public static final String IS_IDLE = "IsIdle"; + public static final String JOBS_FAILED = "JobsFailed"; + public static final String JOBS_RUNNING = "JobsRunning"; + public static final String LIVE_DATA_NODES = "LiveDataNodes"; + public static final String LIVE_TASK_TRACKERS = "LiveTaskTrackers"; + public static final String MAP_SLOTS_OPEN = "MapSlotsOpen"; + public static final String MISSING_BLOCKS = "MissingBlocks"; + public static final String REDUCE_SLOTS_OPEN = "ReduceSlotsOpen"; + public static final String REMAINING_MAP_TASKS = "RemainingMapTasks"; + public static final String REMAINING_MAP_TASKS_PER_SLOT = "RemainingMapTasksPerSlot"; + public static final String REMAINING_REDUCE_TASKS = "RemainingReduceTasks"; + public static final String RUNNING_MAP_TASKS = "RunningMapTasks"; + public static final String RUNNING_REDUCE_TASKS = "RunningReduceTasks"; + public static final String S3_BYTES_READ = "S3BytesRead"; + public static final String S3_BYTES_WRITTEN = "S3BytesWritten"; + public static final String TASK_NODES_PENDING = "TaskNodesPending"; + public static final String TASK_NODES_RUNNING = "TaskNodesRunning"; + public static final String TOTAL_LOAD = "TotalLoad"; + + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/GetMetricStatistics.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/GetMetricStatistics.java new file mode 100644 index 0000000000..1b5167c293 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/GetMetricStatistics.java @@ -0,0 +1,342 @@ +/** + * 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.cloudwatch.domain; + +import java.util.Date; +import java.util.Set; + +import org.jclouds.cloudwatch.options.ListMetricsOptions; +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.collect.Sets; + +/** + * Options use to get statistics for the specified metric. + * + * @see + * + * @author Jeremy Whitlock + */ +@Beta +public class GetMetricStatistics { + + private final Set dimensions; + private final Date endTime; + private final String metricName; + private final String namespace; + private final int period; + private final Date startTime; + private final Set statistics; + private final Unit unit; + + /** + * Private constructor to enforce using {@link Builder}. + */ + private GetMetricStatistics(@Nullable Set dimensions, Date endTime, String metricName, + String namespace, int period, Date startTime, Set statistics, + Unit unit) { + this.dimensions = dimensions; + this.endTime = endTime; + this.metricName = metricName; + this.namespace = namespace; + this.period = period; + this.startTime = startTime; + this.statistics = statistics; + this.unit = unit; + } + + /** + * return the set of dimensions for this request + */ + @Nullable + public Set getDimensions() { + return dimensions; + } + + /** + * return the end time for this request + */ + public Date getEndTime() { + return endTime; + } + + /** + * return the metric name for this request + */ + public String getMetricName() { + return metricName; + } + + /** + * return the namespace for this request + */ + public String getNamespace() { + return namespace; + } + + /** + * return the period for this request + */ + public int getPeriod() { + return period; + } + + /** + * return the start time for this request + */ + public Date getStartTime() { + return startTime; + } + + /** + * return the statistics for this request + */ + public Set getStatistics() { + return statistics; + } + + /** + * return the unit for this request + */ + public Unit getUnit() { + return unit; + } + + /** + * Returns a new builder. The generated builder is equivalent to the builder + * created by the {@link Builder} constructor. + */ + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private Set dimensions = Sets.newLinkedHashSet(); + private Date endTime; + private String metricName; + private String namespace; + private int period; + private Date startTime; + private Set statistics = Sets.newLinkedHashSet(); + private Unit unit; + + /** + * Creates a new builder. The returned builder is equivalent to the builder + * generated by {@link ListMetricsOptions#builder}. + */ + public Builder() {} + + /** + * A list of dimensions describing qualities of the metric. (Set can be 10 or less items.) + * + * @param dimensions the dimensions describing the qualities of the metric + * + * @return this {@code Builder} object + * + * @throws IllegalArgumentException if this is invoked more than 10 times + */ + public Builder dimensions(Set dimensions) { + if (dimensions != null) { + Preconditions.checkArgument(dimensions.size() <= 10, "dimensions can have 10 or fewer members."); + this.dimensions = dimensions; + } + return this; + } + + /** + * A dimension describing qualities of the metric. (Can be called multiple times up to a maximum of 10 times.) + * + * @param dimension the dimension describing the qualities of the metric + * + * @return this {@code Builder} object + * + * @throws IllegalArgumentException if the number of dimensions would be greater than 10 after adding + */ + public Builder dimension(Dimension dimension) { + if (dimension != null) { + Preconditions.checkArgument(dimensions.size() < 10, "dimension member maximum count of 10 exceeded."); + this.dimensions.add(dimension); + } + return this; + } + + /** + * The time stamp to use for determining the last datapoint to return. The value specified is exclusive so + * results will include datapoints up to the time stamp specified. (Should be called once. Subsequent calls + * will overwrite the previous value.) + * + * @param endTime the timestamp to use for determining the last datapoint to return + * + * @return this {@code Builder} object + * + * @throws NullPointerException if endTime is null + */ + public Builder endTime(Date endTime) { + Preconditions.checkNotNull(endTime, "endTime cannot be null."); + this.endTime = endTime; + return this; + } + + /** + * The name of the metric. (Should be called once. Subsequent calls will overwrite the previous value.) + * + * @param metricName the metric name to filter against + * + * @return this {@code Builder} object + * + * @throws NullPointerException if metricName is null + * @throws IllegalArgumentException if metricName is empty + */ + public Builder metricName(String metricName) { + Preconditions.checkNotNull(metricName, "metricName cannot be null."); + Preconditions.checkArgument(metricName.length() > 1, "metricName must not be empty."); + this.metricName = metricName; + return this; + } + + /** + * The namespace of the metric. (Should be called once. Subsequent calls will overwrite the previous value. + * See {@link org.jclouds.cloudwatch.domain.Namespaces} for the known list of namespaces.) + * + * @param namespace the namespace to filter against + * + * @return this {@code Builder} object + * + * @throws NullPointerException if namespace is null + * @throws IllegalArgumentException if namespace is empty + */ + public Builder namespace(String namespace) { + Preconditions.checkNotNull(namespace, "namespace cannot be null."); + Preconditions.checkArgument(namespace.length() > 1, "namespace must not be empty."); + this.namespace = namespace; + return this; + } + + /** + * The granularity, in seconds, of the returned datapoints. Period must be at least 60 seconds and must be a + * multiple of 60. The default value is 60. (Should be called once. Subsequent calls will overwrite the + * previous value.) + * + * @param period the granularity, in seconds, of the returned datapoints + * + * @return this {@code Builder} object + * + * @throws NullPointerException if period is null + * @throws IllegalArgumentException if period is less than 60 or not a multiple of 60 + */ + public Builder period(int period) { + Preconditions.checkNotNull(period, "period cannot be null."); + Preconditions.checkArgument(period >= 60 && period % 60 == 0, "period must be greater than 60 and as a " + + "multiple of 60."); + this.period = period; + return this; + } + + /** + * The time stamp to use for determining the first datapoint to return. The value specified is inclusive so + * results include datapoints with the time stamp specified. (Should be called once. Subsequent calls will + * overwrite the previous value.) + * + * @param startTime The time stamp to use for determining the first datapoint to return + * + * @return this {@code Builder} object + * + * @throws NullPointerException if startTime is null + */ + public Builder startTime(Date startTime) { + Preconditions.checkNotNull(startTime, "startTime cannot be null."); + this.startTime = startTime; + return this; + } + + /** + * The metric statistics to return. (Should be called once. Subsequent calls will overwrite the previous + * value.) + * + * @param statistics the metric statistics to return. + * + * @return this {@code Builder} object + * + * @throws IllegalArgumentException if the number of statistics is greater than 5 + * @throws NullPointerException if statistics is null + */ + public Builder statistics(Set statistics) { + Preconditions.checkNotNull(statistics, "statistics cannot be null."); + Preconditions.checkArgument(statistics.size() <= 5, "statistics can have 5 or fewer members."); + this.statistics = statistics; + return this; + } + + /** + * The metric statistic to return. (Can be called multiple times up to a maximum of 5 times.) + * + * @param statistic the metric statistic to return + * + * @return this {@code Builder} object + * + * @throws IllegalArgumentException if the number of statistics would be greater than 5 after adding + * @throws NullPointerException if statistic is null + */ + public Builder statistic(Statistics statistic) { + Preconditions.checkNotNull(statistic, "statistic cannot be null."); + Preconditions.checkArgument(statistics.size() < 5, "statistics member maximum count of 5 exceeded."); + this.statistics.add(statistic); + return this; + } + + /** + * The unit for the metric. (Should be called once. Subsequent calls will overwrite the previous value.) + * + * @param unit the unit for the metric + * + * @return this {@code Builder} object + * + * @throws NullPointerException if unit is null + */ + public Builder unit(Unit unit) { + Preconditions.checkNotNull(unit, "unit cannot be null."); + this.unit = unit; + return this; + } + + /** + * Returns a newly-created {@code GetMetricStatisticsOptionsV2} based on the contents of + * the {@code Builder}. + * + * @throws NullPointerException if any of the required fields are null + * @throws IllegalArgumentException if any of the provided fields don't meet required criteria + */ + public GetMetricStatistics build() { + Preconditions.checkNotNull(endTime, "endTime cannot be null."); + Preconditions.checkNotNull(metricName, "metricName cannot be null."); + Preconditions.checkNotNull(namespace, "namespace cannot be null."); + Preconditions.checkNotNull(period, "period cannot be null."); + Preconditions.checkNotNull(startTime, "startTime cannot be null."); + Preconditions.checkNotNull(statistics, "statistics cannot be null."); + Preconditions.checkNotNull(unit, "unit cannot be null."); + Preconditions.checkArgument(statistics.size() >= 1, "statistics must have at least one member"); + + return new GetMetricStatistics(dimensions, endTime, metricName,namespace, period, startTime, statistics, unit); + } + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/GetMetricStatisticsResponse.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/GetMetricStatisticsResponse.java new file mode 100644 index 0000000000..146de9c569 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/GetMetricStatisticsResponse.java @@ -0,0 +1,97 @@ +/** + * 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.cloudwatch.domain; + +import java.util.Set; + +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.base.Objects; +import com.google.common.collect.ForwardingSet; +import com.google.common.collect.ImmutableSet; + +/** + * the list of {@link Datapoint} for the metric + * + * @see + * + * @author Jeremy Whitlock + */ +public class GetMetricStatisticsResponse extends ForwardingSet { + + private final Set datapoints; + private final String label; + + public GetMetricStatisticsResponse(@Nullable Set datapoints, String label) { + // Default to an empty set + if (datapoints == null) { + this.datapoints = ImmutableSet.of(); + } else { + this.datapoints = ImmutableSet.copyOf(datapoints); + } + this.label = label; + } + + /** + * return the label describing the specified metric + */ + public String getLabel() { + return label; + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + return Objects.hashCode(datapoints, label); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + GetMetricStatisticsResponse other = (GetMetricStatisticsResponse)obj; + return Objects.equal(this.datapoints, other.datapoints) && + Objects.equal(this.label, other.label); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return Objects.toStringHelper(this) + .add("label", label) + .add("datapoints", datapoints).toString(); + } + + @Override + protected Set delegate() { + return datapoints; + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/ListMetricsResponse.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/ListMetricsResponse.java new file mode 100644 index 0000000000..77e2810863 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/ListMetricsResponse.java @@ -0,0 +1,97 @@ +/** + * 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.cloudwatch.domain; + +import java.util.Set; + +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.base.Objects; +import com.google.common.collect.ForwardingSet; +import com.google.common.collect.ImmutableSet; + +/** + * list of {@link Metric} + * @see + * + * @author Jeremy Whitlock + */ +public class ListMetricsResponse extends ForwardingSet{ + + private final Set metrics; + private final String nextToken; + + public ListMetricsResponse(@Nullable Set metrics, @Nullable String nextToken) { + // Default to an empty set + if (metrics == null) { + this.metrics = ImmutableSet.of(); + } else { + this.metrics = ImmutableSet.copyOf(metrics); + } + this.nextToken = nextToken; + } + + /** + * return the next token or null if there is none. + */ + @Nullable + public String getNextToken() { + return nextToken; + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + return Objects.hashCode(metrics, nextToken); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ListMetricsResponse other = (ListMetricsResponse)obj; + return Objects.equal(this.metrics, other.metrics) && + Objects.equal(this.nextToken, other.nextToken); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return Objects.toStringHelper(this) + .add("metrics", metrics) + .add("nextToken", nextToken).toString(); + } + + @Override + protected Set delegate() { + return metrics; + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Metric.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Metric.java new file mode 100644 index 0000000000..1a4f79d282 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Metric.java @@ -0,0 +1,108 @@ +/** + * 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.cloudwatch.domain; + +import com.google.common.base.Objects; +import com.google.common.collect.Sets; +import org.jclouds.javax.annotation.Nullable; + +import java.util.Set; + +/** + * @see + * + * @author Jeremy Whitlock + */ +public class Metric { + + private final Set dimensions; + private final String metricName; + private final String namespace; + + public Metric (String metricName, String namespace, @Nullable Set dimensions) { + // Default to an empty set + if (dimensions == null) { + this.dimensions = Sets.newLinkedHashSet(); + } else { + this.dimensions = dimensions; + } + + this.metricName = metricName; + this.namespace = namespace; + } + + /** + * return the metric name for the metric. + */ + public String getMetricName() { + return metricName; + } + + /** + * return the namespace for the metric + */ + public String getNamespace() { + return namespace; + } + + /** + * return the available dimensions for the metric + */ + @Nullable + public Set getDimensions() { + return dimensions; + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + return Objects.hashCode(dimensions, metricName, namespace); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Metric other = (Metric)obj; + return Objects.equal(this.dimensions, other.dimensions) && + Objects.equal(this.metricName, other.metricName) && + Objects.equal(this.namespace, other.namespace); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return Objects.toStringHelper(this) + .add("namespace", namespace) + .add("metricName", metricName) + .add("dimension", dimensions).toString(); + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Namespaces.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Namespaces.java new file mode 100644 index 0000000000..8d67b1af4a --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/Namespaces.java @@ -0,0 +1,41 @@ +/** + * 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.cloudwatch.domain; + +/** + * Constants interface for the AWS provided namespaces as of 2012-04-24. + * + * @see + * + * @author Jeremy Whitlock + */ +public interface Namespaces { + + public static final String AUTO_SCALING = "AWS/AutoScaling"; + public static final String DYNAMODB = "AWS/DynamoDB"; + public static final String EBS = "AWS/EBS"; + public static final String EC2 = "AWS/EC2"; + public static final String ELB = "AWS/ELB"; + public static final String EMR = "AWS/EMR"; + public static final String RDS = "AWS/RDS"; + public static final String SNS = "AWS/SNS"; + public static final String SQS = "AWS/SQS"; + public static final String STORAGE_GATEWAY = "AWS/StorageGateway"; + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/RDSConstants.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/RDSConstants.java new file mode 100644 index 0000000000..66ed13e299 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/RDSConstants.java @@ -0,0 +1,56 @@ +/** + * 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.cloudwatch.domain; + +/** + * Constants interface for the AWS AutoScaling dimensions and metric names as of 2012-04-24. + * + * @see + * + * @author Jeremy Whitlock + */ +public interface RDSConstants { + + public static class Dimension { + + public static final String DB_INSTANCE_IDENTIFIER = "DBInstanceIdentifier"; + public static final String DATABASE_CLASS = "DatabaseClass"; + public static final String ENGINE_NAME = "EngineName"; + + } + + public static class MetricName { + + public static final String BIN_LOG_DISK_USAGE = "BinLogDiskUsage"; + public static final String CPU_UTILIZATION = "CPUUtilization"; + public static final String DATABASE_CONNECTIONS = "DatabaseConnections"; + public static final String FREEABLE_MEMORY = "FreeableMemory"; + public static final String FREE_STORAGE_SPACE = "FreeStorageSpace"; + public static final String REPLICA_LAG = "ReplicaLag"; + public static final String READ_IO_OPS = "ReadIOPS"; + public static final String READ_LATENCY = "ReadLatency"; + public static final String READ_THROUGHPUT = "ReadThroughput"; + public static final String SWAP_USAGE = "SwapUsage"; + public static final String WRITE_IO_OPS = "WriteIOPS"; + public static final String WRITE_LATENCY = "WriteLtency"; + public static final String WRITE_THROUGHPUT = "WriteThroughput"; + + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/SNSConstants.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/SNSConstants.java new file mode 100644 index 0000000000..b87c0b43af --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/SNSConstants.java @@ -0,0 +1,45 @@ +/** + * 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.cloudwatch.domain; + +/** + * Constants interface for the AWS AutoScaling dimensions and metric names as of 2012-04-24. + * + * @see + * + * @author Jeremy Whitlock + */ +public interface SNSConstants { + + public static class Dimension { + + public static final String TOPIC_NAME = "TopicName"; + + } + + public static class MetricName { + + public static final String NUMBER_OF_MESSAGES_PUBLISHED = "NumberOfMessagesPublished"; + public static final String NUMBER_OF_NOTIFICATIONS_DELIVERED = "NumberOfNotificationsDelivered"; + public static final String NUMBER_OF_NOTIFICATIONS_FAILED = "NumberOfNotificationsFailed"; + public static final String PUBLISH_SIZE = "PublishSize"; + + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/SQSConstants.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/SQSConstants.java new file mode 100644 index 0000000000..0ebe0442ca --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/SQSConstants.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.cloudwatch.domain; + +/** + * Constants interface for the AWS AutoScaling dimensions and metric names as of 2012-04-24. + * + * @see + * + * @author Jeremy Whitlock + */ +public interface SQSConstants { + + public static class Dimension { + + public static final String QUEUE_NAME = "QueueName"; + + } + + public static class MetricName { + + public static final String APPROXIMATE_NUMBER_OF_MESSAGES_DELAYED = "ApproximateNumberOfMessagesDelayed"; + public static final String APPROXIMATE_NUMBER_OF_MESSAGES_NOT_VISIBLE = "ApproximateNumberOfMessagesNotVisible"; + public static final String APPROXIMATE_NUMBER_OF_MESSAGES_VISIBLE = "ApproximateNumberOfMessagesVisible"; + public static final String NUMBER_OF_EMPTY_RECEIVES = "NumberOfEmptyReceives"; + public static final String NUMBER_OF_MESSAGES_DELETED = "NumberOfMessagesDeleted"; + public static final String NUMBER_OF_MESSAGES_RECEIVED = "NumberOfMessagesReceived"; + public static final String NUMBER_OF_MESSAGES_SENT = "NumberOfMessagesSent"; + public static final String SENT_MESSAGES_SIZE = "SentMessageSize"; + + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/StorageGatewayConstants.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/StorageGatewayConstants.java new file mode 100644 index 0000000000..9128b1b5b4 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/domain/StorageGatewayConstants.java @@ -0,0 +1,57 @@ +/** + * 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.cloudwatch.domain; + +/** + * Constants interface for the AWS AutoScaling dimensions and metric names as of 2012-04-24. + * + * @see + * + * @author Jeremy Whitlock + */ +public interface StorageGatewayConstants { + + public static class Dimension { + + public static final String GATEWAY_ID = "GatewayId"; + public static final String GATEWAY_NAME = "GatewayName"; + public static final String VOLUME_ID = "VolumeId"; + + } + + public static class MetricName { + + // Applicable for all Dimensions + public static final String QUEUED_WRITES = "QueuedWrites"; + public static final String READ_BYTES = "ReadBytes"; + public static final String READ_TIME = "ReadTime"; + public static final String WRITE_BYTES = "WriteBytes"; + public static final String WRITE_TIME = "WriteTime"; + + // Applicable for only GatewayId and GatewayName Dimensions + public static final String CLOUD_BYTES_DOWNLOADED = "CloudBytesDownloaded"; + public static final String CLOUD_BYTES_UPLOADED = "CloudBytesUploaded"; + public static final String CLOUD_DOWNLOAD_LATENCY = "CloudDownloadLatency"; + public static final String WORKING_STORAGE_FREE = "WorkingStorageFree"; + public static final String WORKING_STORAGE_PERCENT_USED = "WorkingStoragePercentUsed"; + public static final String WORKING_STORAGE_USED = "WorkingStorageUsed"; + + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/features/MetricAsyncClient.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/features/MetricAsyncClient.java new file mode 100644 index 0000000000..6c1852e2c2 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/features/MetricAsyncClient.java @@ -0,0 +1,91 @@ +/** + * 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.cloudwatch.features; + +import javax.ws.rs.POST; +import javax.ws.rs.Path; + +import org.jclouds.aws.filters.FormSigner; +import org.jclouds.cloudwatch.binders.GetMetricStatisticsBinder; +import org.jclouds.cloudwatch.domain.GetMetricStatistics; +import org.jclouds.cloudwatch.domain.GetMetricStatisticsResponse; +import org.jclouds.cloudwatch.domain.ListMetricsResponse; +import org.jclouds.cloudwatch.options.GetMetricStatisticsOptions; +import org.jclouds.cloudwatch.options.ListMetricsOptions; +import org.jclouds.cloudwatch.xml.GetMetricStatisticsResponseHandlerV2; +import org.jclouds.cloudwatch.xml.ListMetricsResponseHandler; +import org.jclouds.rest.annotations.BinderParam; +import org.jclouds.rest.annotations.FormParams; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.VirtualHost; +import org.jclouds.rest.annotations.XMLResponseParser; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides access to Amazon CloudWatch via the Query API + *

+ * + * @see + * @author Jeremy Whitlock + */ +@RequestFilters(FormSigner.class) +@VirtualHost +public interface MetricAsyncClient { + + /** + * @see MetricClient#listMetrics() + */ + @POST + @Path("/") + @XMLResponseParser(ListMetricsResponseHandler.class) + @FormParams(keys = "Action", values = "ListMetrics") + ListenableFuture listMetrics(); + + /** + * @see MetricClient#listMetrics(ListMetricsOptions) + */ + @POST + @Path("/") + @XMLResponseParser(ListMetricsResponseHandler.class) + @FormParams(keys = "Action", values = "ListMetrics") + ListenableFuture listMetrics(ListMetricsOptions options); + + /** + * @see MetricClient#getMetricStatistics(GetMetricStatistics) + */ + @POST + @Path("/") + @XMLResponseParser(GetMetricStatisticsResponseHandlerV2.class) + @FormParams(keys = "Action", values = "GetMetricStatistics") + ListenableFuture getMetricStatistics( + @BinderParam(GetMetricStatisticsBinder.class) GetMetricStatistics statistics); + + /** + * @see MetricClient#getMetricStatistics(GetMetricStatistics, GetMetricStatisticsOptions) + */ + @POST + @Path("/") + @XMLResponseParser(GetMetricStatisticsResponseHandlerV2.class) + @FormParams(keys = "Action", values = "GetMetricStatistics") + ListenableFuture getMetricStatistics( + @BinderParam(GetMetricStatisticsBinder.class) GetMetricStatistics statistics, + GetMetricStatisticsOptions options); + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/features/MetricClient.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/features/MetricClient.java new file mode 100644 index 0000000000..7f5d465185 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/features/MetricClient.java @@ -0,0 +1,73 @@ +/** + * 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.cloudwatch.features; + +import java.util.concurrent.TimeUnit; + +import org.jclouds.cloudwatch.domain.GetMetricStatistics; +import org.jclouds.cloudwatch.domain.GetMetricStatisticsResponse; +import org.jclouds.cloudwatch.domain.ListMetricsResponse; +import org.jclouds.cloudwatch.options.GetMetricStatisticsOptions; +import org.jclouds.cloudwatch.options.ListMetricsOptions; +import org.jclouds.concurrent.Timeout; + +/** + * Provides access to Amazon CloudWatch via the Query API + *

+ * + * @see + * @author Jeremy Whitlock + */ +@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) +public interface MetricClient { + + /** + * Returns a list of valid metrics stored for the AWS account owner. + * + *

+ *

Note

Up to 500 results are returned for any one call. To retrieve further results, + * use returned NextToken ( + * {@link org.jclouds.cloudwatch.domain.ListMetricsResponse#getNextToken()}) value with + * subsequent calls .To retrieve all available metrics with one call, use + * {@link #list(MetricsClient, String, org.jclouds.cloudwatch.options.ListMetricsOptions)}. + * + * @param options + * the options describing the metrics query + * + * @return the response object + */ + ListMetricsResponse listMetrics(ListMetricsOptions options); + + ListMetricsResponse listMetrics(); + + /** + * Gets statistics for the specified metric. + * + * @param statistics + * the statistics to gather + * @param options + * the options describing the metric statistics query + * + * @return the response object + */ + GetMetricStatisticsResponse getMetricStatistics(GetMetricStatistics statistics, GetMetricStatisticsOptions options); + + GetMetricStatisticsResponse getMetricStatistics(GetMetricStatistics statistics); + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/GetMetricStatisticsOptions.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/GetMetricStatisticsOptions.java index 62eb050733..b100f6e240 100644 --- a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/GetMetricStatisticsOptions.java +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/GetMetricStatisticsOptions.java @@ -20,22 +20,64 @@ package org.jclouds.cloudwatch.options; import static com.google.common.base.Preconditions.checkNotNull; +import java.util.Set; + import org.jclouds.aws.util.AWSUtils; +import org.jclouds.cloudwatch.domain.Dimension; import org.jclouds.cloudwatch.domain.Unit; import org.jclouds.http.options.BaseHttpRequestOptions; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimap; +import com.google.common.collect.Sets; + /** * Options used to control metric statistics are returned * * @see - * @author Andrei Savu + * @author Andrei Savu, Jeremy Whitlock */ public class GetMetricStatisticsOptions extends BaseHttpRequestOptions { - public static final GetMetricStatisticsOptions NONE = new GetMetricStatisticsOptions(); - + private Set dimensions = Sets.newLinkedHashSet(); + + /** + * A dimension describing qualities of the metric. (Can be called multiple times up to a maximum of 10 times.) + * + * @param dimension the dimension describing the qualities of the metric + * + * @return this {@code Builder} object + * + * @throws IllegalArgumentException if the number of dimensions would be greater than 10 after adding + */ + public GetMetricStatisticsOptions dimension(Dimension dimension) { + if (dimension != null) { + Preconditions.checkArgument(dimensions.size() < 10, "dimension member maximum count of 10 exceeded."); + this.dimensions.add(dimension); + } + return this; + } + + /** + * A list of dimensions describing qualities of the metric. (Set can be 10 or less items.) + * + * @param dimensions the dimensions describing the qualities of the metric + * + * @return this {@code Builder} object + * + * @throws IllegalArgumentException if this is invoked more than 10 times + */ + public GetMetricStatisticsOptions dimensions(Set dimensions) { + if (dimensions != null) { + Preconditions.checkArgument(dimensions.size() <= 10, "dimensions can have 10 or fewer members."); + this.dimensions = ImmutableSet.copyOf(dimensions); + } + return this; + } + /** * @param instanceId * filter metrics by instance Id @@ -73,5 +115,34 @@ public class GetMetricStatisticsOptions extends BaseHttpRequestOptions { GetMetricStatisticsOptions options = new GetMetricStatisticsOptions(); return options.unit(unit); } + + /** + * @see GetMetricStatisticsOptions#dimension + */ + public static GetMetricStatisticsOptions dimension(Dimension dimension) { + GetMetricStatisticsOptions options = new GetMetricStatisticsOptions(); + return options.dimension(dimension); + } + + /** + * @see GetMetricStatisticsOptions#dimensions + */ + public static GetMetricStatisticsOptions dimensions(Set dimensions) { + GetMetricStatisticsOptions options = new GetMetricStatisticsOptions(); + return options.dimensions(dimensions); + } } + + @Override + public Multimap buildFormParameters() { + Multimap formParameters = super.buildFormParameters(); + int dimensionIndex = 1; + for (Dimension dimension : dimensions) { + formParameters.put("Dimensions.member." + dimensionIndex + ".Name", dimension.getName()); + formParameters.put("Dimensions.member." + dimensionIndex + ".Value", dimension.getValue()); + dimensionIndex++; + } + return formParameters; + } + } diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/ListMetricsOptions.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/ListMetricsOptions.java new file mode 100644 index 0000000000..ee4b024410 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/options/ListMetricsOptions.java @@ -0,0 +1,219 @@ +/** + * 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.cloudwatch.options; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Sets; +import org.jclouds.cloudwatch.domain.Dimension; +import org.jclouds.http.options.BaseHttpRequestOptions; +import org.jclouds.javax.annotation.Nullable; + +import java.util.Set; + +/** + * Options used to list available metrics. + * + * @see + * + * @author Jeremy Whitlock + */ +public class ListMetricsOptions extends BaseHttpRequestOptions { + + private final Set dimensions; + private final String metricName; + private final String namespace; + private final String nextToken; + + /** + * Private constructor to enforce using {@link Builder}. + */ + private ListMetricsOptions(@Nullable String namespace, @Nullable String metricName, + @Nullable Set dimensions, @Nullable String nextToken) { + this.dimensions = dimensions; + this.metricName = metricName; + this.namespace = namespace; + this.nextToken = nextToken; + } + + /** + * return the set of dimensions for this request + */ + @Nullable + public Set getDimensions() { + return dimensions; + } + + /** + * return the metric name for this request + */ + @Nullable + public String getMetricName() { + return metricName; + } + + /** + * return the namespace for this request + */ + @Nullable + public String getNamespace() { + return namespace; + } + + /** + * return the next token for this request + */ + @Nullable + public String getNextToken() { + return nextToken; + } + + /** + * Returns a new builder. The generated builder is equivalent to the builder + * created by the {@link Builder} constructor. + */ + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private Set dimensions = Sets.newLinkedHashSet(); + private String metricName; + private String namespace; + private String nextToken; + + /** + * Creates a new builder. The returned builder is equivalent to the builder + * generated by {@link ListMetricsOptions#builder}. + */ + public Builder() {} + + /** + * The namespace to filter against. (Should be called once. Subsequent calls will overwrite the previous value. + * See {@link org.jclouds.cloudwatch.domain.Namespaces} for the known list of namespaces.) + * + * @param namespace the namespace to filter against + * + * @return this {@code Builder} object + * + * @throws IllegalArgumentException if namespace is empty + */ + public Builder namespace(String namespace) { + if (namespace != null) { + Preconditions.checkArgument(namespace.length() > 1, "namespace must not be empty."); + } + this.namespace = namespace; + return this; + } + + /** + * The name of the metric to filter against. (Should be called once. Subsequent calls will overwrite the + * previous value.) + * + * @param metricName the metric name to filter against + * + * @return this {@code Builder} object + * + * @throws IllegalArgumentException if metricName is empty + */ + public Builder metricName(String metricName) { + if (metricName != null) { + Preconditions.checkArgument(metricName.length() > 1, "metricName must not be empty."); + } + this.metricName = metricName; + return this; + } + + /** + * A list of dimensions to filter against. (Set can be 10 or less items.) + * + * @param dimensions the dimensions to filter against + * + * @return this {@code Builder} object + * + * @throws IllegalArgumentException if the number of dimensions would be greater than 10 after adding + */ + public Builder dimensions(Set dimensions) { + if (dimensions != null) { + Preconditions.checkArgument(dimensions.size() <= 10, "dimensions can have 10 or fewer members."); + this.dimensions = dimensions; + } + return this; + } + + /** + * A dimension to filter the available metrics by. (Can be called multiple times up to a maximum of 10 times.) + * + * @param dimension a dimension to filter the returned metrics by + * + * @return this {@code Builder} object + * + * @throws IllegalArgumentException if this is invoked more than 10 times + */ + public Builder dimension(Dimension dimension) { + if (dimension != null) { + Preconditions.checkArgument(dimensions.size() < 10, "dimension member maximum count of 10 exceeded."); + this.dimensions.add(dimension); + } + return this; + } + + /** + * The token returned by a previous call to indicate that there is more data available. + * + * @param nextToken the next token indicating that there is more data available + * + * @return this {@code Builder} object + */ + public Builder nextToken(String nextToken) { + this.nextToken = nextToken; + return this; + } + + /** + * Returns a newly-created {@code ListMetricsOptions} based on the contents of + * the {@code Builder}. + */ + public ListMetricsOptions build() { + ListMetricsOptions lmo = new ListMetricsOptions(namespace, metricName, dimensions, nextToken); + int dimensionIndex = 1; + + if (namespace != null) { + lmo.formParameters.put("Namespace", namespace); + } + + if (metricName != null) { + lmo.formParameters.put("MetricName", metricName); + } + + for (Dimension dimension : dimensions) { + lmo.formParameters.put("Dimensions.member." + dimensionIndex + ".Name", dimension.getName()); + lmo.formParameters.put("Dimensions.member." + dimensionIndex + ".Value", dimension.getValue()); + dimensionIndex++; + } + + if (nextToken != null) { + lmo.formParameters.put("NextToken", nextToken); + } + + return lmo; + } + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/DimensionHandler.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/DimensionHandler.java new file mode 100644 index 0000000000..523963482b --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/DimensionHandler.java @@ -0,0 +1,72 @@ +/** + * 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.cloudwatch.xml; + +import org.jclouds.cloudwatch.domain.Dimension; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.util.SaxUtils; +import org.xml.sax.SAXException; + +/** + * @see + * + * @author Jeremy Whitlock + */ +public class DimensionHandler extends ParseSax.HandlerForGeneratedRequestWithResult { + + private StringBuilder currentText = new StringBuilder(); + private String name; + private String value; + + /** + * {@inheritDoc} + */ + @Override + public Dimension getResult() { + Dimension dimension = new Dimension(name, value); + + // Reset since this handler is created once but produces N results + name = null; + value = null; + + return dimension; + } + + /** + * {@inheritDoc} + */ + @Override + public void endElement(String uri, String name, String qName) throws SAXException { + if (qName.equals("Name")) { + this.name = SaxUtils.currentOrNull(currentText); + } else if (qName.equals("Value")) { + value = SaxUtils.currentOrNull(currentText); + } + currentText = new StringBuilder(); + } + + /** + * {@inheritDoc} + */ + @Override + public void characters(char ch[], int start, int length) { + currentText.append(ch, start, length); + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/GetMetricStatisticsResponseHandlerV2.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/GetMetricStatisticsResponseHandlerV2.java new file mode 100644 index 0000000000..bf3e71b60d --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/GetMetricStatisticsResponseHandlerV2.java @@ -0,0 +1,90 @@ +/** + * 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.cloudwatch.xml; + +import com.google.common.collect.Sets; +import org.jclouds.cloudwatch.domain.Datapoint; +import org.jclouds.cloudwatch.domain.GetMetricStatisticsResponse; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.util.SaxUtils; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +import javax.inject.Inject; +import java.util.Set; + +/** + * @see + * + * @author Jeremy Whitlock + */ +public class GetMetricStatisticsResponseHandlerV2 extends ParseSax.HandlerWithResult { + + private StringBuilder currentText = new StringBuilder(); + private Set datapoints = Sets.newLinkedHashSet(); + private String label; + private final DatapointHandler datapointHandler; + private boolean inDatapoints; + + @Inject + public GetMetricStatisticsResponseHandlerV2(DatapointHandler DatapointHandler) { + this.datapointHandler = DatapointHandler; + } + + public GetMetricStatisticsResponse getResult() { + return new GetMetricStatisticsResponse(datapoints, label); + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (qName.equals("Datapoints")) { + inDatapoints = true; + } + if (inDatapoints) { + datapointHandler.startElement(uri, localName, qName, attributes); + } + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (inDatapoints) { + if (qName.equals("Datapoints")) { + inDatapoints = false; + } else { + datapointHandler.endElement(uri, localName, qName); + if (qName.equals("member")) { + this.datapoints.add(datapointHandler.getResult()); + } + } + } else if (qName.equals("Label")) { + label = SaxUtils.currentOrNull(currentText); + } + + currentText = new StringBuilder(); + } + + public void characters(char ch[], int start, int length) { + if (inDatapoints) { + datapointHandler.characters(ch, start, length); + } else { + currentText.append(ch, start, length); + } + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/ListMetricsResponseHandler.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/ListMetricsResponseHandler.java new file mode 100644 index 0000000000..7c55490efc --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/ListMetricsResponseHandler.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.cloudwatch.xml; + +import com.google.common.collect.Sets; +import com.google.inject.Inject; +import org.jclouds.cloudwatch.domain.ListMetricsResponse; +import org.jclouds.cloudwatch.domain.Metric; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.util.SaxUtils; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +import java.util.Set; + +/** + * @see + * + * @author Jeremy Whitlock + */ +public class ListMetricsResponseHandler extends ParseSax.HandlerForGeneratedRequestWithResult { + + private final MetricHandler metricHandler; + + private StringBuilder currentText = new StringBuilder(); + private Set metrics = Sets.newLinkedHashSet(); + private boolean inMetrics; + private String nextToken; + + @Inject + public ListMetricsResponseHandler(MetricHandler metricHandler) { + this.metricHandler = metricHandler; + } + + /** + * {@inheritDoc} + */ + @Override + public ListMetricsResponse getResult() { + return new ListMetricsResponse(metrics, nextToken); + } + + /** + * {@inheritDoc} + */ + @Override + public void startElement(String url, String name, String qName, Attributes attributes) throws SAXException { + if (SaxUtils.equalsOrSuffix(qName, "Metrics")) { + inMetrics = true; + } + if (inMetrics) { + metricHandler.startElement(url, name, qName, attributes); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void endElement(String uri, String name, String qName) throws SAXException { + if (inMetrics) { + if (qName.equals("Metrics")) { + inMetrics = false; + } else if (qName.equals("member") && !metricHandler.inDimensions()) { + metrics.add(metricHandler.getResult()); + } else { + metricHandler.endElement(uri, name, qName); + } + } else if (qName.equals("NextToken")) { + nextToken = SaxUtils.currentOrNull(currentText); + } + + currentText = new StringBuilder(); + } + + /** + * {@inheritDoc} + */ + @Override + public void characters(char ch[], int start, int length) { + if (inMetrics) { + metricHandler.characters(ch, start, length); + } else { + currentText.append(ch, start, length); + } + } + +} diff --git a/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/MetricHandler.java b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/MetricHandler.java new file mode 100644 index 0000000000..d8d300add7 --- /dev/null +++ b/apis/cloudwatch/src/main/java/org/jclouds/cloudwatch/xml/MetricHandler.java @@ -0,0 +1,118 @@ +/** + * 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.cloudwatch.xml; + +import com.google.common.collect.Sets; +import com.google.inject.Inject; +import org.jclouds.cloudwatch.domain.Dimension; +import org.jclouds.cloudwatch.domain.Metric; +import org.jclouds.http.functions.ParseSax; +import org.jclouds.util.SaxUtils; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +import java.util.Set; + +/** + * @see + * + * @author Jeremy Whitlock + */ +public class MetricHandler extends ParseSax.HandlerForGeneratedRequestWithResult { + + private final DimensionHandler dimensionHandler; + + private StringBuilder currentText = new StringBuilder(); + private Set dimensions = Sets.newLinkedHashSet(); + private boolean inDimensions; + private String metricName; + private String namespace; + + @Inject + public MetricHandler(DimensionHandler dimensionHandler) { + this.dimensionHandler = dimensionHandler; + } + + public boolean inDimensions() { + return inDimensions; + } + + /** + * {@inheritDoc} + */ + @Override + public Metric getResult() { + Metric metric = new Metric(metricName, namespace, dimensions); + + // Reset since this handler is created once but produces N results + dimensions = Sets.newLinkedHashSet(); + metricName = null; + namespace = null; + + return metric; + } + + /** + * {@inheritDoc} + */ + @Override + public void startElement(String url, String name, String qName, Attributes attributes) throws SAXException { + if (!inDimensions && SaxUtils.equalsOrSuffix(qName, "member")) { + inDimensions = true; + } + if (inDimensions) { + dimensionHandler.startElement(url, name, qName, attributes); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void endElement(String uri, String name, String qName) throws SAXException { + if (inDimensions) { + if (qName.equals("Dimensions")) { + inDimensions = false; + } else if (qName.equals("member")) { + dimensions.add(dimensionHandler.getResult()); + } else { + dimensionHandler.endElement(uri, name, qName); + } + } else if (qName.equals("MetricName")) { + metricName = SaxUtils.currentOrNull(currentText); + } else if (qName.equals("Namespace")) { + namespace = SaxUtils.currentOrNull(currentText); + } + + currentText = new StringBuilder(); + } + + /** + * {@inheritDoc} + */ + @Override + public void characters(char ch[], int start, int length) { + if (inDimensions) { + dimensionHandler.characters(ch, start, length); + } else { + currentText.append(ch, start, length); + } + } + +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchAsyncClientTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchAsyncClientTest.java index 690c7092fc..d313ccd9b7 100644 --- a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchAsyncClientTest.java +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchAsyncClientTest.java @@ -61,6 +61,7 @@ import com.google.inject.TypeLiteral; // NOTE:without testName, this will not call @Before* and fail w/NPE during // surefire @Test(groups = "unit", testName = "CloudWatchAsyncClientTest") +@Deprecated public class CloudWatchAsyncClientTest extends BaseAsyncClientTest { public void testRegisterInstancesWithMeasure() throws SecurityException, NoSuchMethodException, IOException { @@ -90,7 +91,7 @@ public class CloudWatchAsyncClientTest extends BaseAsyncClientTest> { public CloudWatchClientLiveTest() { provider = "cloudwatch"; @@ -55,10 +56,6 @@ public class CloudWatchClientLiveTest extends BaseContextLiveTest getEC2MetricStatisticsInRegion(String region) { Calendar cal = Calendar.getInstance(); @@ -74,4 +71,5 @@ public class CloudWatchClientLiveTest extends BaseContextLiveTest> contextType() { return CloudWatchApiMetadata.CONTEXT_TOKEN; } + } diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchLiveTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchLiveTest.java new file mode 100644 index 0000000000..f8115fc45d --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchLiveTest.java @@ -0,0 +1,61 @@ +/** + * 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.cloudwatch; + +import com.google.common.reflect.TypeToken; +import org.jclouds.apis.BaseContextLiveTest; +import org.jclouds.cloudwatch.options.ListMetricsOptions; +import org.jclouds.rest.RestContext; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import static com.google.common.base.Preconditions.checkArgument; + +/** + * Tests behavior of {@code CloudWatch}. + * + * @author Jeremy Whitlock + */ +public class CloudWatchLiveTest extends BaseContextLiveTest> { + + public CloudWatchLiveTest() { + provider = "cloudwatch"; + } + + private CloudWatchClient client; + + @Override + @BeforeClass(groups = { "integration", "live" }) + public void setupContext() { + super.setupContext(); + client = context.getApi(); + } + + @Override + protected TypeToken> contextType() { + return CloudWatchApiMetadata.CONTEXT_TOKEN; + } + + @Test + protected void testCloudWatchListMetrics() { + // Just make sure there is at least one metric returned (Much better if the account you use has more than 500) + checkArgument(CloudWatch.listMetrics(client, null, ListMetricsOptions.builder().build()).iterator().hasNext()); + } + +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchTest.java new file mode 100644 index 0000000000..ac34d5e09f --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/CloudWatchTest.java @@ -0,0 +1,100 @@ +/** + * 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.cloudwatch; + +import static org.easymock.EasyMock.anyObject; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; + +import org.easymock.EasyMock; +import org.jclouds.cloudwatch.domain.ListMetricsResponse; +import org.jclouds.cloudwatch.domain.Metric; +import org.jclouds.cloudwatch.features.MetricClient; +import org.jclouds.cloudwatch.options.ListMetricsOptions; +import org.testng.Assert; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; + +/** + * Tests behavior of {@code CloudWatch}. + * + * @author Jeremy Whitlock + */ +public class CloudWatchTest { + + /** + * Tests {@link CloudWatch#listMetrics(CloudWatchClient, String, org.jclouds.cloudwatch.options.ListMetricsOptions)} + * where a single response returns all results. + * + * @throws Exception if anything goes wrong + */ + @Test + public void testSinglePageResult() throws Exception { + CloudWatchClient client = createMock(CloudWatchClient.class); + MetricClient metricClient = createMock(MetricClient.class); + ListMetricsOptions options = ListMetricsOptions.builder().build(); + ListMetricsResponse response = new ListMetricsResponse(ImmutableSet.of(createMock(Metric.class)), null); + + expect(client.getMetricClientForRegion(null)) + .andReturn(metricClient) + .atLeastOnce(); + + expect(metricClient.listMetrics(options)) + .andReturn(response) + .once(); + + EasyMock.replay(client, metricClient); + + Assert.assertEquals(1, Iterables.size(CloudWatch.listMetrics(client, null, options))); + } + + /** + * Tests {@link CloudWatch#listMetrics(CloudWatchClient, String, org.jclouds.cloudwatch.options.ListMetricsOptions)} + * where retrieving all results requires multiple requests. + * + * @throws Exception if anything goes wrong + */ + @Test + public void testMultiPageResult() throws Exception { + CloudWatchClient client = createMock(CloudWatchClient.class); + MetricClient metricClient = createMock(MetricClient.class); + ListMetricsOptions options = ListMetricsOptions.builder().build(); + ListMetricsResponse response1 = new ListMetricsResponse(ImmutableSet.of(createMock(Metric.class)), "NEXTTOKEN"); + ListMetricsResponse response2 = new ListMetricsResponse(ImmutableSet.of(createMock(Metric.class)), null); + + // Using EasyMock.eq("") because EasyMock makes it impossible to pass null as a String value here + expect(client.getMetricClientForRegion(EasyMock.eq(""))) + .andReturn(metricClient) + .atLeastOnce(); + + expect(metricClient.listMetrics(anyObject(ListMetricsOptions.class))) + .andReturn(response1) + .once(); + expect(metricClient.listMetrics(anyObject(ListMetricsOptions.class))) + .andReturn(response2) + .once(); + + EasyMock.replay(client, metricClient); + + Assert.assertEquals(2, Iterables.size(CloudWatch.listMetrics(client, "", options))); + } + +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricClientExpectTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricClientExpectTest.java new file mode 100644 index 0000000000..0701846d48 --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricClientExpectTest.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 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 + * + * Unles 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 expres or implied. See the License for the + * specific language governing permisions and limitations + * under the License. + */ +package org.jclouds.cloudwatch.features; + +import static org.testng.Assert.assertEquals; + +import java.net.URI; +import java.util.Date; + +import org.jclouds.cloudwatch.CloudWatchClient; +import org.jclouds.cloudwatch.domain.Dimension; +import org.jclouds.cloudwatch.domain.EC2Constants; +import org.jclouds.cloudwatch.domain.GetMetricStatistics; +import org.jclouds.cloudwatch.domain.Namespaces; +import org.jclouds.cloudwatch.domain.Statistics; +import org.jclouds.cloudwatch.domain.Unit; +import org.jclouds.cloudwatch.internal.BaseCloudWatchClientExpectTest; +import org.jclouds.cloudwatch.options.GetMetricStatisticsOptions; +import org.jclouds.cloudwatch.options.ListMetricsOptions; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.rest.ResourceNotFoundException; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMultimap; + +/** + * @author Jeremy Whitlock, Adrian Cole + */ +@Test(groups = "unit", testName = "MetricClientExpectTest") +public class MetricClientExpectTest extends BaseCloudWatchClientExpectTest { + HttpRequest listMetrics = HttpRequest.builder() + .method("POST") + .endpoint(URI.create("https://monitoring.us-east-1.amazonaws.com/")) + .headers(ImmutableMultimap. builder() + .put("Host", "monitoring.us-east-1.amazonaws.com") + .build()) + .payload( + payloadFromStringWithContentType( + new StringBuilder() + .append("Action=ListMetrics").append('&') + .append("Signature=KSh9oQydCR0HMAV6QPYwDzqwQIpxs8I%2Fig7brYgHVZU%3D").append('&') + .append("SignatureMethod=HmacSHA256").append('&') + .append("SignatureVersion=2").append('&') + .append("Timestamp=2009-11-08T15%3A54%3A08.897Z").append('&') + .append("Version=2010-08-01").append('&') + .append("AWSAccessKeyId=identity").toString(), "application/x-www-form-urlencoded")) + .build(); + + public void testListMetricsWhenResponseIs2xx() throws Exception { + + HttpResponse listMetricsResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/list_metrics.xml", "text/xml")).build(); + + CloudWatchClient clientWhenMetricsExist = requestSendsResponse( + listMetrics, listMetricsResponse); + + assertEquals(clientWhenMetricsExist.getMetricClientForRegion(null).listMetrics().toString(), + "ListMetricsResponse{metrics=[Metric{namespace=AWS/EC2, metricName=CPUUtilization, dimension=[Dimension{name=InstanceId, value=i-689fcf0f}]}], nextToken=null}"); + } + + // TODO: this should really be an empty set + @Test(expectedExceptions = ResourceNotFoundException.class) + public void testListMetricsWhenResponseIs404() throws Exception { + + HttpResponse listMetricsResponse = HttpResponse.builder().statusCode(404).build(); + + CloudWatchClient clientWhenMetricsDontExist = requestSendsResponse( + listMetrics, listMetricsResponse); + + clientWhenMetricsDontExist.getMetricClientForRegion(null).listMetrics(); + } + + public void testListMetricsWithOptionsWhenResponseIs2xx() throws Exception { + HttpRequest listMetricsWithOptions = HttpRequest.builder() + .method("POST") + .endpoint(URI.create("https://monitoring.us-east-1.amazonaws.com/")) + .headers(ImmutableMultimap. builder() + .put("Host", "monitoring.us-east-1.amazonaws.com") + .build()) + .payload( + payloadFromStringWithContentType( + new StringBuilder() + .append("Action=ListMetrics").append('&') + .append("Dimensions.member.1.Name=InstanceId").append('&') + .append("Dimensions.member.1.Value=SOMEINSTANCEID").append('&') + .append("MetricName=CPUUtilization").append('&') + .append("Namespace=SOMENEXTTOKEN").append('&') + .append("NextToken=AWS%2FEC2").append('&') + .append("Signature=G05HKEx9FJpGZBk02OVYwt3u4g%2FilAY9nU5hJI9LDXA%3D").append('&') + .append("SignatureMethod=HmacSHA256").append('&') + .append("SignatureVersion=2").append('&') + .append("Timestamp=2009-11-08T15%3A54%3A08.897Z").append('&') + .append("Version=2010-08-01").append('&') + .append("AWSAccessKeyId=identity").toString(), "application/x-www-form-urlencoded")) + .build(); + + HttpResponse listMetricsWithOptionsResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/list_metrics.xml", "text/xml")).build(); + + CloudWatchClient clientWhenMetricsWithOptionsExist = requestSendsResponse(listMetricsWithOptions, + listMetricsWithOptionsResponse); + + assertEquals( + clientWhenMetricsWithOptionsExist.getMetricClientForRegion(null).listMetrics( + ListMetricsOptions.builder() + .dimension(new Dimension(EC2Constants.Dimension.INSTANCE_ID, "SOMEINSTANCEID")) + .metricName(EC2Constants.MetricName.CPU_UTILIZATION) + .namespace("SOMENEXTTOKEN") + .nextToken( Namespaces.EC2) + .build()).toString(), + "ListMetricsResponse{metrics=[Metric{namespace=AWS/EC2, metricName=CPUUtilization, dimension=[Dimension{name=InstanceId, value=i-689fcf0f}]}], nextToken=null}"); + } + + GetMetricStatistics stats = GetMetricStatistics.builder() + .endTime(new Date(10000000l)) + .metricName(EC2Constants.MetricName.CPU_UTILIZATION) + .namespace(Namespaces.EC2) + .period(60) + .startTime(new Date(10000000l)) + .statistic(Statistics.MAXIMUM) + .statistic(Statistics.MINIMUM) + .unit(Unit.PERCENT).build(); + + HttpRequest getMetricStatistics = HttpRequest.builder() + .method("POST") + .endpoint(URI.create("https://monitoring.us-east-1.amazonaws.com/")) + .headers(ImmutableMultimap. builder() + .put("Host", "monitoring.us-east-1.amazonaws.com") + .build()) + .payload( + payloadFromStringWithContentType( + new StringBuilder() + .append("Action=GetMetricStatistics").append('&') + .append("EndTime=1970-01-01T02%3A46%3A40Z").append('&') + .append("MetricName=CPUUtilization").append('&') + .append("Namespace=AWS%2FEC2").append('&') + .append("Period=60").append('&') + .append("Signature=rmg8%2Ba7w4ycy%2FKfO8rnuj6rDL0jNE96m8GKfjh3SWcw%3D").append('&') + .append("SignatureMethod=HmacSHA256").append('&') + .append("SignatureVersion=2").append('&') + .append("StartTime=1970-01-01T02%3A46%3A40Z").append('&') + .append("Statistics.member.1=Maximum").append('&') + .append("Statistics.member.2=Minimum").append('&') + .append("Timestamp=2009-11-08T15%3A54%3A08.897Z").append('&') + .append("Unit=Percent").append('&').append("Version=2010-08-01").append('&') + .append("AWSAccessKeyId=identity").toString(), "application/x-www-form-urlencoded")) + .build(); + + public void testGetMetricStatisticsWhenResponseIs2xx() throws Exception { + + HttpResponse getMetricStatisticsResponse = HttpResponse.builder().statusCode(200).payload( + payloadFromResourceWithContentType("/get_metric_statistics.xml", "text/xml")).build(); + + CloudWatchClient clientWhenMetricsExist = requestSendsResponse(getMetricStatistics, getMetricStatisticsResponse); + + assertEquals( + clientWhenMetricsExist.getMetricClientForRegion(null).getMetricStatistics(stats).toString(), + // TODO: make an object for this + "GetMetricStatisticsResponse{label=CPUUtilization, datapoints=[Datapoint{timestamp=Thu Jan 15 16:00:00 PST 2009, customUnit=null, maximum=null, minimum=null, average=0.17777777777777778, sum=null, samples=9.0, unit=Percent}, Datapoint{timestamp=Thu Jan 15 16:01:00 PST 2009, customUnit=null, maximum=null, minimum=null, average=0.1, sum=null, samples=8.0, unit=Percent}]}"); + } + + // TODO: this should really be an empty set + @Test(expectedExceptions = ResourceNotFoundException.class) + public void testGetMetricStatisticsWhenResponseIs404() throws Exception { + + HttpResponse getMetricStatisticsResponse = HttpResponse.builder().statusCode(404).build(); + + CloudWatchClient clientWhenMetricsDontExist = requestSendsResponse(getMetricStatistics, getMetricStatisticsResponse); + + clientWhenMetricsDontExist.getMetricClientForRegion(null).getMetricStatistics(stats); + } + + public void testGetMetricStatisticsWithOptionsWhenResponseIs2xx() throws Exception { + HttpRequest getMetricStatistics = HttpRequest.builder() + .method("POST") + .endpoint(URI.create("https://monitoring.us-east-1.amazonaws.com/")) + .headers(ImmutableMultimap. builder() + .put("Host", "monitoring.us-east-1.amazonaws.com") + .build()) + .payload( + payloadFromStringWithContentType( + new StringBuilder() + .append("Action=GetMetricStatistics").append('&') + .append("Dimensions.member.1.Name=InstanceId").append('&') + .append("Dimensions.member.1.Value=SOMEINSTANCEID").append('&') + .append("Dimensions.member.2.Name=InstanceType").append('&') + .append("Dimensions.member.2.Value=t1.micro").append('&') + .append("EndTime=1970-01-01T02%3A46%3A40Z").append('&') + .append("MetricName=CPUUtilization").append('&') + .append("Namespace=AWS%2FEC2").append('&') + .append("Period=60").append('&') + .append("Signature=e0WyI%2FNm4hN2%2BMEm1mjRUzsvgvMCdFXbVJWi4ORpwic%3D").append('&') + .append("SignatureMethod=HmacSHA256").append('&') + .append("SignatureVersion=2").append('&') + .append("StartTime=1970-01-01T02%3A46%3A40Z").append('&') + .append("Statistics.member.1=Maximum").append('&') + .append("Statistics.member.2=Minimum").append('&') + .append("Timestamp=2009-11-08T15%3A54%3A08.897Z").append('&') + .append("Unit=Percent").append('&') + .append("Version=2010-08-01").append('&') + .append("AWSAccessKeyId=identity").toString(), "application/x-www-form-urlencoded")) + .build(); + + HttpResponse getMetricStatisticsResponse = HttpResponse.builder().statusCode(200).payload( + payloadFromResourceWithContentType("/get_metric_statistics.xml", "text/xml")).build(); + + CloudWatchClient clientWhenMetricsExist = requestSendsResponse(getMetricStatistics, getMetricStatisticsResponse); + + Dimension dimension1 = new Dimension(EC2Constants.Dimension.INSTANCE_ID, "SOMEINSTANCEID"); + Dimension dimension2 = new Dimension(EC2Constants.Dimension.INSTANCE_TYPE, "t1.micro"); + + assertEquals( + clientWhenMetricsExist.getMetricClientForRegion(null).getMetricStatistics(stats, + GetMetricStatisticsOptions.Builder.dimension(dimension1).dimension(dimension2)).toString(), + // TODO: make an object for this + "GetMetricStatisticsResponse{label=CPUUtilization, datapoints=[Datapoint{timestamp=Thu Jan 15 16:00:00 PST 2009, customUnit=null, maximum=null, minimum=null, average=0.17777777777777778, sum=null, samples=9.0, unit=Percent}, Datapoint{timestamp=Thu Jan 15 16:01:00 PST 2009, customUnit=null, maximum=null, minimum=null, average=0.1, sum=null, samples=8.0, unit=Percent}]}"); + } + +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricClientLiveTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricClientLiveTest.java new file mode 100644 index 0000000000..ad463ae819 --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/features/MetricClientLiveTest.java @@ -0,0 +1,214 @@ +/** + * 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.cloudwatch.features; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Calendar; +import java.util.Date; +import java.util.Set; + +import org.jclouds.cloudwatch.domain.Datapoint; +import org.jclouds.cloudwatch.domain.Dimension; +import org.jclouds.cloudwatch.domain.EC2Constants; +import org.jclouds.cloudwatch.domain.GetMetricStatistics; +import org.jclouds.cloudwatch.domain.GetMetricStatisticsResponse; +import org.jclouds.cloudwatch.domain.ListMetricsResponse; +import org.jclouds.cloudwatch.domain.Metric; +import org.jclouds.cloudwatch.domain.Namespaces; +import org.jclouds.cloudwatch.domain.Statistics; +import org.jclouds.cloudwatch.domain.Unit; +import org.jclouds.cloudwatch.internal.BaseCloudWatchClientLiveTest; +import org.jclouds.cloudwatch.options.ListMetricsOptions; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; + +/** + * @author Jeremy Whitlock, Adrian Cole + */ +@Test(groups = "live", testName = "MetricClientLiveTest") +public class MetricClientLiveTest extends BaseCloudWatchClientLiveTest { + + // TODO: change this test to retrieve pre-seeded custom metrics + @Test + protected void testGetMetricStatistics() { + ListMetricsResponse metricsResponse = client().listMetrics(); + + // Walk through all datapoints in all metrics until we find a metric datapoint that returns statistics + if (metricsResponse.size() > 0) { + for (Metric metric : metricsResponse) { + Set dimensions = metric.getDimensions(); + boolean testRan = false; + + for (Dimension dimension : dimensions) { + Date endTime = new Date(); + Calendar cal = Calendar.getInstance(); + + cal.add(Calendar.MINUTE, -60 * 24); // 24 hours + + GetMetricStatistics options = + GetMetricStatistics.builder() + .dimension(dimension) + .endTime(endTime) + .metricName(metric.getMetricName()) + .namespace(metric.getNamespace()) + .period(300) + .startTime(cal.getTime()) + .statistics(ImmutableSet.of(Statistics.MAXIMUM, + Statistics.MINIMUM)) + .unit(Unit.PERCENT).build(); + GetMetricStatisticsResponse response = client().getMetricStatistics(options); + + if (response.size() > 0) { + checkNotNull(response.getLabel()); + + for (Datapoint datapoint : response) { + checkArgument(datapoint.getAverage() == null); + checkNotNull(datapoint.getMaximum()); + checkNotNull(datapoint.getMinimum()); + } + + testRan = true; + break; + } + } + + if (testRan) { + break; + } + } + } + } + + @Test + protected void testListMetrics() { + ListMetricsResponse response; + String testNamespace = Namespaces.EC2; + String testMetricName = EC2Constants.MetricName.CPU_UTILIZATION; + String testDimensionName = EC2Constants.Dimension.INSTANCE_TYPE; + String testDimensionValue = "t1.micro"; + + // Test an empty request (pulls all stored metric options across all products) + response = client().listMetrics(); + + performDefaultMetricsTests(response); + + if (response.size() > 0) { + Metric metric = response.iterator().next(); + + testMetricName = metric.getMetricName(); + testNamespace = metric.getNamespace(); + + if (metric.getDimensions().size() > 0) { + Dimension dimension = metric.getDimensions().iterator().next(); + + testDimensionName = dimension.getName(); + testDimensionValue = dimension.getValue(); + } + + if (testDimensionName == null) { + for (Metric metric1 : response) { + Set dimensions = metric1.getDimensions(); + + if (dimensions.size() > 0) { + Dimension dimension = metric.getDimensions().iterator().next(); + + testDimensionName = dimension.getName(); + testDimensionValue = dimension.getValue(); + + break; + } + } + } + } + + // Test with a NextToken, even if it's null + response = client().listMetrics(ListMetricsOptions.builder().nextToken(response.getNextToken()).build()); + + performDefaultMetricsTests(response); + + // Test with a Namespace + response = client().listMetrics(ListMetricsOptions.builder().namespace(testNamespace).build()); + + performDefaultMetricsTests(response); + + for (Metric metric : response) { + checkArgument(metric.getNamespace().equals(testNamespace), + "All metrics should have the " + testNamespace + " Namespace."); + } + + // Test with a MetricName + response = client().listMetrics(ListMetricsOptions.builder().metricName(testMetricName).build()); + + performDefaultMetricsTests(response); + + for (Metric metric : response) { + checkArgument(metric.getMetricName().equals(testMetricName), + "All metrics should have the " + testMetricName + " MetricName."); + } + + // Test with a Dimension + if (testDimensionName != null) { + Dimension testDimension = new Dimension(testDimensionName, testDimensionValue); + + response = client().listMetrics(ListMetricsOptions.builder().dimension(testDimension).build()); + + performDefaultMetricsTests(response); + + for (Metric metric : response) { + Set dimensions = metric.getDimensions(); + + checkArgument(dimensions.size() == 1, "There should only be one Dimension."); + + Dimension dimension = dimensions.iterator().next(); + + checkArgument(dimension.equals(testDimension), + "The retrieved Dimension and test Dimension should be equal."); + } + } + } + + private void performDefaultMetricsTests(ListMetricsResponse response) { + // If there are less than 500 metrics, NextToken should be null + if (response.size() < 500) { + checkArgument(response.getNextToken() == null, + "NextToken should be null for response with fewer than 500 metrics."); + } + + for (Metric metric : response) { + Set dimensions = metric.getDimensions(); + + checkArgument(dimensions.size() <= 10, "Dimensions set cannot be greater than 10 items."); + + for (Dimension dimension : dimensions) { + checkNotNull(dimension.getName(), "Name cannot be null for a Dimension."); + checkNotNull(dimension.getValue(), "Value cannot be null for a Dimension."); + } + + checkNotNull(metric.getMetricName(), "MetricName cannot be null for a Metric."); + checkNotNull(metric.getNamespace(), "Namespace cannot be null for a Metric."); + } + } + + protected MetricClient client() { + return context.getApi().getMetricClientForRegion(null); + } +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchAsyncClientExpectTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchAsyncClientExpectTest.java new file mode 100644 index 0000000000..89445fbdb3 --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchAsyncClientExpectTest.java @@ -0,0 +1,38 @@ +/** + * 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.cloudwatch.internal; + +import java.util.Properties; + +import org.jclouds.cloudwatch.CloudWatchAsyncClient; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; + +import com.google.common.base.Function; +import com.google.inject.Module; + +/** + * + * @author Adrian Cole + */ +public class BaseCloudWatchAsyncClientExpectTest extends BaseCloudWatchExpectTest { + public CloudWatchAsyncClient createClient(Function fn, Module module, Properties props) { + return createInjector(fn, module, props).getInstance(CloudWatchAsyncClient.class); + } +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchClientExpectTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchClientExpectTest.java new file mode 100644 index 0000000000..61c7c1ac92 --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchClientExpectTest.java @@ -0,0 +1,29 @@ +/** + * 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.cloudwatch.internal; + +import org.jclouds.cloudwatch.CloudWatchClient; + +/** + * + * @author Adrian Cole + */ +public class BaseCloudWatchClientExpectTest extends BaseCloudWatchExpectTest { + +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchClientLiveTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchClientLiveTest.java new file mode 100644 index 0000000000..c6af13ca05 --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchClientLiveTest.java @@ -0,0 +1,46 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.cloudwatch.internal; + +import org.jclouds.apis.BaseContextLiveTest; +import org.jclouds.cloudwatch.CloudWatchApiMetadata; +import org.jclouds.cloudwatch.CloudWatchAsyncClient; +import org.jclouds.cloudwatch.CloudWatchClient; +import org.jclouds.rest.RestContext; +import org.testng.annotations.Test; + +import com.google.common.reflect.TypeToken; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "live") +public class BaseCloudWatchClientLiveTest extends BaseContextLiveTest> { + + public BaseCloudWatchClientLiveTest() { + provider = "cloudwatch"; + } + + @Override + protected TypeToken> contextType() { + return CloudWatchApiMetadata.CONTEXT_TOKEN; + } + +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchExpectTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchExpectTest.java new file mode 100644 index 0000000000..d4576ac55a --- /dev/null +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/internal/BaseCloudWatchExpectTest.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.cloudwatch.internal; + +import static com.google.common.collect.Maps.transformValues; + +import java.net.URI; +import java.util.Map; + +import javax.inject.Named; + +import org.jclouds.Constants; +import org.jclouds.aws.domain.Region; +import org.jclouds.cloudwatch.config.CloudWatchRestClientModule; +import org.jclouds.date.DateService; +import org.jclouds.location.config.LocationModule; +import org.jclouds.location.suppliers.RegionIdToURISupplier; +import org.jclouds.rest.ConfiguresRestClient; +import org.jclouds.rest.internal.BaseRestClientExpectTest; +import org.jclouds.util.Suppliers2; + +import com.google.common.base.Supplier; +import com.google.common.collect.ImmutableMap; +import com.google.inject.Module; + +/** + * + * @author Adrian Cole + */ +public class BaseCloudWatchExpectTest extends BaseRestClientExpectTest { + + public BaseCloudWatchExpectTest() { + provider = "cloudwatch"; + } + + @ConfiguresRestClient + private static final class TestMonitoringRestClientModule extends CloudWatchRestClientModule { + + @Override + protected void installLocations() { + install(new LocationModule()); + bind(RegionIdToURISupplier.class).toInstance(new RegionIdToURISupplier() { + + @Override + public Map> get() { + return transformValues(ImmutableMap. of(Region.EU_WEST_1, URI + .create("https://ec2.eu-west-1.amazonaws.com"), Region.US_EAST_1, URI + .create("https://ec2.us-east-1.amazonaws.com"), Region.US_WEST_1, URI + .create("https://ec2.us-west-1.amazonaws.com")), Suppliers2. ofInstanceFunction()); + } + + }); + } + + @Override + protected String provideTimeStamp(final DateService dateService, + @Named(Constants.PROPERTY_SESSION_INTERVAL) int expiration) { + return "2009-11-08T15:54:08.897Z"; + } + } + + @Override + protected Module createModule() { + return new TestMonitoringRestClientModule(); + } +} diff --git a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/xml/GetMetricStatisticsResponseHandlerTest.java b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/xml/GetMetricStatisticsResponseHandlerTest.java index 289b2d1618..c3951173e5 100644 --- a/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/xml/GetMetricStatisticsResponseHandlerTest.java +++ b/apis/cloudwatch/src/test/java/org/jclouds/cloudwatch/xml/GetMetricStatisticsResponseHandlerTest.java @@ -26,6 +26,7 @@ import java.util.Set; import org.jclouds.cloudwatch.domain.Datapoint; import org.jclouds.cloudwatch.domain.Unit; import org.jclouds.date.DateService; +import org.jclouds.date.internal.SimpleDateFormatDateService; import org.jclouds.http.functions.BaseHandlerTest; import org.testng.annotations.Test; @@ -40,13 +41,9 @@ import com.google.common.collect.ImmutableSet; @Test(groups = "unit", testName = "GetMetricStatisticsResponseHandlerTest") public class GetMetricStatisticsResponseHandlerTest extends BaseHandlerTest { public void testApplyInputStream() { - DateService dateService = injector.getInstance(DateService.class); InputStream is = getClass().getResourceAsStream("/get_metric_statistics.xml"); - Set expected = ImmutableSet.of(new Datapoint(0.17777777777777778, null, null, dateService - .iso8601SecondsDateParse("2009-01-16T00:00:00Z"), 9.0, null, Unit.PERCENT, null), new Datapoint( - 0.1, null, null, dateService.iso8601SecondsDateParse("2009-01-16T00:01:00Z"), 8.0, null, - Unit.PERCENT, null)); + Set expected = expected(); GetMetricStatisticsResponseHandler handler = injector.getInstance(GetMetricStatisticsResponseHandler.class); Set result = factory.create(handler).parse(is); @@ -54,4 +51,14 @@ public class GetMetricStatisticsResponseHandlerTest extends BaseHandlerTest { assertEquals(result, expected); } + DateService dateService = new SimpleDateFormatDateService(); + + public Set expected() { + + Set expected = ImmutableSet.of(new Datapoint(0.17777777777777778, null, null, dateService + .iso8601SecondsDateParse("2009-01-16T00:00:00Z"), 9.0, null, Unit.PERCENT, null), new Datapoint(0.1, + null, null, dateService.iso8601SecondsDateParse("2009-01-16T00:01:00Z"), 8.0, null, Unit.PERCENT, null)); + return expected; + } + } diff --git a/apis/cloudwatch/src/test/resources/list_metrics.xml b/apis/cloudwatch/src/test/resources/list_metrics.xml new file mode 100644 index 0000000000..92385f44c6 --- /dev/null +++ b/apis/cloudwatch/src/test/resources/list_metrics.xml @@ -0,0 +1,16 @@ + + + + + + + InstanceId + i-689fcf0f + + + CPUUtilization + AWS/EC2 + + + + \ No newline at end of file diff --git a/apis/deltacloud/src/test/java/org/jclouds/deltacloud/DeltacloudClientLiveTest.java b/apis/deltacloud/src/test/java/org/jclouds/deltacloud/DeltacloudClientLiveTest.java index 82a4f46532..ba34d5e4d4 100644 --- a/apis/deltacloud/src/test/java/org/jclouds/deltacloud/DeltacloudClientLiveTest.java +++ b/apis/deltacloud/src/test/java/org/jclouds/deltacloud/DeltacloudClientLiveTest.java @@ -32,7 +32,6 @@ import org.jclouds.deltacloud.domain.TransitionOnAction; import org.jclouds.deltacloud.options.CreateInstanceOptions; import org.jclouds.domain.LoginCredentials; import org.jclouds.http.HttpRequest; -import org.jclouds.net.IPSocket; import org.jclouds.ssh.SshClient; import org.jclouds.sshj.config.SshjSshClientModule; import org.testng.annotations.AfterClass; @@ -40,6 +39,7 @@ import org.testng.annotations.Test; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; +import com.google.common.net.HostAndPort; import com.google.gson.Gson; import com.google.inject.Guice; @@ -95,7 +95,7 @@ public class DeltacloudClientLiveTest extends ReadOnlyDeltacloudClientLiveTest { @Test(dependsOnMethods = "testCreateInstance") public void testConnectivity() throws Exception { Logger.getAnonymousLogger().info("awaiting ssh"); - assert socketTester.apply(new IPSocket(Iterables.get(instance.getPublicAddresses(), 0), 22)) : instance; + assert socketTester.apply(HostAndPort.fromParts(Iterables.get(instance.getPublicAddresses(), 0), 22)) : instance; if (creds != null) { Logger.getAnonymousLogger().info("will connect ssh"); doConnectViaSsh(instance, creds); @@ -136,7 +136,7 @@ public class DeltacloudClientLiveTest extends ReadOnlyDeltacloudClientLiveTest { protected void doConnectViaSsh(Instance instance, LoginCredentials creds) throws IOException { SshClient ssh = Guice.createInjector(new SshjSshClientModule()).getInstance(SshClient.Factory.class).create( - new IPSocket(Iterables.get(instance.getPublicAddresses(), 0), 22), creds); + HostAndPort.fromParts(Iterables.get(instance.getPublicAddresses(), 0), 22), creds); try { ssh.connect(); ExecResponse hello = ssh.exec("echo hello"); diff --git a/apis/deltacloud/src/test/java/org/jclouds/deltacloud/ReadOnlyDeltacloudClientLiveTest.java b/apis/deltacloud/src/test/java/org/jclouds/deltacloud/ReadOnlyDeltacloudClientLiveTest.java index c87a0e852e..39a9d8288e 100644 --- a/apis/deltacloud/src/test/java/org/jclouds/deltacloud/ReadOnlyDeltacloudClientLiveTest.java +++ b/apis/deltacloud/src/test/java/org/jclouds/deltacloud/ReadOnlyDeltacloudClientLiveTest.java @@ -30,12 +30,11 @@ import org.jclouds.deltacloud.domain.DeltacloudCollection; import org.jclouds.deltacloud.domain.HardwareProfile; import org.jclouds.deltacloud.domain.Image; import org.jclouds.deltacloud.domain.Instance; +import org.jclouds.deltacloud.domain.Instance.State; import org.jclouds.deltacloud.domain.Realm; import org.jclouds.deltacloud.domain.Transition; -import org.jclouds.deltacloud.domain.Instance.State; import org.jclouds.deltacloud.predicates.InstanceFinished; import org.jclouds.deltacloud.predicates.InstanceRunning; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.InetSocketAddressConnect; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.sshj.config.SshjSshClientModule; @@ -48,6 +47,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Multimap; +import com.google.common.net.HostAndPort; import com.google.inject.Module; /** @@ -64,7 +64,7 @@ public class ReadOnlyDeltacloudClientLiveTest extends BaseComputeServiceContextL protected DeltacloudClient client; - protected Predicate socketTester; + protected Predicate socketTester; protected ImmutableMap> stateChanges; @Override @@ -72,7 +72,7 @@ public class ReadOnlyDeltacloudClientLiveTest extends BaseComputeServiceContextL public void setupContext() { super.setupContext(); client = view.unwrap(DeltacloudApiMetadata.CONTEXT_TOKEN).getApi(); - socketTester = new RetryablePredicate(new InetSocketAddressConnect(), 180, 1, TimeUnit.SECONDS); + socketTester = new RetryablePredicate(new InetSocketAddressConnect(), 180, 1, TimeUnit.SECONDS); stateChanges = ImmutableMap.> of(// Instance.State.RUNNING, new RetryablePredicate(new InstanceRunning(client), 600, 1, TimeUnit.SECONDS),// diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/CloudApplicationArchitecturesEC2ClientLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/CloudApplicationArchitecturesEC2ClientLiveTest.java index 69e4ef37b4..ad21a91cf6 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/CloudApplicationArchitecturesEC2ClientLiveTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/CloudApplicationArchitecturesEC2ClientLiveTest.java @@ -37,6 +37,7 @@ import org.jclouds.compute.domain.ExecResponse; import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest; import org.jclouds.domain.LoginCredentials; import org.jclouds.ec2.domain.BlockDevice; +import org.jclouds.ec2.domain.Image.EbsBlockDevice; import org.jclouds.ec2.domain.InstanceState; import org.jclouds.ec2.domain.InstanceType; import org.jclouds.ec2.domain.IpProtocol; @@ -44,12 +45,10 @@ import org.jclouds.ec2.domain.KeyPair; import org.jclouds.ec2.domain.PublicIpInstanceIdPair; import org.jclouds.ec2.domain.Reservation; import org.jclouds.ec2.domain.RunningInstance; -import org.jclouds.ec2.domain.Image.EbsBlockDevice; import org.jclouds.ec2.domain.Volume.InstanceInitiatedShutdownBehavior; import org.jclouds.ec2.predicates.InstanceHasIpAddress; import org.jclouds.ec2.predicates.InstanceStateRunning; import org.jclouds.http.HttpResponseException; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.predicates.SocketOpen; import org.jclouds.scriptbuilder.ScriptBuilder; @@ -63,6 +62,7 @@ import org.testng.annotations.Test; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; +import com.google.common.net.HostAndPort; import com.google.inject.Injector; /** @@ -88,7 +88,7 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest extends BaseComputeS private String instanceId; private String address; - private RetryablePredicate socketTester; + private RetryablePredicate socketTester; private RetryablePredicate hasIpTester; private RetryablePredicate runningTester; @@ -102,7 +102,7 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest extends BaseComputeS TimeUnit.SECONDS); hasIpTester = new RetryablePredicate(new InstanceHasIpAddress(client), 180, 5, TimeUnit.SECONDS); SocketOpen socketOpen = injector.getInstance(SocketOpen.class); - socketTester = new RetryablePredicate(socketOpen, 180, 1, TimeUnit.SECONDS); + socketTester = new RetryablePredicate(socketOpen, 180, 1, TimeUnit.SECONDS); } @Test(enabled = false) @@ -296,7 +296,7 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest extends BaseComputeS Thread.sleep(1000); instance = getInstance(instanceId); blockUntilWeCanSshIntoInstance(instance); - SshClient ssh = sshFactory.create(new IPSocket(instance.getIpAddress(), 22), + SshClient ssh = sshFactory.create(HostAndPort.fromParts(instance.getIpAddress(), 22), LoginCredentials.builder().user("root").privateKey(keyPair.getKeyMaterial()).build()); try { ssh.connect(); @@ -357,14 +357,14 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest extends BaseComputeS assert hasIpTester.apply(instance); System.out.printf("%d: %s awaiting ssh service to start%n", System.currentTimeMillis(), instance.getIpAddress()); - assert socketTester.apply(new IPSocket(instance.getIpAddress(), 22)); + assert socketTester.apply(HostAndPort.fromParts(instance.getIpAddress(), 22)); System.out.printf("%d: %s ssh service started%n", System.currentTimeMillis(), instance.getDnsName()); sshPing(instance); System.out.printf("%d: %s ssh connection made%n", System.currentTimeMillis(), instance.getId()); System.out.printf("%d: %s awaiting http service to start%n", System.currentTimeMillis(), instance.getIpAddress()); - assert socketTester.apply(new IPSocket(instance.getIpAddress(), 80)); + assert socketTester.apply(HostAndPort.fromParts(instance.getIpAddress(), 80)); System.out.printf("%d: %s http service started%n", System.currentTimeMillis(), instance.getDnsName()); return instance; } @@ -401,7 +401,7 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest extends BaseComputeS } private void doCheckKey(String address) { - SshClient ssh = sshFactory.create(new IPSocket(address, 22), + SshClient ssh = sshFactory.create(HostAndPort.fromParts(address, 22), LoginCredentials.builder().user("root").privateKey(keyPair.getKeyMaterial()).build()); try { ssh.connect(); diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/EBSBootEC2ClientLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/EBSBootEC2ClientLiveTest.java index 9f6f126bbd..a0e0a21373 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/EBSBootEC2ClientLiveTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/EBSBootEC2ClientLiveTest.java @@ -39,6 +39,8 @@ import org.jclouds.domain.LoginCredentials; import org.jclouds.ec2.domain.Attachment; import org.jclouds.ec2.domain.BlockDevice; import org.jclouds.ec2.domain.Image; +import org.jclouds.ec2.domain.Image.Architecture; +import org.jclouds.ec2.domain.Image.ImageType; import org.jclouds.ec2.domain.InstanceState; import org.jclouds.ec2.domain.InstanceType; import org.jclouds.ec2.domain.IpProtocol; @@ -48,8 +50,6 @@ import org.jclouds.ec2.domain.RootDeviceType; import org.jclouds.ec2.domain.RunningInstance; import org.jclouds.ec2.domain.Snapshot; import org.jclouds.ec2.domain.Volume; -import org.jclouds.ec2.domain.Image.Architecture; -import org.jclouds.ec2.domain.Image.ImageType; import org.jclouds.ec2.domain.Volume.InstanceInitiatedShutdownBehavior; import org.jclouds.ec2.predicates.InstanceStateRunning; import org.jclouds.ec2.predicates.InstanceStateStopped; @@ -59,7 +59,6 @@ import org.jclouds.ec2.predicates.VolumeAttached; import org.jclouds.ec2.predicates.VolumeAvailable; import org.jclouds.http.HttpResponseException; import org.jclouds.io.Payloads; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.predicates.SocketOpen; import org.jclouds.scriptbuilder.InitScript; @@ -76,6 +75,7 @@ import com.google.common.base.Predicate; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; +import com.google.common.net.HostAndPort; import com.google.inject.Injector; /** @@ -107,7 +107,7 @@ public class EBSBootEC2ClientLiveTest extends BaseComputeServiceContextLiveTest private KeyPair keyPair; private String securityGroupName; - private RetryablePredicate socketTester; + private RetryablePredicate socketTester; private RetryablePredicate attachTester; private RetryablePredicate volumeTester; private RunningInstance instance; @@ -130,7 +130,7 @@ public class EBSBootEC2ClientLiveTest extends BaseComputeServiceContextLiveTest client = injector.getInstance(EC2Client.class); sshFactory = injector.getInstance(SshClient.Factory.class); SocketOpen socketOpen = injector.getInstance(SocketOpen.class); - socketTester = new RetryablePredicate(socketOpen, 120, 1, TimeUnit.SECONDS); + socketTester = new RetryablePredicate(socketOpen, 120, 1, TimeUnit.SECONDS); VolumeAvailable volumeAvailable = injector.getInstance(VolumeAvailable.class); volumeTester = new RetryablePredicate(volumeAvailable, 60, 1, TimeUnit.SECONDS); @@ -273,7 +273,7 @@ public class EBSBootEC2ClientLiveTest extends BaseComputeServiceContextLiveTest @Test(enabled = false, dependsOnMethods = "testCreateAndAttachVolume") void testBundleInstance() { - SshClient ssh = sshFactory.create(new IPSocket(instance.getIpAddress(), 22), + SshClient ssh = sshFactory.create(HostAndPort.fromParts(instance.getIpAddress(), 22), LoginCredentials.builder().user("ubuntu").privateKey(keyPair.getKeyMaterial()).build()); try { ssh.connect(); @@ -510,7 +510,7 @@ public class EBSBootEC2ClientLiveTest extends BaseComputeServiceContextLiveTest } private void doCheckKey(String address) { - SshClient ssh = sshFactory.create(new IPSocket(address, 22), + SshClient ssh = sshFactory.create(HostAndPort.fromParts(address, 22), LoginCredentials.builder().user("ubuntu").privateKey(keyPair.getKeyMaterial()).build()); try { ssh.connect(); @@ -538,7 +538,7 @@ public class EBSBootEC2ClientLiveTest extends BaseComputeServiceContextLiveTest instance = Iterables.getOnlyElement(Iterables.getOnlyElement(reservations)); System.out.printf("%d: %s awaiting ssh service to start%n", System.currentTimeMillis(), instance.getIpAddress()); - assert socketTester.apply(new IPSocket(instance.getIpAddress(), 22)); + assert socketTester.apply(HostAndPort.fromParts(instance.getIpAddress(), 22)); System.out.printf("%d: %s ssh service started%n", System.currentTimeMillis(), instance.getDnsName()); sshPing(instance); System.out.printf("%d: %s ssh connection made%n", System.currentTimeMillis(), instance.getId()); diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2ComputeServiceLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2ComputeServiceLiveTest.java index cb8fa386ff..39f04e8e4a 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2ComputeServiceLiveTest.java +++ b/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2ComputeServiceLiveTest.java @@ -54,7 +54,6 @@ import org.jclouds.ec2.services.ElasticBlockStoreClient; import org.jclouds.ec2.services.InstanceClient; import org.jclouds.ec2.services.KeyPairClient; import org.jclouds.ec2.services.SecurityGroupClient; -import org.jclouds.net.IPSocket; import org.jclouds.scriptbuilder.domain.Statements; import org.jclouds.sshj.config.SshjSshClientModule; import org.jclouds.util.InetAddresses2; @@ -65,6 +64,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Iterables; import com.google.common.collect.Sets; +import com.google.common.net.HostAndPort; import com.google.inject.Module; /** @@ -198,7 +198,7 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest { // Check that the address is public and port 22 is accessible String ip = Iterables.getOnlyElement(publicIps); assertFalse(InetAddresses2.isPrivateIPAddress(ip)); - IPSocket socket = new IPSocket(ip, 22); + HostAndPort socket = HostAndPort.fromParts(ip, 22); assertTrue(socketTester.apply(socket), String.format("failed to open socket %s on node %s", socket, node)); // check that there is an elastic ip correlating to it diff --git a/apis/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackClientLiveTest.java b/apis/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackClientLiveTest.java index 5365d502c7..54c9fd1709 100644 --- a/apis/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackClientLiveTest.java +++ b/apis/elasticstack/src/test/java/org/jclouds/elasticstack/ElasticStackClientLiveTest.java @@ -43,7 +43,6 @@ import org.jclouds.elasticstack.domain.ServerStatus; import org.jclouds.elasticstack.predicates.DriveClaimed; import org.jclouds.elasticstack.util.Servers; import org.jclouds.io.Payloads; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.InetSocketAddressConnect; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.rest.RestContext; @@ -59,6 +58,7 @@ import com.google.common.base.Predicates; import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.net.HostAndPort; import com.google.gson.Gson; import com.google.inject.Guice; @@ -81,7 +81,7 @@ public class ElasticStackClientLiveTest protected String vncPassword = "Il0veVNC"; protected ElasticStackClient client; protected RestContext cloudStackContext; - protected Predicate socketTester; + protected Predicate socketTester; protected Predicate driveNotClaimed; @BeforeGroups(groups = { "integration", "live" }) @@ -93,7 +93,7 @@ public class ElasticStackClientLiveTest client = cloudStackContext.getApi(); driveNotClaimed = new RetryablePredicate(Predicates.not(new DriveClaimed(client)), maxDriveImageTime, 1, TimeUnit.SECONDS); - socketTester = new RetryablePredicate(new InetSocketAddressConnect(), maxDriveImageTime, 1, + socketTester = new RetryablePredicate(new InetSocketAddressConnect(), maxDriveImageTime, 1, TimeUnit.SECONDS); if (Strings.emptyToNull(imageId) == null) { @@ -229,10 +229,10 @@ public class ElasticStackClientLiveTest @Test(dependsOnMethods = "testCreateAndStartServer") public void testConnectivity() throws Exception { - IPSocket vncsocket = new IPSocket(server.getVnc().getIp(), 5900); + HostAndPort vncsocket = HostAndPort.fromParts(server.getVnc().getIp(), 5900); Logger.getAnonymousLogger().info("awaiting vnc: " + vncsocket); assert socketTester.apply(vncsocket) : server; - IPSocket sshsocket = new IPSocket(server.getNics().get(0).getDhcp(), 22); + HostAndPort sshsocket = HostAndPort.fromParts(server.getNics().get(0).getDhcp(), 22); Logger.getAnonymousLogger().info("awaiting ssh: " + sshsocket); assert socketTester.apply(sshsocket) : server; doConnectViaSsh(server, getSshCredentials(server)); @@ -290,7 +290,7 @@ public class ElasticStackClientLiveTest protected void doConnectViaSsh(Server server, LoginCredentials creds) throws IOException { SshClient ssh = Guice.createInjector(new SshjSshClientModule()).getInstance(SshClient.Factory.class).create( - new IPSocket(server.getVnc().getIp(), 22), creds); + HostAndPort.fromParts(server.getVnc().getIp(), 22), creds); try { ssh.connect(); ExecResponse hello = ssh.exec("echo hello"); diff --git a/apis/nova/src/test/java/org/jclouds/openstack/nova/NovaClientLiveTest.java b/apis/nova/src/test/java/org/jclouds/openstack/nova/NovaClientLiveTest.java index ccbdeb509d..769a3afc45 100644 --- a/apis/nova/src/test/java/org/jclouds/openstack/nova/NovaClientLiveTest.java +++ b/apis/nova/src/test/java/org/jclouds/openstack/nova/NovaClientLiveTest.java @@ -36,7 +36,6 @@ import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest; import org.jclouds.domain.LoginCredentials; import org.jclouds.http.HttpResponseException; import org.jclouds.io.Payload; -import org.jclouds.net.IPSocket; import org.jclouds.openstack.nova.domain.Flavor; import org.jclouds.openstack.nova.domain.Image; import org.jclouds.openstack.nova.domain.ImageStatus; @@ -56,6 +55,7 @@ import org.testng.annotations.Test; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; +import com.google.common.net.HostAndPort; import com.google.inject.Injector; /** @@ -72,7 +72,7 @@ public class NovaClientLiveTest extends BaseComputeServiceContextLiveTest { protected NovaClient client; protected SshClient.Factory sshFactory; - protected Predicate socketTester; + protected Predicate socketTester; @BeforeGroups(groups = { "integration", "live" }) @Override @@ -82,7 +82,7 @@ public class NovaClientLiveTest extends BaseComputeServiceContextLiveTest { client = injector.getInstance(NovaClient.class); sshFactory = injector.getInstance(SshClient.Factory.class); SocketOpen socketOpen = injector.getInstance(SocketOpen.class); - socketTester = new RetryablePredicate(socketOpen, 120, 1, TimeUnit.SECONDS); + socketTester = new RetryablePredicate(socketOpen, 120, 1, TimeUnit.SECONDS); injector.injectMembers(socketOpen); // add logger } @@ -296,7 +296,7 @@ public class NovaClientLiveTest extends BaseComputeServiceContextLiveTest { } private void doCheckPass(Server newDetails, String pass) throws IOException { - IPSocket socket = new IPSocket(Iterables.get(newDetails.getAddresses().getPublicAddresses(), 0).getAddress(), 22); + HostAndPort socket = HostAndPort.fromParts(Iterables.get(newDetails.getAddresses().getPublicAddresses(), 0).getAddress(), 22); socketTester.apply(socket); SshClient client = sshFactory.create(socket, LoginCredentials.builder().user("root").password(pass).build()); diff --git a/apis/vcloud/src/test/java/org/jclouds/vcloud/features/VmClientLiveTest.java b/apis/vcloud/src/test/java/org/jclouds/vcloud/features/VmClientLiveTest.java index 2fd7661601..35f387467f 100644 --- a/apis/vcloud/src/test/java/org/jclouds/vcloud/features/VmClientLiveTest.java +++ b/apis/vcloud/src/test/java/org/jclouds/vcloud/features/VmClientLiveTest.java @@ -28,7 +28,6 @@ import static org.testng.Assert.assertNotNull; import org.jclouds.compute.domain.ExecResponse; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.options.TemplateOptions; -import org.jclouds.net.IPSocket; import org.jclouds.vcloud.VCloudApiMetadata; import org.jclouds.vcloud.VCloudMediaType; import org.jclouds.vcloud.compute.options.VCloudTemplateOptions; @@ -41,6 +40,7 @@ import org.jclouds.vcloud.internal.BaseVCloudClientLiveTest; import org.testng.annotations.Test; import com.google.common.collect.Iterables; +import com.google.common.net.HostAndPort; /** * This tests that we can use guest customization as an alternative to bootstrapping with ssh. There @@ -157,8 +157,8 @@ public class VmClientLiveTest extends BaseVCloudClientLiveTest { assertEquals(apiOutput, script.replace("\n", "")); } - protected IPSocket getSocket(NodeMetadata node) { - return new IPSocket(get(node.getPublicAddresses(), 0), 22); + protected HostAndPort getSocket(NodeMetadata node) { + return HostAndPort.fromParts(get(node.getPublicAddresses(), 0), 22); } } \ No newline at end of file diff --git a/blobstore/src/main/java/org/jclouds/blobstore/TransientAsyncBlobStore.java b/blobstore/src/main/java/org/jclouds/blobstore/TransientAsyncBlobStore.java index 81ef2f5dfd..28891d32a3 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/TransientAsyncBlobStore.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/TransientAsyncBlobStore.java @@ -179,11 +179,13 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore { final String finalMarker = options.getMarker(); StorageMetadata lastMarkerMetadata = find(contents, new Predicate() { public boolean apply(StorageMetadata metadata) { - return metadata.getName().equals(finalMarker); + return metadata.getName().compareTo(finalMarker) >= 0; } }); contents = contents.tailSet(lastMarkerMetadata); - contents.remove(lastMarkerMetadata); + if (finalMarker.equals(lastMarkerMetadata.getName())) { + contents.remove(lastMarkerMetadata); + } } final String prefix = options.getDir(); diff --git a/blobstore/src/main/java/org/jclouds/blobstore/options/ListContainerOptions.java b/blobstore/src/main/java/org/jclouds/blobstore/options/ListContainerOptions.java index 8b42bea841..ab84be050b 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/options/ListContainerOptions.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/options/ListContainerOptions.java @@ -140,8 +140,9 @@ public class ListContainerOptions extends ListOptions implements Cloneable { * */ public ListContainerOptions inDirectory(String dir) { - this.dir = checkNotNull(dir, "dir"); + checkNotNull(dir, "dir"); checkArgument(!dir.equals("/"), "dir must not be a slash"); + this.dir = dir; return this; } diff --git a/blobstore/src/main/java/org/jclouds/blobstore/strategy/internal/DeleteAllKeysInList.java b/blobstore/src/main/java/org/jclouds/blobstore/strategy/internal/DeleteAllKeysInList.java index ee4c38ea05..dc8b816df2 100644 --- a/blobstore/src/main/java/org/jclouds/blobstore/strategy/internal/DeleteAllKeysInList.java +++ b/blobstore/src/main/java/org/jclouds/blobstore/strategy/internal/DeleteAllKeysInList.java @@ -22,6 +22,7 @@ import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursi import static org.jclouds.concurrent.FutureIterables.awaitCompletion; import java.util.Map; +import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; @@ -31,17 +32,18 @@ import javax.inject.Singleton; import org.jclouds.Constants; import org.jclouds.blobstore.AsyncBlobStore; +import org.jclouds.blobstore.domain.PageSet; import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.internal.BlobRuntimeException; import org.jclouds.blobstore.options.ListContainerOptions; import org.jclouds.blobstore.reference.BlobStoreConstants; import org.jclouds.blobstore.strategy.ClearContainerStrategy; import org.jclouds.blobstore.strategy.ClearListStrategy; -import org.jclouds.blobstore.strategy.ListContainerStrategy; import org.jclouds.http.handlers.BackoffLimitedRetryHandler; import org.jclouds.logging.Logger; import com.google.common.base.Predicate; +import com.google.common.base.Throwables; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.inject.Inject; @@ -57,7 +59,6 @@ public class DeleteAllKeysInList implements ClearListStrategy, ClearContainerStr @Named(BlobStoreConstants.BLOBSTORE_LOGGER) protected Logger logger = Logger.NULL; - protected final ListContainerStrategy listContainer; protected final BackoffLimitedRetryHandler retryHandler; private final ExecutorService userExecutor; @@ -71,12 +72,11 @@ public class DeleteAllKeysInList implements ClearListStrategy, ClearContainerStr @Inject DeleteAllKeysInList(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor, - AsyncBlobStore connection, ListContainerStrategy listContainer, + AsyncBlobStore connection, BackoffLimitedRetryHandler retryHandler) { this.userExecutor = userExecutor; this.connection = connection; - this.listContainer = listContainer; this.retryHandler = retryHandler; } @@ -84,19 +84,31 @@ public class DeleteAllKeysInList implements ClearListStrategy, ClearContainerStr execute(containerName, recursive()); } - public void execute(final String containerName, final ListContainerOptions options) { + public void execute(final String containerName, ListContainerOptions options) { String message = options.getDir() != null ? String.format("clearing path %s/%s", containerName, options.getDir()) : String.format("clearing container %s", containerName); + options = options.clone(); if (options.isRecursive()) message = message + " recursively"; Map exceptions = Maps.newHashMap(); + PageSet listing; Iterable toDelete; - for (int i = 0; i < 3; i++) { // TODO parameterize - toDelete = getResourcesToDelete(containerName, options); - if (Iterables.isEmpty(toDelete)) { - break; + int maxErrors = 3; // TODO parameterize + for (int i = 0; i < maxErrors; ) { + try { + listing = connection.list(containerName, options).get(); + } catch (ExecutionException ee) { + ++i; + if (i == maxErrors) { + throw new BlobRuntimeException("list error", ee.getCause()); + } + retryHandler.imposeBackoffExponentialDelay(i, message); + continue; + } catch (InterruptedException ie) { + throw Throwables.propagate(ie); } + toDelete = filterListing(listing, options); Map> responses = Maps.newHashMap(); try { @@ -127,24 +139,30 @@ public class DeleteAllKeysInList implements ClearListStrategy, ClearContainerStr exceptions = awaitCompletion(responses, userExecutor, maxTime, logger, message); } if (!exceptions.isEmpty()) { - retryHandler.imposeBackoffExponentialDelay(i + 1, message); + ++i; + retryHandler.imposeBackoffExponentialDelay(i, message); + continue; } + + String marker = listing.getNextMarker(); + if (marker == null) { + break; + } + options = options.afterMarker(marker); } if (!exceptions.isEmpty()) throw new BlobRuntimeException(String.format("error %s: %s", message, exceptions)); - toDelete = getResourcesToDelete(containerName, options); - assert Iterables.isEmpty(toDelete) : String.format("items remaining %s: %s", message, - toDelete); } private boolean parentIsFolder(final ListContainerOptions options, final StorageMetadata md) { return (options.getDir() != null && md.getName().indexOf('/') == -1); } - private Iterable getResourcesToDelete(final String containerName, + private Iterable filterListing( + final PageSet listing, final ListContainerOptions options) { - Iterable toDelete = Iterables.filter(listContainer.execute( - containerName, options), new Predicate() { + Iterable toDelete = Iterables.filter(listing, + new Predicate() { @Override public boolean apply(StorageMetadata input) { diff --git a/blobstore/src/test/java/org/jclouds/blobstore/strategy/internal/ConcatenateContainerListsTest.java b/blobstore/src/test/java/org/jclouds/blobstore/strategy/internal/ConcatenateContainerListsTest.java new file mode 100644 index 0000000000..6a98a5c634 --- /dev/null +++ b/blobstore/src/test/java/org/jclouds/blobstore/strategy/internal/ConcatenateContainerListsTest.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.blobstore.strategy.internal; + +import static org.testng.Assert.assertEquals; + +import org.jclouds.ContextBuilder; +import org.jclouds.blobstore.BlobStore; +import org.jclouds.blobstore.domain.StorageMetadata; +import org.jclouds.blobstore.options.ListContainerOptions; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import com.google.common.collect.Iterables; +import com.google.common.io.Closeables; +import com.google.inject.Injector; + +/** + * + * @author Adrian Cole + */ +@Test(testName = "ConcatenateContainerListsTest", singleThreaded = true) +public class ConcatenateContainerListsTest { + private BlobStore blobstore; + private ConcatenateContainerLists concatter; + + @BeforeClass + void setupBlobStore() { + Injector injector = ContextBuilder.newBuilder("transient").buildInjector(); + blobstore = injector.getInstance(BlobStore.class); + concatter = injector.getInstance(ConcatenateContainerLists.class); + } + + public void testLargerThanOnePageNoOptions() { + blobstore.createContainerInLocation(null, "goodies"); + for (int i = 0; i < 1001; i++) { + blobstore.putBlob("goodies", blobstore.blobBuilder(i + "").payload(i + "").build()); + } + Iterable listing = concatter.execute("goodies", new ListContainerOptions()); + assertEquals(Iterables.size(listing), 1001); + } + + public void testLargerThanOnePageInDirAndRecursive() { + blobstore.createContainerInLocation(null, "foo"); + for (int i = 0; i < 1001; i++) { + blobstore.putBlob("foo", blobstore.blobBuilder(i + "").payload(i + "").build()); + } + for (int i = 0; i < 1001; i++) { + blobstore.putBlob("foo", blobstore.blobBuilder("dir/" + i + "").payload(i + "").build()); + } + Iterable listing = concatter.execute("foo", new ListContainerOptions()); + // TODO: this looks broke. seems we should have 1002 (1001 + directory foo), not 1003 + assertEquals(Iterables.size(listing), 1003); + listing = concatter.execute("foo", ListContainerOptions.Builder.inDirectory("dir")); + assertEquals(Iterables.size(listing), 1001); + listing = concatter.execute("foo", ListContainerOptions.Builder.recursive()); + assertEquals(Iterables.size(listing), 2002); + } + + @AfterClass + void close() { + if (blobstore != null) + Closeables.closeQuietly(blobstore.getContext()); + } +} diff --git a/blobstore/src/test/java/org/jclouds/blobstore/strategy/internal/DeleteAllKeysInListTest.java b/blobstore/src/test/java/org/jclouds/blobstore/strategy/internal/DeleteAllKeysInListTest.java new file mode 100644 index 0000000000..47de7565e5 --- /dev/null +++ b/blobstore/src/test/java/org/jclouds/blobstore/strategy/internal/DeleteAllKeysInListTest.java @@ -0,0 +1,77 @@ +/** + * 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.blobstore.strategy.internal; + +import static org.testng.Assert.assertEquals; + +import org.jclouds.ContextBuilder; +import org.jclouds.blobstore.BlobStore; +import org.jclouds.blobstore.options.ListContainerOptions; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import com.google.common.io.Closeables; +import com.google.inject.Injector; + +/** + * + * @author Adrian Cole + */ +@Test(testName = "DeleteAllKeysInListTest", singleThreaded = true) +public class DeleteAllKeysInListTest { + private BlobStore blobstore; + private DeleteAllKeysInList deleter; + + @BeforeClass + void setupBlobStore() { + Injector injector = ContextBuilder.newBuilder("transient").buildInjector(); + blobstore = injector.getInstance(BlobStore.class); + deleter = injector.getInstance(DeleteAllKeysInList.class); + } + + public void testExecuteWithoutOptionsClearsRecursively() { + blobstore.createContainerInLocation(null, "goodies"); + for (int i = 0; i < 1001; i++) { + blobstore.putBlob("goodies", blobstore.blobBuilder(i + "").payload(i + "").build()); + } + assertEquals(blobstore.countBlobs("goodies"), 1001); + deleter.execute("goodies"); + assertEquals(blobstore.countBlobs("goodies"), 0); + } + + public void testExecuteNonRecursive() { + blobstore.createContainerInLocation(null, "foo"); + for (int i = 0; i < 1001; i++) { + blobstore.putBlob("foo", blobstore.blobBuilder(i + "").payload(i + "").build()); + } + for (int i = 0; i < 1001; i++) { + blobstore.putBlob("foo", blobstore.blobBuilder("dir/" + i + "").payload(i + "").build()); + } + assertEquals(blobstore.countBlobs("foo"), 2002); + deleter.execute("foo", ListContainerOptions.Builder.inDirectory("dir")); + assertEquals(blobstore.countBlobs("foo"), 1001); + } + + @AfterClass + void close() { + if (blobstore != null) + Closeables.closeQuietly(blobstore.getContext()); + } +} diff --git a/common/aws/src/main/java/org/jclouds/aws/handlers/ParseAWSErrorFromXmlContent.java b/common/aws/src/main/java/org/jclouds/aws/handlers/ParseAWSErrorFromXmlContent.java index 7471bf47c5..e4dc779e8c 100644 --- a/common/aws/src/main/java/org/jclouds/aws/handlers/ParseAWSErrorFromXmlContent.java +++ b/common/aws/src/main/java/org/jclouds/aws/handlers/ParseAWSErrorFromXmlContent.java @@ -18,6 +18,7 @@ */ package org.jclouds.aws.handlers; +import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream; import static org.jclouds.http.HttpUtils.releasePayload; import java.io.IOException; @@ -65,7 +66,9 @@ public class ParseAWSErrorFromXmlContent implements HttpErrorHandler { Exception exception = new HttpResponseException(command, response); try { AWSError error = null; - String message = null; + // it is important to always read fully and close streams + byte[] data = closeClientButKeepContentStream(response); + String message = data != null ? new String(data) : null; if (response.getPayload() != null) { String contentType = response.getPayload().getContentMetadata().getContentType(); if (contentType != null && (contentType.indexOf("xml") != -1 || contentType.indexOf("unknown") != -1)) { diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/ServiceAsyncClient.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/AuthenticationAsyncClient.java similarity index 93% rename from common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/ServiceAsyncClient.java rename to common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/AuthenticationAsyncClient.java index d47967c2c8..be75da1b5a 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/ServiceAsyncClient.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/AuthenticationAsyncClient.java @@ -35,17 +35,17 @@ import com.google.common.util.concurrent.ListenableFuture; * Provides asynchronous access to Service via their REST API. *

* - * @see ServiceClient + * @see AuthenticationClient * @see * @author Adrian Cole */ @Path("/v1.1") -public interface ServiceAsyncClient { +public interface AuthenticationAsyncClient { /** - * @see ServiceClient#authenticate + * @see AuthenticationClient#authenticate */ @POST @SelectJson("auth") diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/ServiceClient.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/AuthenticationClient.java similarity index 95% rename from common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/ServiceClient.java rename to common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/AuthenticationClient.java index 5bbb520611..0e51289ad8 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/ServiceClient.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/AuthenticationClient.java @@ -27,13 +27,13 @@ import org.jclouds.openstack.keystone.v1_1.domain.Auth; * Provides synchronous access to the KeyStone Service API. *

* - * @see ServiceAsyncClient + * @see AuthenticationAsyncClient * @see * @author Adrian Cole */ @Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) -public interface ServiceClient { +public interface AuthenticationClient { /** * Authenticate to generate a token. diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/config/AuthenticationServiceModule.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/config/AuthenticationServiceModule.java index ba16265d27..4f70bc4c0f 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/config/AuthenticationServiceModule.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/config/AuthenticationServiceModule.java @@ -35,8 +35,8 @@ import org.jclouds.http.annotation.ClientError; import org.jclouds.location.Provider; import org.jclouds.location.suppliers.RegionIdToURISupplier; import org.jclouds.openstack.Authentication; -import org.jclouds.openstack.keystone.v1_1.ServiceAsyncClient; -import org.jclouds.openstack.keystone.v1_1.ServiceClient; +import org.jclouds.openstack.keystone.v1_1.AuthenticationAsyncClient; +import org.jclouds.openstack.keystone.v1_1.AuthenticationClient; import org.jclouds.openstack.keystone.v1_1.domain.Auth; import org.jclouds.openstack.keystone.v1_1.handlers.RetryOnRenew; import org.jclouds.openstack.keystone.v1_1.suppliers.RegionIdToURIFromAuthForServiceSupplier; @@ -63,7 +63,7 @@ public class AuthenticationServiceModule extends AbstractModule { }).to(GetAuth.class); // ServiceClient is used directly for filters and retry handlers, so let's bind it // explicitly - bindClientAndAsyncClient(binder(), ServiceClient.class, ServiceAsyncClient.class); + bindClientAndAsyncClient(binder(), AuthenticationClient.class, AuthenticationAsyncClient.class); install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class, RegionIdToURIFromAuthForServiceSupplier.class).build(RegionIdToURISupplier.Factory.class)); bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(RetryOnRenew.class); @@ -88,7 +88,7 @@ public class AuthenticationServiceModule extends AbstractModule { public static class GetAuth extends RetryOnTimeOutExceptionFunction { @Inject - public GetAuth(final ServiceClient client) { + public GetAuth(final AuthenticationClient client) { super(new Function() { @Override diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/ServiceAsyncClient.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationAsyncClient.java similarity index 90% rename from common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/ServiceAsyncClient.java rename to common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationAsyncClient.java index 31c1ffcd70..2f160ed365 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/ServiceAsyncClient.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationAsyncClient.java @@ -37,16 +37,16 @@ import com.google.common.util.concurrent.ListenableFuture; * Provides asynchronous access to Service via their REST API. *

* - * @see ServiceClient + * @see AuthenticationClient * @see * @author Adrian Cole */ @Path("/v2.0") -public interface ServiceAsyncClient { +public interface AuthenticationAsyncClient { /** - * @see ServiceClient#authenticateTenantWithCredentials(String,PasswordCredentials) + * @see AuthenticationClient#authenticateTenantWithCredentials(String,PasswordCredentials) */ @POST @SelectJson("access") @@ -57,7 +57,7 @@ public interface ServiceAsyncClient { PasswordCredentials passwordCredentials); /** - * @see ServiceClient#authenticateTenantWithCredentials(String,ApiAccessKeyCredentials) + * @see AuthenticationClient#authenticateTenantWithCredentials(String,ApiAccessKeyCredentials) */ @POST @SelectJson("access") diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/ServiceClient.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationClient.java similarity index 96% rename from common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/ServiceClient.java rename to common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationClient.java index 0e53e6067a..695b55f527 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/ServiceClient.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationClient.java @@ -29,13 +29,13 @@ import org.jclouds.openstack.keystone.v2_0.domain.PasswordCredentials; * Provides synchronous access to the KeyStone Service API. *

* - * @see ServiceAsyncClient + * @see AuthenticationAsyncClient * @see * @author Adrian Cole */ @Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) -public interface ServiceClient { +public interface AuthenticationClient { /** * Authenticate to generate a token. diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java index 4730cf4efd..21b1733918 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java @@ -40,12 +40,14 @@ import org.jclouds.location.suppliers.ZoneIdsSupplier; import org.jclouds.location.suppliers.derived.RegionIdsFromRegionIdToURIKeySet; import org.jclouds.location.suppliers.derived.ZoneIdsFromZoneIdToURIKeySet; import org.jclouds.openstack.Authentication; -import org.jclouds.openstack.keystone.v2_0.ServiceAsyncClient; -import org.jclouds.openstack.keystone.v2_0.ServiceClient; +import org.jclouds.openstack.keystone.v2_0.AuthenticationAsyncClient; +import org.jclouds.openstack.keystone.v2_0.AuthenticationClient; import org.jclouds.openstack.keystone.v2_0.domain.Access; import org.jclouds.openstack.keystone.v2_0.functions.AuthenticateApiAccessKeyCredentials; import org.jclouds.openstack.keystone.v2_0.functions.AuthenticatePasswordCredentials; import org.jclouds.openstack.keystone.v2_0.handlers.RetryOnRenew; +import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToAdminURIFromAccessForTypeAndVersionSupplier; +import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToAdminURISupplier; import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToURIFromAccessForTypeAndVersionSupplier; import org.jclouds.openstack.keystone.v2_0.suppliers.ZoneIdToURIFromAccessForTypeAndVersionSupplier; import org.jclouds.rest.annotations.ApiVersion; @@ -85,6 +87,8 @@ public class KeystoneAuthenticationModule extends AbstractModule { protected void configure() { install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class, RegionIdToURIFromAccessForTypeAndVersionSupplier.class).build(RegionIdToURISupplier.Factory.class)); + install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class, + RegionIdToAdminURIFromAccessForTypeAndVersionSupplier.class).build(RegionIdToAdminURISupplier.Factory.class)); // dynamically build the region list as opposed to from properties bind(RegionIdsSupplier.class).to(RegionIdsFromRegionIdToURIKeySet.class); } @@ -98,6 +102,16 @@ public class KeystoneAuthenticationModule extends AbstractModule { RegionIdToURISupplier.Factory factory) { return factory.createForApiTypeAndVersion(serviceType, apiVersion); } + + // supply the region to id to AdminURL map from keystone, based on the servicetype and api version in + // config + @Provides + @Singleton + protected RegionIdToAdminURISupplier provideRegionIdToAdminURISupplierForApiVersion( + @Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion, + RegionIdToAdminURISupplier.Factory factory) { + return factory.createForApiTypeAndVersion(serviceType, apiVersion); + } } @@ -132,7 +146,7 @@ public class KeystoneAuthenticationModule extends AbstractModule { bind(CredentialType.class).toProvider(CredentialTypeFromPropertyOrDefault.class); // ServiceClient is used directly for filters and retry handlers, so let's bind it // explicitly - bindClientAndAsyncClient(binder(), ServiceClient.class, ServiceAsyncClient.class); + bindClientAndAsyncClient(binder(), AuthenticationClient.class, AuthenticationAsyncClient.class); install(locationModule); } diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/ApiMetadata.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/ApiMetadata.java new file mode 100644 index 0000000000..61057d76da --- /dev/null +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/ApiMetadata.java @@ -0,0 +1,170 @@ +/** + * 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.keystone.v2_0.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Collections; +import java.util.Date; +import java.util.Set; + +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.openstack.domain.Link; +import org.jclouds.openstack.domain.Resource; + +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; +import com.google.gson.annotations.SerializedName; + +/** + * Class ApiMetadata + */ +public class ApiMetadata extends Resource { + + public static Builder builder() { + return new Builder(); + } + + public Builder toBuilder() { + return new Builder().fromApiMetadata(this); + } + + public static class Builder extends Resource.Builder { + private String status; + private Date updated; + private Set mediaTypes = Sets.newLinkedHashSet(); + + public Builder status(String status) { + this.status = status; + return this; + } + + public Builder updated(Date updated) { + this.updated = updated; + return this; + } + + public Builder mediaTypes(Set mediaTypes) { + this.mediaTypes = mediaTypes; + return this; + } + + public ApiMetadata build() { + return new ApiMetadata(id, name, links, updated, status, mediaTypes); + } + + public Builder fromApiMetadata(ApiMetadata in) { + return fromResource(in) + .status(in.getStatus()) + .updated(in.getUpdated()) + .mediaTypes(in.getMediaTypes()); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder id(String id) { + return Builder.class.cast(super.id(id)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder name(String name) { + return Builder.class.cast(super.name(name)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder links(Set links) { + return Builder.class.cast(super.links(links)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder fromResource(Resource in) { + return Builder.class.cast(super.fromResource(in)); + } + } + + private final String status; + private final Date updated; + @SerializedName("media-types") + private final Set mediaTypes; + + protected ApiMetadata(String id, String name, Set links, Date updated, String status, Set mediaTypes) { + super(id, name, links); + this.status = status; + this.updated = updated; + this.mediaTypes = ImmutableSet.copyOf(checkNotNull(mediaTypes, "mediaTypes")); + } + + /** + */ + @Nullable + public String getStatus() { + return this.status; + } + + /** + */ + @Nullable + public Date getUpdated() { + return this.updated; + } + + /** + */ + @Nullable + public Set getMediaTypes() { + return Collections.unmodifiableSet(this.mediaTypes); + } + + @Override + public int hashCode() { + return Objects.hashCode(status, updated, mediaTypes); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + ApiMetadata that = ApiMetadata.class.cast(obj); + return Objects.equal(this.status, that.status) + && Objects.equal(this.updated, that.updated) + && Objects.equal(this.mediaTypes, that.mediaTypes) + ; + } + + protected ToStringHelper string() { + return super.string() + .add("status", status) + .add("updated", updated) + .add("mediaTypes", mediaTypes); + } + +} \ No newline at end of file diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/Endpoint.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/Endpoint.java index f42e86b1e1..0b57843d22 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/Endpoint.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/Endpoint.java @@ -55,6 +55,7 @@ public class Endpoint implements Comparable { protected String region; protected URI publicURL; protected URI internalURL; + protected URI adminURL; protected String tenantId; /** @@ -89,6 +90,14 @@ public class Endpoint implements Comparable { return this; } + /** + * @see Endpoint#getInternalURL() + */ + public Builder adminURL(URI adminURL) { + this.adminURL = checkNotNull(adminURL, "adminURL"); + return this; + } + /** * @see Endpoint#getTenantId() */ @@ -98,7 +107,7 @@ public class Endpoint implements Comparable { } public Endpoint build() { - return new Endpoint(versionId, region, publicURL, internalURL, tenantId); + return new Endpoint(versionId, region, publicURL, internalURL, adminURL, tenantId); } public Builder fromEndpoint(Endpoint from) { @@ -113,17 +122,20 @@ public class Endpoint implements Comparable { protected final String region; protected final URI publicURL; protected final URI internalURL; + protected final URI adminURL; + // renamed half-way through @Deprecated protected String tenantName; protected final String tenantId; protected Endpoint(String versionId, String region, @Nullable URI publicURL, @Nullable URI internalURL, - @Nullable String tenantId) { + @Nullable URI adminURL, @Nullable String tenantId) { this.versionId = checkNotNull(versionId, "versionId"); this.region = checkNotNull(region, "region"); this.publicURL = publicURL; this.internalURL = internalURL; + this.adminURL = adminURL; this.tenantId = tenantId; } @@ -160,6 +172,14 @@ public class Endpoint implements Comparable { return internalURL; } + /** + * @return the admin url of the endpoint + */ + @Nullable + public URI getAdminURL() { + return adminURL; + } + /** * @return the tenant versionId of the endpoint or null */ @@ -176,7 +196,7 @@ public class Endpoint implements Comparable { if (object instanceof Endpoint) { final Endpoint other = Endpoint.class.cast(object); return equal(getVersionId(), other.getVersionId()) && equal(region, other.region) && equal(publicURL, other.publicURL) - && equal(internalURL, other.internalURL) && equal(getTenantId(), other.getTenantId()); + && equal(internalURL, other.internalURL) && equal(adminURL, other.adminURL) && equal(getTenantId(), other.getTenantId()); } else { return false; } @@ -184,13 +204,13 @@ public class Endpoint implements Comparable { @Override public int hashCode() { - return Objects.hashCode(getVersionId(), region, publicURL, internalURL, getTenantId()); + return Objects.hashCode(getVersionId(), region, publicURL, internalURL, adminURL, getTenantId()); } @Override public String toString() { return toStringHelper("").add("versionId", getVersionId()).add("region", region).add("publicURL", publicURL).add("internalURL", - internalURL).add("tenantId", getTenantId()).toString(); + internalURL).add("adminURL", adminURL).add("tenantId", getTenantId()).toString(); } @Override diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/MediaType.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/MediaType.java new file mode 100644 index 0000000000..cb3cf6d071 --- /dev/null +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/MediaType.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.keystone.v2_0.domain; + +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; + +/** + * Class MediaType + */ +public class MediaType { + + public static Builder builder() { + return new Builder(); + } + + public Builder toBuilder() { + return builder().fromMediaType(this); + } + + public static class Builder { + + private String base; + private String type; + + public Builder base(String base) { + this.base = base; + return this; + } + + public Builder type(String type) { + this.type = type; + return this; + } + + public MediaType build() { + return new MediaType(this); + } + + public Builder fromMediaType(MediaType in) { + return this.base(in.getBase()).type(in.getType()); + } + } + + private final String base; + private final String type; + + protected MediaType(Builder builder) { + this.base = builder.base; + this.type = builder.type; + } + + /** + */ + @Nullable + public String getBase() { + return this.base; + } + + /** + */ + @Nullable + public String getType() { + return this.type; + } + + @Override + public int hashCode() { + return Objects.hashCode(base, type); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + MediaType that = MediaType.class.cast(obj); + return Objects.equal(this.base, that.base) + && Objects.equal(this.type, that.type) + ; + } + + protected ToStringHelper string() { + return Objects.toStringHelper("") + .add("base", base) + .add("type", type); + } + + @Override + public String toString() { + return string().toString(); + } + +} \ No newline at end of file diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/Service.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/Service.java index 77a3bc27cf..6f8d579f74 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/Service.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/Service.java @@ -52,7 +52,7 @@ public class Service implements Comparable { protected Set endpoints = ImmutableSet.of(); /** - * @see Service#getId() + * @see Service#getType() */ public Builder type(String type) { this.type = checkNotNull(type, "type"); diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/Tenant.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/Tenant.java index 840892e338..35f884629c 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/Tenant.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/Tenant.java @@ -23,12 +23,16 @@ import static com.google.common.base.Objects.equal; import static com.google.common.base.Objects.toStringHelper; import static com.google.common.base.Preconditions.checkNotNull; +import javax.ws.rs.DefaultValue; + +import org.jclouds.javax.annotation.Nullable; + import com.google.common.base.Objects; /** * A container used to group or isolate resources and/or identity objects. Depending on the service * operator, a tenant may map to a customer, account, organization, or project. - * + * * @author Adrian Cole * @see @@ -46,6 +50,7 @@ public class Tenant implements Comparable { public static class Builder { protected String id; protected String name; + protected String description; /** * @see Tenant#getId() @@ -63,8 +68,16 @@ public class Tenant implements Comparable { return this; } + /** + * @see Tenant#getDescription() + */ + public Builder description(String description) { + this.description = description; + return this; + } + public Tenant build() { - return new Tenant(id, name); + return new Tenant(id, name, description); } public Builder fromTenant(Tenant from) { @@ -74,15 +87,17 @@ public class Tenant implements Comparable { protected final String id; protected final String name; + protected final String description; - public Tenant(String id, String name) { + protected Tenant(String id, String name, String description) { this.id = checkNotNull(id, "id"); this.name = checkNotNull(name, "name"); + this.description = description; } /** * When providing an ID, it is assumed that the tenant exists in the current OpenStack deployment - * + * * @return the id of the tenant in the current OpenStack deployment */ public String getId() { @@ -96,6 +111,14 @@ public class Tenant implements Comparable { return name; } + /** + * @return the description of the tenant + */ + @Nullable + public String getDescription() { + return description; + } + @Override public boolean equals(Object object) { if (this == object) { @@ -103,7 +126,8 @@ public class Tenant implements Comparable { } if (object instanceof Tenant) { final Tenant other = Tenant.class.cast(object); - return equal(id, other.id) && equal(name, other.name); + return equal(id, other.id) && equal(name, other.name) + && equal(description, other.description); } else { return false; } @@ -111,12 +135,12 @@ public class Tenant implements Comparable { @Override public int hashCode() { - return Objects.hashCode(id, name); + return Objects.hashCode(id, name, description); } @Override public String toString() { - return toStringHelper("").add("id", id).add("name", name).toString(); + return toStringHelper("").add("id", id).add("name", name).add("description", description).toString(); } @Override diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/User.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/User.java index 0ce93ccec3..e8d5ff7dcb 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/User.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/User.java @@ -98,11 +98,17 @@ public class User implements Comparable { protected final String name; protected final Set roles; - public User(String id, String name, Set roles) { + protected User(String id, String name, Set roles) { this.id = checkNotNull(id, "id"); this.name = checkNotNull(name, "name"); this.roles = ImmutableSet.copyOf(checkNotNull(roles, "roles")); } + + protected User() { + id = null; + name = null; + roles = ImmutableSet.of(); + } /** * When providing an ID, it is assumed that the user exists in the current OpenStack deployment diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AdminURL.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AdminURL.java new file mode 100644 index 0000000000..b4454b6497 --- /dev/null +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AdminURL.java @@ -0,0 +1,43 @@ +/** + * 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.keystone.v2_0.functions; + +import java.net.URI; + +import javax.inject.Singleton; + +import org.jclouds.openstack.keystone.v2_0.domain.Endpoint; + +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; + +/** + * @author Adam Lowe + */ +@Singleton +public class AdminURL implements EndpointToSupplierAdminURI { + @Override + public Supplier apply(Endpoint input) { + return Suppliers.ofInstance(input.getAdminURL()); + } + + public String toString() { + return "supplyAdminURL()"; + } +} \ No newline at end of file diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticateApiAccessKeyCredentials.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticateApiAccessKeyCredentials.java index b62cb33d69..29be1b1ded 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticateApiAccessKeyCredentials.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticateApiAccessKeyCredentials.java @@ -22,7 +22,7 @@ import javax.inject.Inject; import javax.inject.Singleton; import org.jclouds.domain.Credentials; -import org.jclouds.openstack.keystone.v2_0.ServiceClient; +import org.jclouds.openstack.keystone.v2_0.AuthenticationClient; import org.jclouds.openstack.keystone.v2_0.domain.Access; import org.jclouds.openstack.keystone.v2_0.domain.ApiAccessKeyCredentials; import org.jclouds.rest.AuthorizationException; @@ -31,10 +31,10 @@ import com.google.common.base.Function; @Singleton public class AuthenticateApiAccessKeyCredentials implements Function { - private final ServiceClient client; + private final AuthenticationClient client; @Inject - public AuthenticateApiAccessKeyCredentials(ServiceClient client) { + public AuthenticateApiAccessKeyCredentials(AuthenticationClient client) { this.client = client; } diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticatePasswordCredentials.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticatePasswordCredentials.java index 0191266ead..0c59e02ede 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticatePasswordCredentials.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticatePasswordCredentials.java @@ -20,7 +20,7 @@ package org.jclouds.openstack.keystone.v2_0.functions; import javax.inject.Inject; import org.jclouds.domain.Credentials; -import org.jclouds.openstack.keystone.v2_0.ServiceClient; +import org.jclouds.openstack.keystone.v2_0.AuthenticationClient; import org.jclouds.openstack.keystone.v2_0.domain.Access; import org.jclouds.openstack.keystone.v2_0.domain.PasswordCredentials; import org.jclouds.rest.AuthorizationException; @@ -28,10 +28,10 @@ import org.jclouds.rest.AuthorizationException; import com.google.common.base.Function; public class AuthenticatePasswordCredentials implements Function { - private final ServiceClient client; + private final AuthenticationClient client; @Inject - public AuthenticatePasswordCredentials(ServiceClient client) { + public AuthenticatePasswordCredentials(AuthenticationClient client) { this.client = client; } diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/EndpointToSupplierAdminURI.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/EndpointToSupplierAdminURI.java new file mode 100644 index 0000000000..2061a2dc11 --- /dev/null +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/EndpointToSupplierAdminURI.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.keystone.v2_0.functions; + +import com.google.inject.ImplementedBy; + +/** + * @author Adam Lowe + */ +@ImplementedBy(AdminURL.class) +public interface EndpointToSupplierAdminURI extends EndpointToSupplierURI { +} \ No newline at end of file diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/RegionToAdminEndpointURI.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/RegionToAdminEndpointURI.java new file mode 100644 index 0000000000..a98bf9d87f --- /dev/null +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/RegionToAdminEndpointURI.java @@ -0,0 +1,16 @@ +package org.jclouds.openstack.keystone.v2_0.functions; + +import javax.inject.Inject; + +import org.jclouds.location.functions.RegionToEndpoint; +import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToAdminURISupplier; + +/** + * @author Adam Lowe + */ +public class RegionToAdminEndpointURI extends RegionToEndpoint { + @Inject + public RegionToAdminEndpointURI(RegionIdToAdminURISupplier regionToEndpointSupplier) { + super(regionToEndpointSupplier); + } +} diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionSupplier.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionSupplier.java new file mode 100644 index 0000000000..74d15f5be0 --- /dev/null +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionSupplier.java @@ -0,0 +1,45 @@ +/** + * 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.keystone.v2_0.suppliers; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.openstack.keystone.v2_0.domain.Access; +import org.jclouds.openstack.keystone.v2_0.functions.EndpointToRegion; +import org.jclouds.openstack.keystone.v2_0.functions.EndpointToSupplierAdminURI; + +import com.google.common.base.Supplier; +import com.google.inject.assistedinject.Assisted; + +@Singleton +public class RegionIdToAdminURIFromAccessForTypeAndVersionSupplier extends + LocationIdToURIFromAccessForTypeAndVersionSupplier implements RegionIdToAdminURISupplier { + @Inject + public RegionIdToAdminURIFromAccessForTypeAndVersionSupplier(Supplier access, + EndpointToSupplierAdminURI endpointToSupplierURI, EndpointToRegion endpointToRegion, + @Assisted("apiType") String apiType, @Assisted("apiVersion") String apiVersion) { + super(access, endpointToSupplierURI, endpointToRegion, apiType, apiVersion); + } + + @Override + public String toString() { + return "regionIdToAdminURIFromAccessForTypeAndVersion(" + apiType + ", " + apiVersion + ")"; + } +} \ No newline at end of file diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURISupplier.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURISupplier.java new file mode 100644 index 0000000000..9f2b1c15b7 --- /dev/null +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURISupplier.java @@ -0,0 +1,28 @@ +package org.jclouds.openstack.keystone.v2_0.suppliers; + +import java.net.URI; +import java.util.Map; + +import com.google.common.base.Supplier; +import com.google.inject.ImplementedBy; +import com.google.inject.assistedinject.Assisted; + +/** + * @author Adam Lowe + */ +@ImplementedBy(RegionIdToAdminURIFromAccessForTypeAndVersionSupplier.class) +public interface RegionIdToAdminURISupplier extends Supplier>> { + static interface Factory { + /** + * + * @param apiType + * type of the api, according to the provider. ex. {@code compute} {@code + * object-store} + * @param apiVersion + * version of the api + * @return regions mapped to default uri + */ + RegionIdToAdminURISupplier createForApiTypeAndVersion(@Assisted("apiType") String apiType, + @Assisted("apiVersion") String apiVersion); + } +} 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 106150cb47..4d97aec0fd 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 @@ -41,4 +41,8 @@ public interface ServiceType { * Image Service (Glance) */ public static final String IMAGE = "image"; + /** + * Identity Service (Keystone) + */ + public static final String IDENTITY = "identity"; } \ No newline at end of file diff --git a/common/openstack/src/test/java/org/jclouds/openstack/keystone/v2_0/functions/AdminURLTest.java b/common/openstack/src/test/java/org/jclouds/openstack/keystone/v2_0/functions/AdminURLTest.java new file mode 100644 index 0000000000..33021208b7 --- /dev/null +++ b/common/openstack/src/test/java/org/jclouds/openstack/keystone/v2_0/functions/AdminURLTest.java @@ -0,0 +1,50 @@ +/** + * 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.keystone.v2_0.functions; + +import static org.testng.Assert.assertEquals; + +import java.net.URI; + +import org.jclouds.openstack.keystone.v2_0.domain.Endpoint; +import org.testng.annotations.Test; + +/** + * @author Adam Lowe + */ +@Test(groups = "unit", testName = "AdminURLTest") +public class AdminURLTest { + private final AdminURL fn = new AdminURL(); + + public void testAdminURL() { + assertEquals(fn.apply( + Endpoint.builder().region("LON").versionId("1.0").adminURL( + URI.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953")) + .build()).get(), URI + .create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953")); + } + + public void testPublicURLNullReturnsInternalURL() { + assertEquals(fn + .apply( + Endpoint.builder().region("lon").versionId("1.0") + .internalURL(URI.create("https://192.168.1.1")).build()).get(), null); + } + +} 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 bf7492dcf6..146a376533 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 @@ -67,11 +67,13 @@ public class ParseAccessTest extends BaseItemParserTest { Service.builder().name("Object Storage").type("object-store").endpoints( Endpoint.builder().tenantId("40806637803162").publicURL( URI.create("https://objects.jclouds.org/v1.0/40806637803162")) + .adminURL(URI.create("https://objects.jclouds.org/v1.0/")) .region("region-a.geo-1").versionId("1.0").build()).build(), Service.builder().name("Identity").type("identity").endpoints( - Endpoint.builder().publicURL(URI.create("https://csnode.jclouds.org/v2.0/")).region( - "region-a.geo-1").versionId("2.0").build()).build(), + Endpoint.builder().publicURL(URI.create("https://csnode.jclouds.org/v2.0/")) + .adminURL(URI.create("https://csnode.jclouds.org:35357/v2.0/")) + .region("region-a.geo-1").versionId("2.0").build()).build(), Service.builder().name("Image Management").type("image").endpoints( Endpoint.builder().tenantId("40806637803162").publicURL( diff --git a/common/openstack/src/test/java/org/jclouds/openstack/keystone/v2_0/parse/ParseApiMetadataTest.java b/common/openstack/src/test/java/org/jclouds/openstack/keystone/v2_0/parse/ParseApiMetadataTest.java new file mode 100644 index 0000000000..83718ee799 --- /dev/null +++ b/common/openstack/src/test/java/org/jclouds/openstack/keystone/v2_0/parse/ParseApiMetadataTest.java @@ -0,0 +1,70 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.openstack.keystone.v2_0.parse; + +import java.net.URI; + +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; + +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.json.BaseItemParserTest; +import org.jclouds.openstack.domain.Link; +import org.jclouds.openstack.keystone.v2_0.domain.Access; +import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata; +import org.jclouds.openstack.keystone.v2_0.domain.Endpoint; +import org.jclouds.openstack.keystone.v2_0.domain.Role; +import org.jclouds.openstack.keystone.v2_0.domain.Service; +import org.jclouds.openstack.keystone.v2_0.domain.Tenant; +import org.jclouds.openstack.keystone.v2_0.domain.Token; +import org.jclouds.openstack.keystone.v2_0.domain.User; +import org.jclouds.rest.annotations.SelectJson; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; + +/** + * @author Adam Lowe + */ +@Test(groups = "unit", testName = "ParseApiMetadataTest") +public class ParseApiMetadataTest extends BaseItemParserTest { + + @Override + public String resource() { + return "/apiMetadataResponse.json"; + } + + @Override + @SelectJson("version") + @Consumes(MediaType.APPLICATION_JSON) + public ApiMetadata expected() { + return ApiMetadata.builder().id("v2.0") + .links(ImmutableSet.of(Link.builder().relation(Link.Relation.SELF).href(URI.create("http://172.16.89.140:5000/v2.0/")).build(), + Link.builder().relation(Link.Relation.DESCRIBEDBY).type("text/html").href(URI.create("http://docs.openstack.org/api/openstack-identity-service/2.0/content/")).build(), + Link.builder().relation(Link.Relation.DESCRIBEDBY).type("application/pdf").href(URI.create("http://docs.openstack.org/api/openstack-identity-service/2.0/identity-dev-guide-2.0.pdf")).build() + )) + .status("beta") + .updated(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-11-19T00:00:00Z")) + .mediaTypes(ImmutableSet.of( + org.jclouds.openstack.keystone.v2_0.domain.MediaType.builder().base("application/json").type("application/vnd.openstack.identity-v2.0+json").build(), + org.jclouds.openstack.keystone.v2_0.domain.MediaType.builder().base("application/xml").type("application/vnd.openstack.identity-v2.0+xml").build() + )) + .build(); + } +} diff --git a/common/openstack/src/test/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionSupplierTest.java b/common/openstack/src/test/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionSupplierTest.java new file mode 100644 index 0000000000..de4453dccc --- /dev/null +++ b/common/openstack/src/test/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionSupplierTest.java @@ -0,0 +1,71 @@ +/** + * 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.keystone.v2_0.suppliers; + +import static org.testng.Assert.assertEquals; + +import java.net.URI; +import java.util.Map; + +import javax.inject.Singleton; + +import org.jclouds.openstack.keystone.v2_0.domain.Access; +import org.jclouds.openstack.keystone.v2_0.parse.ParseAccessTest; +import org.testng.annotations.Test; + +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Provides; +import com.google.inject.assistedinject.FactoryModuleBuilder; + +/** + * @author Adam Lowe + */ +@Test(groups = "unit", testName = "RegionIdToAdminURIFromAccessForTypeAndVersionSupplierTest") +public class RegionIdToAdminURIFromAccessForTypeAndVersionSupplierTest { + private final RegionIdToAdminURISupplier.Factory factory = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class, + RegionIdToAdminURIFromAccessForTypeAndVersionSupplier.class).build(RegionIdToAdminURISupplier.Factory.class)); + } + + @SuppressWarnings("unused") + @Provides + @Singleton + public Supplier provide() { + return Suppliers.ofInstance(new ParseAccessTest().expected()); + } + }).getInstance(RegionIdToAdminURISupplier.Factory.class); + + public void testRegionMatches() { + assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("identity", "2.0").get(), Suppliers + . supplierFunction()), ImmutableMap.of("region-a.geo-1", URI.create("https://csnode.jclouds.org:35357/v2.0/"))); + Map map = Maps.newLinkedHashMap(); + map.put("region-a.geo-1", null); + assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.1").get(), Suppliers + . supplierFunction()), map); + } + +} diff --git a/common/openstack/src/test/resources/apiMetadataResponse.json b/common/openstack/src/test/resources/apiMetadataResponse.json new file mode 100644 index 0000000000..09934299c9 --- /dev/null +++ b/common/openstack/src/test/resources/apiMetadataResponse.json @@ -0,0 +1 @@ +{"version": {"status": "beta", "updated": "2011-11-19T00:00:00Z", "media-types": [{"base": "application/json", "type": "application/vnd.openstack.identity-v2.0+json"}, {"base": "application/xml", "type": "application/vnd.openstack.identity-v2.0+xml"}], "id": "v2.0", "links": [{"href": "http://172.16.89.140:5000/v2.0/", "rel": "self"}, {"href": "http://docs.openstack.org/api/openstack-identity-service/2.0/content/", "type": "text/html", "rel": "describedby"}, {"href": "http://docs.openstack.org/api/openstack-identity-service/2.0/identity-dev-guide-2.0.pdf", "type": "application/pdf", "rel": "describedby"}]}} \ No newline at end of file diff --git a/common/openstack/src/test/resources/keystoneAuthResponse.json b/common/openstack/src/test/resources/keystoneAuthResponse.json index 4d872152f8..4751ca3d2b 100644 --- a/common/openstack/src/test/resources/keystoneAuthResponse.json +++ b/common/openstack/src/test/resources/keystoneAuthResponse.json @@ -56,9 +56,11 @@ "type": "identity", "endpoints": [ { + "adminURL": "https://csnode.jclouds.org:35357/v2.0/", "publicURL": "https://csnode.jclouds.org/v2.0/", "region": "region-a.geo-1", "id": "2.0", + "versionId":"2.0", "list": "https://csnode.jclouds.org/extension" } ] diff --git a/common/trmk/src/test/java/org/jclouds/trmk/vcloud_0_8/TerremarkClientLiveTest.java b/common/trmk/src/test/java/org/jclouds/trmk/vcloud_0_8/TerremarkClientLiveTest.java index f6308b9841..8cd5467115 100644 --- a/common/trmk/src/test/java/org/jclouds/trmk/vcloud_0_8/TerremarkClientLiveTest.java +++ b/common/trmk/src/test/java/org/jclouds/trmk/vcloud_0_8/TerremarkClientLiveTest.java @@ -32,9 +32,9 @@ import java.io.IOException; import java.net.URI; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Properties; import java.util.Set; -import java.util.Map.Entry; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -43,14 +43,13 @@ import org.jclouds.cim.CIMPredicates; import org.jclouds.cim.ResourceAllocationSettingData; import org.jclouds.cim.ResourceAllocationSettingData.ResourceType; import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.predicates.SocketOpen; import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.RestContext; import org.jclouds.ssh.SshClient; -import org.jclouds.ssh.SshException; import org.jclouds.ssh.SshClient.Factory; +import org.jclouds.ssh.SshException; import org.jclouds.trmk.vcloud_0_8.domain.Catalog; import org.jclouds.trmk.vcloud_0_8.domain.CatalogItem; import org.jclouds.trmk.vcloud_0_8.domain.CustomizationParameters; @@ -80,6 +79,7 @@ import com.google.common.base.Function; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; +import com.google.common.net.HostAndPort; import com.google.inject.Injector; @Test(groups = "live", singleThreaded = true) @@ -93,7 +93,7 @@ public abstract class TerremarkClientLiveTest socketTester; + protected RetryablePredicate socketTester; protected RetryablePredicate successTester; protected Injector injector; @@ -107,7 +107,7 @@ public abstract class TerremarkClientLiveTest(injector.getInstance(SocketOpen.class), 300, 10, TimeUnit.SECONDS);// make + socketTester = new RetryablePredicate(injector.getInstance(SocketOpen.class), 300, 10, TimeUnit.SECONDS);// make // it // longer // then diff --git a/common/trmk/src/test/java/org/jclouds/trmk/vcloud_0_8/internal/BaseTerremarkClientLiveTest.java b/common/trmk/src/test/java/org/jclouds/trmk/vcloud_0_8/internal/BaseTerremarkClientLiveTest.java index 2d16b21584..a7ff954ad1 100644 --- a/common/trmk/src/test/java/org/jclouds/trmk/vcloud_0_8/internal/BaseTerremarkClientLiveTest.java +++ b/common/trmk/src/test/java/org/jclouds/trmk/vcloud_0_8/internal/BaseTerremarkClientLiveTest.java @@ -22,7 +22,6 @@ import java.util.concurrent.TimeUnit; import org.jclouds.compute.ComputeService; import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.InetSocketAddressConnect; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.rest.RestContext; @@ -33,6 +32,7 @@ import org.jclouds.trmk.vcloud_0_8.TerremarkVCloudClient; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import com.google.common.net.HostAndPort; import com.google.inject.Injector; import com.google.inject.Module; @@ -51,7 +51,7 @@ public abstract class BaseTerremarkClientLiveTest socketTester; + protected RetryablePredicate socketTester; protected Factory sshFactory; protected S connection; @@ -61,7 +61,7 @@ public abstract class BaseTerremarkClientLiveTest(new InetSocketAddressConnect(), 300, 1, TimeUnit.SECONDS); + socketTester = new RetryablePredicate(new InetSocketAddressConnect(), 300, 1, TimeUnit.SECONDS); sshFactory = injector.getInstance(Factory.class); connection = (S) RestContext.class.cast(view.unwrap()).getApi(); } diff --git a/compute/src/main/java/org/jclouds/compute/functions/CreateSshClientOncePortIsListeningOnNode.java b/compute/src/main/java/org/jclouds/compute/functions/CreateSshClientOncePortIsListeningOnNode.java index d4d779c0ad..90a5b23c8e 100644 --- a/compute/src/main/java/org/jclouds/compute/functions/CreateSshClientOncePortIsListeningOnNode.java +++ b/compute/src/main/java/org/jclouds/compute/functions/CreateSshClientOncePortIsListeningOnNode.java @@ -26,10 +26,10 @@ import javax.inject.Singleton; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.predicates.RetryIfSocketNotYetOpen; import org.jclouds.compute.util.ComputeServiceUtils; -import org.jclouds.net.IPSocket; import org.jclouds.ssh.SshClient; import com.google.common.base.Function; +import com.google.common.net.HostAndPort; import com.google.inject.Inject; /** @@ -55,7 +55,7 @@ public class CreateSshClientOncePortIsListeningOnNode implements Function { +public class RetryIfSocketNotYetOpen implements Predicate { @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) private Logger logger = Logger.NULL; @@ -84,11 +84,11 @@ public class RetryIfSocketNotYetOpen implements Predicate { } @Override - public boolean apply(IPSocket socket) { + public boolean apply(HostAndPort socket) { logger.debug(">> blocking on socket %s for %d %s", socket, timeoutValue, timeoutUnits); // Specify a retry period of 1s, expressed in the same time units. long period = timeoutUnits.convert(1, TimeUnit.SECONDS); - RetryablePredicate tester = new RetryablePredicate(socketTester, timeoutValue, period, timeoutUnits); + RetryablePredicate tester = new RetryablePredicate(socketTester, timeoutValue, period, timeoutUnits); boolean passed = tester.apply(socket); if (passed) logger.debug("<< socket %s opened", socket); diff --git a/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceDependenciesModule.java b/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceDependenciesModule.java index 98bde50baf..4ec374c9d7 100644 --- a/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceDependenciesModule.java +++ b/compute/src/main/java/org/jclouds/compute/stub/config/StubComputeServiceDependenciesModule.java @@ -33,7 +33,6 @@ import org.jclouds.compute.domain.NodeState; import org.jclouds.compute.domain.Processor; import org.jclouds.compute.domain.Volume; import org.jclouds.compute.domain.internal.VolumeImpl; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.SocketOpen; import org.jclouds.rest.annotations.Identity; @@ -41,6 +40,7 @@ import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableList; +import com.google.common.net.HostAndPort; import com.google.inject.AbstractModule; import com.google.inject.Provides; @@ -128,10 +128,10 @@ public class StubComputeServiceDependenciesModule extends AbstractModule { } @Override - public boolean apply(IPSocket input) { - if (input.getAddress().indexOf(publicIpPrefix) == -1) + public boolean apply(HostAndPort input) { + if (input.getHostText().indexOf(publicIpPrefix) == -1) return false; - String id = input.getAddress().replace(publicIpPrefix, ""); + String id = input.getHostText().replace(publicIpPrefix, ""); NodeMetadata node = nodes.get(id); return node != null && node.getState() == NodeState.RUNNING; } diff --git a/compute/src/main/java/org/jclouds/compute/util/ComputeServiceUtils.java b/compute/src/main/java/org/jclouds/compute/util/ComputeServiceUtils.java index 34e73036a0..ff149ab778 100644 --- a/compute/src/main/java/org/jclouds/compute/util/ComputeServiceUtils.java +++ b/compute/src/main/java/org/jclouds/compute/util/ComputeServiceUtils.java @@ -30,8 +30,8 @@ import static org.jclouds.scriptbuilder.domain.Statements.pipeHttpResponseToBash import java.net.URI; import java.util.Formatter; import java.util.Map; -import java.util.NoSuchElementException; import java.util.Map.Entry; +import java.util.NoSuchElementException; import java.util.regex.Pattern; import org.jclouds.compute.ComputeServiceContext; @@ -43,13 +43,13 @@ import org.jclouds.compute.domain.Processor; import org.jclouds.compute.domain.Volume; import org.jclouds.compute.predicates.RetryIfSocketNotYetOpen; import org.jclouds.http.HttpRequest; -import org.jclouds.net.IPSocket; import org.jclouds.scriptbuilder.domain.Statement; import org.jclouds.scriptbuilder.domain.Statements; import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; +import com.google.common.net.HostAndPort; import com.google.common.reflect.TypeToken; /** @@ -165,17 +165,17 @@ public class ComputeServiceUtils { return org.jclouds.rest.Providers.getSupportedProvidersOfType(TypeToken.of(ComputeServiceContext.class)); } - public static IPSocket findReachableSocketOnNode(RetryIfSocketNotYetOpen socketTester, final NodeMetadata node, + public static HostAndPort findReachableSocketOnNode(RetryIfSocketNotYetOpen socketTester, final NodeMetadata node, final int port) { checkNodeHasIps(node); - IPSocket socket = null; + HostAndPort socket = null; try { socket = find(transform(concat(node.getPublicAddresses(), node.getPrivateAddresses()), - new Function() { + new Function() { @Override - public IPSocket apply(String from) { - return new IPSocket(from, port); + public HostAndPort apply(String from) { + return HostAndPort.fromParts(from, port); } }), socketTester); } catch (NoSuchElementException e) { diff --git a/compute/src/main/java/org/jclouds/ssh/SshClient.java b/compute/src/main/java/org/jclouds/ssh/SshClient.java index 33c1c7331e..4e9160b704 100644 --- a/compute/src/main/java/org/jclouds/ssh/SshClient.java +++ b/compute/src/main/java/org/jclouds/ssh/SshClient.java @@ -23,7 +23,8 @@ import org.jclouds.compute.domain.ExecResponse; import org.jclouds.domain.Credentials; import org.jclouds.domain.LoginCredentials; import org.jclouds.io.Payload; -import org.jclouds.net.IPSocket; + +import com.google.common.net.HostAndPort; /** * @author Adrian Cole @@ -35,12 +36,12 @@ public interface SshClient { /** * To be removed in jclouds 1.5.0 * - * @see #create(IPSocket, LoginCredentials) + * @see #create(com.google.common.net.HostAndPort, LoginCredentials) */ @Deprecated - SshClient create(IPSocket socket, Credentials credentials); + SshClient create(HostAndPort socket, Credentials credentials); - SshClient create(IPSocket socket, LoginCredentials credentials); + SshClient create(HostAndPort socket, LoginCredentials credentials); } diff --git a/compute/src/test/clojure/org/jclouds/ssh_test.clj b/compute/src/test/clojure/org/jclouds/ssh_test.clj index d6ea701351..54b001cf97 100644 --- a/compute/src/test/clojure/org/jclouds/ssh_test.clj +++ b/compute/src/test/clojure/org/jclouds/ssh_test.clj @@ -25,7 +25,7 @@ org.jclouds.domain.Credentials org.jclouds.domain.LoginCredentials org.jclouds.io.Payload - org.jclouds.net.IPSocket + com.google.common.net.HostAndPort org.jclouds.compute.domain.ExecResponse)) (defn instantiate [impl-class & args] @@ -67,7 +67,7 @@ (^void put [this ^String path ^String content]) (^void put [this ^String path ^org.jclouds.io.Payload content]) (getUsername [this] username) - (getHostAddress [this] (.getAddress socket)) ) + (getHostAddress [this] (.getHostText socket)) ) (defn no-op-ssh-client [socket username password] @@ -79,11 +79,11 @@ org.jclouds.ssh.SshClient$Factory (^org.jclouds.ssh.SshClient create - [_ ^IPSocket socket ^Credentials credentials] + [_ ^HostAndPort socket ^Credentials credentials] (factory-fn socket (.identity credentials) (.credential credentials))) (^org.jclouds.ssh.SshClient create - [_ ^IPSocket socket ^LoginCredentials credentials] + [_ ^HostAndPort socket ^LoginCredentials credentials] (factory-fn socket (.identity credentials) (.credential credentials))) ) diff --git a/compute/src/test/java/org/jclouds/compute/StubComputeServiceIntegrationTest.java b/compute/src/test/java/org/jclouds/compute/StubComputeServiceIntegrationTest.java index de65693865..0c94f6374e 100644 --- a/compute/src/test/java/org/jclouds/compute/StubComputeServiceIntegrationTest.java +++ b/compute/src/test/java/org/jclouds/compute/StubComputeServiceIntegrationTest.java @@ -39,7 +39,6 @@ import org.jclouds.compute.internal.BaseComputeServiceLiveTest; import org.jclouds.crypto.Pems; import org.jclouds.domain.LoginCredentials; import org.jclouds.io.Payload; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.predicates.SocketOpen; import org.jclouds.rest.AuthorizationException; @@ -54,6 +53,7 @@ import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.base.Throwables; import com.google.common.collect.ImmutableMap; +import com.google.common.net.HostAndPort; import com.google.inject.AbstractModule; import com.google.inject.Module; @@ -80,13 +80,13 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes protected void buildSocketTester() { SocketOpen socketOpen = createMock(SocketOpen.class); - expect(socketOpen.apply(new IPSocket("144.175.1.1", 22))).andReturn(true).times(5); + expect(socketOpen.apply(HostAndPort.fromParts("144.175.1.1", 22))).andReturn(true).times(5); // restart of jboss - expect(socketOpen.apply(new IPSocket("144.175.1.1", 8080))).andReturn(true).times(2); + expect(socketOpen.apply(HostAndPort.fromParts("144.175.1.1", 8080))).andReturn(true).times(2); replay(socketOpen); - preciseSocketTester = socketTester = new RetryablePredicate(socketOpen, 1, 1, TimeUnit.MILLISECONDS); + preciseSocketTester = socketTester = new RetryablePredicate(socketOpen, 1, 1, TimeUnit.MILLISECONDS); } @Override @@ -140,26 +140,26 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes SshClient client5 = createMock(SshClient.class); expect( - factory.create(new IPSocket("144.175.1.1", 22), + factory.create(HostAndPort.fromParts("144.175.1.1", 22), LoginCredentials.builder().user("root").password("password1").build())).andReturn(client1); expect( - factory.create(new IPSocket("144.175.1.1", 22), + factory.create(HostAndPort.fromParts("144.175.1.1", 22), LoginCredentials.builder().user("web").privateKey(Pems.PRIVATE_PKCS1_MARKER).build())).andReturn(client1New) .times(10); runScriptAndService(client1, client1New); expect( - factory.create(new IPSocket("144.175.1.2", 22), + factory.create(HostAndPort.fromParts("144.175.1.2", 22), LoginCredentials.builder().user("root").password("password2").build())).andReturn(client2) .times(4); expect( - factory.create(new IPSocket("144.175.1.2", 22), + factory.create(HostAndPort.fromParts("144.175.1.2", 22), LoginCredentials.builder().user("root").password("password2").build())).andReturn(client2New); expect( - factory.create(new IPSocket("144.175.1.2", 22), + factory.create(HostAndPort.fromParts("144.175.1.2", 22), LoginCredentials.builder().user("foo").privateKey(Pems.PRIVATE_PKCS1_MARKER).build())).andReturn(client2Foo); expect( - factory.create(new IPSocket("144.175.1.2", 22), + factory.create(HostAndPort.fromParts("144.175.1.2", 22), LoginCredentials.builder().user("root").password("romeo").build())).andThrow( new AuthorizationException("Auth fail", null)); @@ -200,15 +200,15 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes client2Foo.disconnect(); expect( - factory.create(new IPSocket("144.175.1.3", 22), + factory.create(HostAndPort.fromParts("144.175.1.3", 22), LoginCredentials.builder().user("root").password("password3").build())).andReturn(client3) .times(2); expect( - factory.create(new IPSocket("144.175.1.4", 22), + factory.create(HostAndPort.fromParts("144.175.1.4", 22), LoginCredentials.builder().user("root").password("password4").build())).andReturn(client4) .times(2); expect( - factory.create(new IPSocket("144.175.1.5", 22), + factory.create(HostAndPort.fromParts("144.175.1.5", 22), LoginCredentials.builder().user("root").password("password5").build())).andReturn(client5) .times(2); @@ -217,23 +217,23 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes runScriptAndInstallSsh(client5, "bootstrap", 5); expect( - factory.create(eq(new IPSocket("144.175.1.1", 22)), + factory.create(eq(HostAndPort.fromParts("144.175.1.1", 22)), eq(LoginCredentials.builder().user("defaultAdminUsername").privateKey(Pems.PRIVATE_PKCS1_MARKER).build()))) .andReturn(client1); expect( - factory.create(eq(new IPSocket("144.175.1.2", 22)), + factory.create(eq(HostAndPort.fromParts("144.175.1.2", 22)), eq(LoginCredentials.builder().user("defaultAdminUsername").privateKey(Pems.PRIVATE_PKCS1_MARKER).build()))) .andReturn(client2); expect( - factory.create(eq(new IPSocket("144.175.1.3", 22)), + factory.create(eq(HostAndPort.fromParts("144.175.1.3", 22)), eq(LoginCredentials.builder().user("defaultAdminUsername").privateKey(Pems.PRIVATE_PKCS1_MARKER).build()))) .andReturn(client3); expect( - factory.create(eq(new IPSocket("144.175.1.4", 22)), + factory.create(eq(HostAndPort.fromParts("144.175.1.4", 22)), eq(LoginCredentials.builder().user("defaultAdminUsername").privateKey(Pems.PRIVATE_PKCS1_MARKER).build()))) .andReturn(client4); expect( - factory.create(eq(new IPSocket("144.175.1.5", 22)), + factory.create(eq(HostAndPort.fromParts("144.175.1.5", 22)), eq(LoginCredentials.builder().user("defaultAdminUsername").privateKey(Pems.PRIVATE_PKCS1_MARKER).build()))) .andReturn(client5); diff --git a/compute/src/test/java/org/jclouds/compute/internal/BaseComputeServiceLiveTest.java b/compute/src/test/java/org/jclouds/compute/internal/BaseComputeServiceLiveTest.java index 33fa6243d6..f5202b32f4 100644 --- a/compute/src/test/java/org/jclouds/compute/internal/BaseComputeServiceLiveTest.java +++ b/compute/src/test/java/org/jclouds/compute/internal/BaseComputeServiceLiveTest.java @@ -50,10 +50,10 @@ import static org.testng.Assert.assertNotNull; import java.io.IOException; import java.util.Collection; import java.util.Map; +import java.util.Map.Entry; import java.util.NoSuchElementException; import java.util.Set; import java.util.SortedSet; -import java.util.Map.Entry; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; @@ -84,7 +84,6 @@ import org.jclouds.domain.Credentials; import org.jclouds.domain.Location; import org.jclouds.domain.LocationScope; import org.jclouds.domain.LoginCredentials; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.predicates.SocketOpen; import org.jclouds.rest.AuthorizationException; @@ -105,6 +104,7 @@ import com.google.common.base.Stopwatch; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; +import com.google.common.net.HostAndPort; import com.google.common.util.concurrent.ListenableFuture; import com.google.inject.Module; @@ -117,8 +117,8 @@ public abstract class BaseComputeServiceLiveTest extends BaseComputeServiceConte protected String group; - protected Predicate socketTester; - protected Predicate preciseSocketTester; + protected Predicate socketTester; + protected Predicate preciseSocketTester; protected SortedSet nodes; protected ComputeService client; @@ -151,12 +151,12 @@ public abstract class BaseComputeServiceLiveTest extends BaseComputeServiceConte protected void buildSocketTester() { SocketOpen socketOpen = view.utils().injector().getInstance(SocketOpen.class); - socketTester = new RetryablePredicate(socketOpen, 60, 1, TimeUnit.SECONDS); + socketTester = new RetryablePredicate(socketOpen, 60, 1, TimeUnit.SECONDS); // wait a maximum of 60 seconds for port 8080 to open. long maxWait = TimeUnit.SECONDS.toMillis(60); long interval = 50; // get more precise than default socket tester - preciseSocketTester = new RetryablePredicate(socketOpen, maxWait, interval, interval, + preciseSocketTester = new RetryablePredicate(socketOpen, maxWait, interval, interval, TimeUnit.MILLISECONDS); } @Override @@ -579,7 +579,7 @@ public abstract class BaseComputeServiceLiveTest extends BaseComputeServiceConte stats.backgroundProcessMilliseconds = watch.elapsedTime(TimeUnit.MILLISECONDS); watch.reset().start(); - IPSocket socket = new IPSocket(Iterables.get(node.getPublicAddresses(), 0), 8080); + HostAndPort socket = HostAndPort.fromParts(Iterables.get(node.getPublicAddresses(), 0), 8080); assert preciseSocketTester.apply(socket) : String.format("failed to open socket %s on node %s:%n%s%s", socket, node, init(node, processName, "stdout"), init(node, processName, "stderr")); stats.socketOpenMilliseconds = watch.elapsedTime(TimeUnit.MILLISECONDS); diff --git a/compute/src/test/java/org/jclouds/compute/predicates/RetryIfSocketNotYetOpenTest.java b/compute/src/test/java/org/jclouds/compute/predicates/RetryIfSocketNotYetOpenTest.java index 1b2f859b3c..c3a24721f0 100644 --- a/compute/src/test/java/org/jclouds/compute/predicates/RetryIfSocketNotYetOpenTest.java +++ b/compute/src/test/java/org/jclouds/compute/predicates/RetryIfSocketNotYetOpenTest.java @@ -26,9 +26,10 @@ import java.util.concurrent.TimeUnit; import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts; import org.jclouds.logging.Logger; -import org.jclouds.net.IPSocket; import org.testng.annotations.Test; +import com.google.common.net.HostAndPort; + /** * Tests timeout behavior of {@link RetryIfSocketNotYetOpen} predicate. @@ -36,7 +37,7 @@ import org.testng.annotations.Test; public class RetryIfSocketNotYetOpenTest { private static final Logger logger = Logger.NULL; - private static final IPSocket socket = new IPSocket("dummy", 0); + private static final HostAndPort socket = HostAndPort.fromParts("dummy", 0); @Test public void fromConstructor() { @@ -70,7 +71,7 @@ public class RetryIfSocketNotYetOpenTest { doAsserts(uninitialised, socket, false, 0, 500); } - private void doAsserts(RetryIfSocketNotYetOpen predicate, IPSocket socket, boolean expectedResult, long minMilliseconds, long maxMilliseconds) { + private void doAsserts(RetryIfSocketNotYetOpen predicate, HostAndPort socket, boolean expectedResult, long minMilliseconds, long maxMilliseconds) { long startTime = System.currentTimeMillis(); boolean result = predicate.apply(socket); long elapsedTime = System.currentTimeMillis() - startTime; diff --git a/compute/src/test/java/org/jclouds/compute/predicates/SocketOpenPredicates.java b/compute/src/test/java/org/jclouds/compute/predicates/SocketOpenPredicates.java index 12efc695ff..86ddbef963 100644 --- a/compute/src/test/java/org/jclouds/compute/predicates/SocketOpenPredicates.java +++ b/compute/src/test/java/org/jclouds/compute/predicates/SocketOpenPredicates.java @@ -18,9 +18,10 @@ */ package org.jclouds.compute.predicates; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.SocketOpen; +import com.google.common.net.HostAndPort; + /** * For use in unit tests, e.g. {@link RetryIfSocketNotYetOpenTest}. @@ -28,11 +29,11 @@ import org.jclouds.predicates.SocketOpen; public class SocketOpenPredicates { public static final SocketOpen alwaysSucceed = new SocketOpen() { - @Override public boolean apply(IPSocket socket) { return true; } + @Override public boolean apply(HostAndPort socket) { return true; } }; public static final SocketOpen alwaysFail = new SocketOpen() { - @Override public boolean apply(IPSocket socket) { return false; } + @Override public boolean apply(HostAndPort socket) { return false; } }; } diff --git a/core/pom.xml b/core/pom.xml index b63f5e978e..566d4f1cdc 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -99,7 +99,7 @@ com.google.guava guava - 12.0-rc2 + 12.0 diff --git a/core/src/main/java/org/jclouds/crypto/Sha512Crypt.java b/core/src/main/java/org/jclouds/crypto/Sha512Crypt.java index e5e6db3c9e..f772861c94 100644 --- a/core/src/main/java/org/jclouds/crypto/Sha512Crypt.java +++ b/core/src/main/java/org/jclouds/crypto/Sha512Crypt.java @@ -160,7 +160,7 @@ public class Sha512Crypt { byte[] s_bytes = null; int cnt, cnt2; int rounds = ROUNDS_DEFAULT; // Default number of rounds. - StringBuffer buffer; + StringBuilder buffer; /* -- */ @@ -181,7 +181,7 @@ public class Sha512Crypt { } } else { java.util.Random randgen = new java.util.Random(); - StringBuffer saltBuf = new StringBuffer(); + StringBuilder saltBuf = new StringBuilder(); while (saltBuf.length() < 16) { int index = (int) (randgen.nextFloat() * SALTCHARS.length()); @@ -286,7 +286,7 @@ public class Sha512Crypt { alt_result = ctx.digest(); } - buffer = new StringBuffer(sha512_salt_prefix); + buffer = new StringBuilder(sha512_salt_prefix); if (rounds != 5000) { buffer.append(sha512_rounds_prefix); @@ -333,7 +333,7 @@ public class Sha512Crypt { private static final String b64_from_24bit(byte B2, byte B1, byte B0, int size) { int v = ((((int) B2) & 0xFF) << 16) | ((((int) B1) & 0xFF) << 8) | ((int) B0 & 0xff); - StringBuffer result = new StringBuffer(); + StringBuilder result = new StringBuilder(); while (--size >= 0) { result.append(itoa64.charAt((int) (v & 0x3f))); diff --git a/core/src/main/java/org/jclouds/http/HttpUtils.java b/core/src/main/java/org/jclouds/http/HttpUtils.java index 0ee0dd24cb..d9a1daf16a 100644 --- a/core/src/main/java/org/jclouds/http/HttpUtils.java +++ b/core/src/main/java/org/jclouds/http/HttpUtils.java @@ -353,7 +353,7 @@ public class HttpUtils { } public static String sortAndConcatHeadersIntoString(Multimap headers) { - StringBuffer buffer = new StringBuffer(); + StringBuilder buffer = new StringBuilder(); SortedSetMultimap sortedMap = TreeMultimap.create(); sortedMap.putAll(headers); for (Entry header : sortedMap.entries()) { diff --git a/core/src/main/java/org/jclouds/http/functions/ParseXMLWithJAXB.java b/core/src/main/java/org/jclouds/http/functions/ParseXMLWithJAXB.java index 2ed2f23c67..cbbadb2c16 100644 --- a/core/src/main/java/org/jclouds/http/functions/ParseXMLWithJAXB.java +++ b/core/src/main/java/org/jclouds/http/functions/ParseXMLWithJAXB.java @@ -72,7 +72,7 @@ public class ParseXMLWithJAXB implements Function { try { return apply(xml); } catch (Exception e) { - StringBuffer message = new StringBuffer(); + StringBuilder message = new StringBuilder(); message.append("Error parsing input"); logger.error(e, message.toString()); throw new HttpResponseException(message.toString() + "\n" + from, null, from, e); diff --git a/core/src/main/java/org/jclouds/predicates/InetSocketAddressConnect.java b/core/src/main/java/org/jclouds/predicates/InetSocketAddressConnect.java index 2ef0814fe8..de95e5c2ff 100644 --- a/core/src/main/java/org/jclouds/predicates/InetSocketAddressConnect.java +++ b/core/src/main/java/org/jclouds/predicates/InetSocketAddressConnect.java @@ -27,8 +27,8 @@ import javax.inject.Named; import javax.inject.Singleton; import org.jclouds.logging.Logger; -import org.jclouds.net.IPSocket; +import com.google.common.net.HostAndPort; import com.google.inject.Inject; /** @@ -48,8 +48,8 @@ public class InetSocketAddressConnect implements SocketOpen { private int timeout = 2000; @Override - public boolean apply(IPSocket socketA) { - InetSocketAddress socketAddress = new InetSocketAddress(socketA.getAddress(), socketA + public boolean apply(HostAndPort socketA) { + InetSocketAddress socketAddress = new InetSocketAddress(socketA.getHostText(), socketA .getPort()); Socket socket = null; try { diff --git a/core/src/main/java/org/jclouds/predicates/SocketOpen.java b/core/src/main/java/org/jclouds/predicates/SocketOpen.java index 23ade2d919..b3b380fdb4 100644 --- a/core/src/main/java/org/jclouds/predicates/SocketOpen.java +++ b/core/src/main/java/org/jclouds/predicates/SocketOpen.java @@ -18,9 +18,8 @@ */ package org.jclouds.predicates; -import org.jclouds.net.IPSocket; - import com.google.common.base.Predicate; +import com.google.common.net.HostAndPort; import com.google.inject.ImplementedBy; /** @@ -30,6 +29,6 @@ import com.google.inject.ImplementedBy; * @author Adrian Cole */ @ImplementedBy(SocketOpenUnsupported.class) -public interface SocketOpen extends Predicate { +public interface SocketOpen extends Predicate { } diff --git a/core/src/main/java/org/jclouds/predicates/SocketOpenUnsupported.java b/core/src/main/java/org/jclouds/predicates/SocketOpenUnsupported.java index 0223535223..074d0a1e85 100644 --- a/core/src/main/java/org/jclouds/predicates/SocketOpenUnsupported.java +++ b/core/src/main/java/org/jclouds/predicates/SocketOpenUnsupported.java @@ -20,7 +20,7 @@ package org.jclouds.predicates; import javax.inject.Singleton; -import org.jclouds.net.IPSocket; +import com.google.common.net.HostAndPort; /** * @@ -31,7 +31,7 @@ import org.jclouds.net.IPSocket; public class SocketOpenUnsupported implements SocketOpen { @Override - public boolean apply(IPSocket socketA) { + public boolean apply(HostAndPort socketA) { throw new UnsupportedOperationException("socket testing not configured"); } diff --git a/core/src/main/java/org/jclouds/util/PasswordGenerator.java b/core/src/main/java/org/jclouds/util/PasswordGenerator.java index a980fe0213..0de64099ec 100644 --- a/core/src/main/java/org/jclouds/util/PasswordGenerator.java +++ b/core/src/main/java/org/jclouds/util/PasswordGenerator.java @@ -51,10 +51,10 @@ public enum PasswordGenerator implements Supplier { @Override public String get() { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); for (int i = 0; i < MIN_LENGTH; i++) { sb.append(goodChar[r.nextInt(goodChar.length)]); } return sb.toString(); } -} \ No newline at end of file +} diff --git a/core/src/test/java/org/jclouds/http/BaseJettyTest.java b/core/src/test/java/org/jclouds/http/BaseJettyTest.java index efff2057df..68055e507a 100644 --- a/core/src/test/java/org/jclouds/http/BaseJettyTest.java +++ b/core/src/test/java/org/jclouds/http/BaseJettyTest.java @@ -175,7 +175,7 @@ public abstract class BaseJettyTest { client = context.getApi(); assert client != null; - assert client.newStringBuffer() != null; + assert client.newStringBuilder() != null; } private static void handlePost(HttpServletRequest request, HttpServletResponse response) throws IOException { diff --git a/core/src/test/java/org/jclouds/http/IntegrationTestAsyncClient.java b/core/src/test/java/org/jclouds/http/IntegrationTestAsyncClient.java index 694c298aab..74eec0ca6a 100644 --- a/core/src/test/java/org/jclouds/http/IntegrationTestAsyncClient.java +++ b/core/src/test/java/org/jclouds/http/IntegrationTestAsyncClient.java @@ -202,6 +202,6 @@ public interface IntegrationTestAsyncClient { } @Provides - StringBuffer newStringBuffer(); + StringBuilder newStringBuilder(); } diff --git a/core/src/test/java/org/jclouds/http/IntegrationTestClient.java b/core/src/test/java/org/jclouds/http/IntegrationTestClient.java index 8207e1055b..a1b97fba08 100644 --- a/core/src/test/java/org/jclouds/http/IntegrationTestClient.java +++ b/core/src/test/java/org/jclouds/http/IntegrationTestClient.java @@ -68,5 +68,5 @@ public interface IntegrationTestClient { String downloadAndParse(String id); @Provides - StringBuffer newStringBuffer(); + StringBuilder newStringBuilder(); } diff --git a/core/src/test/java/org/jclouds/http/internal/WireLiveTest.java b/core/src/test/java/org/jclouds/http/internal/WireLiveTest.java index b4bc891884..68db3c5465 100644 --- a/core/src/test/java/org/jclouds/http/internal/WireLiveTest.java +++ b/core/src/test/java/org/jclouds/http/internal/WireLiveTest.java @@ -68,7 +68,7 @@ public class WireLiveTest { } static class BufferLogger implements Logger { - StringBuffer buff = new StringBuffer(); + StringBuilder buff = new StringBuilder(); public void debug(String message, Object... args) { buff.append(message); diff --git a/core/src/test/java/org/jclouds/http/internal/WireTest.java b/core/src/test/java/org/jclouds/http/internal/WireTest.java index c5119fd582..d50ec08176 100644 --- a/core/src/test/java/org/jclouds/http/internal/WireTest.java +++ b/core/src/test/java/org/jclouds/http/internal/WireTest.java @@ -35,7 +35,7 @@ import org.testng.annotations.Test; public class WireTest { class BufferLogger implements Logger { - StringBuffer buff = new StringBuffer(); + StringBuilder buff = new StringBuilder(); public void debug(String message, Object... args) { buff.append(message); diff --git a/core/src/test/java/org/jclouds/rest/internal/BaseRestClientExpectTest.java b/core/src/test/java/org/jclouds/rest/internal/BaseRestClientExpectTest.java index 8e77a564be..f4ab26c2c8 100644 --- a/core/src/test/java/org/jclouds/rest/internal/BaseRestClientExpectTest.java +++ b/core/src/test/java/org/jclouds/rest/internal/BaseRestClientExpectTest.java @@ -367,12 +367,15 @@ public abstract class BaseRestClientExpectTest { */ public boolean httpRequestsAreEqual(HttpRequest a, HttpRequest b) { try { + if (a == null || b == null) { + return false; + } + if (a.getPayload() == null || b.getPayload() == null) { + return Objects.equal(a, b); + } + switch (compareHttpRequestAsType(a)) { case XML: { - if (a == null || b == null || a.getPayload() == null || b.getPayload() == null) { - return false; - } - Diff diff = XMLUnit.compareXML(Strings2.toStringAndClose(a.getPayload().getInput()), Strings2 .toStringAndClose(b.getPayload().getInput())); @@ -404,10 +407,7 @@ public abstract class BaseRestClientExpectTest { return diff.identical() && Objects.equal(a.getHeaders(), b.getHeaders()); } - case JSON: { - if (a == null || b == null || a.getPayload() == null || b.getPayload() == null) { - return false; - } + case JSON: { JsonParser parser = new JsonParser(); JsonElement payloadA = parser.parse(Strings2.toStringAndClose(a.getPayload().getInput())); JsonElement payloadB = parser.parse(Strings2.toStringAndClose(b.getPayload().getInput())); 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 f4a5b6439d..4d182e223b 100644 --- a/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java +++ b/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java @@ -2474,7 +2474,7 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest { Function parser = (Function) RestAnnotationProcessor .createResponseParser(parserFactory, injector, method, request); - StringBuffer payload = new StringBuffer(XMLParser.DEFAULT_XML_HEADER); + StringBuilder payload = new StringBuilder(XMLParser.DEFAULT_XML_HEADER); payload.append("Hello World"); TestJAXBDomain domain = parser.apply(new HttpResponse(200, "ok", newStringPayload(payload.toString()))); assertEquals(domain.getElem(), "Hello World"); @@ -2492,7 +2492,7 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest { Function parser = (Function) RestAnnotationProcessor .createResponseParser(parserFactory, injector, method, request); - StringBuffer payload = new StringBuffer(XMLParser.DEFAULT_XML_HEADER); + StringBuilder payload = new StringBuilder(XMLParser.DEFAULT_XML_HEADER); payload.append("Hello World"); TestJAXBDomain domain = parser.apply(new HttpResponse(200, "ok", newStringPayload(payload.toString()))); assertEquals(domain.getElem(), "Hello World"); diff --git a/demos/tweetstore/cf-tweetstore-spring/pom.xml b/demos/tweetstore/cf-tweetstore-spring/pom.xml index 657c2a972b..df33d6288f 100644 --- a/demos/tweetstore/cf-tweetstore-spring/pom.xml +++ b/demos/tweetstore/cf-tweetstore-spring/pom.xml @@ -46,6 +46,13 @@ org.springframework spring-context 3.0.5.RELEASE + + + + commons-logging + commons-logging + + org.springframework diff --git a/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/paas/config/HttpClientModule.java b/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/paas/config/HttpClientModule.java new file mode 100644 index 0000000000..5aa077b6cd --- /dev/null +++ b/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/paas/config/HttpClientModule.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.demo.paas.config; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.inject.name.Names.bindProperties; +import static org.jclouds.Constants.*; + +import java.util.Properties; + +import javax.servlet.ServletContext; +import javax.ws.rs.core.UriBuilder; + +import org.jclouds.demo.tweetstore.config.util.PropertiesLoader; + +import com.google.inject.AbstractModule; +import com.sun.jersey.api.uri.UriBuilderImpl; + +/** + * @author Andrew Phillips + */ +public class HttpClientModule extends AbstractModule { + private final ServletContext context; + + HttpClientModule(ServletContext context) { + this.context = context; + } + + @Override + protected void configure() { + // URL connection defaults + Properties toBind = defaultProperties(); + toBind.putAll(checkNotNull(new PropertiesLoader(context).get(), "properties")); + toBind.putAll(System.getProperties()); + bindProperties(binder(), toBind); + bind(UriBuilder.class).to(UriBuilderImpl.class); + } + + private static Properties defaultProperties() { + Properties props = new Properties(); + props.setProperty(PROPERTY_MAX_CONNECTIONS_PER_CONTEXT, 20 + ""); + props.setProperty(PROPERTY_MAX_CONNECTIONS_PER_HOST, 0 + ""); + props.setProperty(PROPERTY_SO_TIMEOUT, 60000 + ""); + props.setProperty(PROPERTY_CONNECTION_TIMEOUT, 60000 + ""); + props.setProperty(PROPERTY_USER_THREADS, 0 + ""); + props.setProperty(PROPERTY_IO_WORKER_THREADS, 20 + ""); + return props; + } +} diff --git a/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/paas/config/PlatformServicesInitializer.java b/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/paas/config/PlatformServicesInitializer.java index 30403e646c..7e0aa429ce 100644 --- a/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/paas/config/PlatformServicesInitializer.java +++ b/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/paas/config/PlatformServicesInitializer.java @@ -18,34 +18,24 @@ */ package org.jclouds.demo.paas.config; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; -import static com.google.inject.name.Names.bindProperties; import static java.util.concurrent.TimeUnit.SECONDS; -import java.util.Properties; - import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; -import javax.ws.rs.core.UriBuilder; import org.cloudfoundry.runtime.env.ApplicationInstanceInfo; import org.cloudfoundry.runtime.env.CloudEnvironment; -import org.jclouds.PropertiesBuilder; import org.jclouds.concurrent.config.ExecutorServiceModule; import org.jclouds.demo.paas.PlatformServices; import org.jclouds.demo.paas.service.scheduler.Scheduler; import org.jclouds.demo.paas.service.taskqueue.TaskQueue; -import org.jclouds.demo.tweetstore.config.util.PropertiesLoader; import org.jclouds.http.HttpCommandExecutorService; import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap.Builder; -import com.google.inject.AbstractModule; import com.google.inject.Guice; -import com.sun.jersey.api.uri.UriBuilderImpl; /** * @author Andrew Phillips @@ -69,27 +59,14 @@ public class PlatformServicesInitializer implements ServletContextListener { final ServletContext context) { return Guice.createInjector(new ExecutorServiceModule(), new JavaUrlHttpCommandExecutorServiceModule(), - new AbstractModule() { - @Override - protected void configure() { - // URL connection defaults - Properties toBind = new PropertiesBuilder().build(); - toBind.putAll(checkNotNull(new PropertiesLoader(context).get(), "properties")); - toBind.putAll(System.getProperties()); - bindProperties(binder(), toBind); - bind(UriBuilder.class).to(UriBuilderImpl.class); - } - }).getInstance(HttpCommandExecutorService.class); + new HttpClientModule(context)) + .getInstance(HttpCommandExecutorService.class); } protected static String getBaseUrl(ServletContext context) { ApplicationInstanceInfo instanceInfo = new CloudEnvironment().getInstanceInfo(); - // TODO: use internal address if possible. See http://support.cloudfoundry.com/requests/102117 -// return "http://" + checkNotNull(instanceInfo.getHost(), "instanceInfo.getHost()") -// + ":" + instanceInfo.getPort() + context.getContextPath(); - checkState(!instanceInfo.getUris().isEmpty(), "instanceInfo.getUris() is empty"); - return "http://" + checkNotNull(instanceInfo.getUris().get(0), "instanceInfo.getUris().get(0)") - + context.getContextPath(); + // using localhost instead of instanceInfo.getHost(). See http://support.cloudfoundry.com/requests/102117 + return "http://127.0.0.1:" + instanceInfo.getPort() + context.getContextPath(); } // TODO: make the number and names of queues configurable diff --git a/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/config/SpringServletConfig.java b/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/config/SpringServletConfig.java index e7f019c3d7..768ec59a3d 100644 --- a/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/config/SpringServletConfig.java +++ b/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/config/SpringServletConfig.java @@ -42,8 +42,8 @@ import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.demo.paas.PlatformServices; import org.jclouds.demo.paas.service.taskqueue.TaskQueue; import org.jclouds.demo.tweetstore.config.util.CredentialsCollector; @@ -85,7 +85,7 @@ public class SpringServletConfig extends LoggingConfig implements ServletConfigA private ServletConfig servletConfig; - private Map> providerTypeToBlobStoreMap; + private Map providerTypeToBlobStoreMap; private Twitter twitterClient; private String container; private TaskQueue queue; @@ -115,8 +115,8 @@ public class SpringServletConfig extends LoggingConfig implements ServletConfigA // instantiate and store references to all blobstores by provider name providerTypeToBlobStoreMap = Maps.newHashMap(); for (String hint : getBlobstoreContexts(props)) { - providerTypeToBlobStoreMap.put(hint, BlobStoreContextBuilder - .newBuilder(hint).modules(modules).overrides(props).build()); + providerTypeToBlobStoreMap.put(hint, ContextBuilder.newBuilder(hint) + .modules(modules).overrides(props).build(BlobStoreContext.class)); } // get a queue for submitting store tweet requests and the application's base URL @@ -212,7 +212,7 @@ public class SpringServletConfig extends LoggingConfig implements ServletConfigA @PreDestroy public void destroy() throws Exception { LOGGER.trace("About to close contexts."); - for (BlobStoreContext context : providerTypeToBlobStoreMap.values()) { + for (BlobStoreContext context : providerTypeToBlobStoreMap.values()) { context.close(); } LOGGER.trace("Contexts closed."); diff --git a/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/AddTweetsController.java b/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/AddTweetsController.java index 08ccbcb1bb..5a8e6baf4b 100644 --- a/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/AddTweetsController.java +++ b/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/AddTweetsController.java @@ -54,14 +54,14 @@ public class AddTweetsController extends HttpServlet implements /** The serialVersionUID */ private static final long serialVersionUID = 3888348023150822683L; - private final Map> contexts; + private final Map contexts; private final ServiceToStoredTweetStatuses blobStoreContextToContainerResult; @Resource protected Logger logger = Logger.NULL; @Inject - public AddTweetsController(Map> contexts, + public AddTweetsController(Map contexts, ServiceToStoredTweetStatuses blobStoreContextToContainerResult) { this.contexts = contexts; this.blobStoreContextToContainerResult = blobStoreContextToContainerResult; diff --git a/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresController.java b/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresController.java index 71b715863b..592eaaa8bd 100644 --- a/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresController.java +++ b/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresController.java @@ -65,7 +65,7 @@ public class EnqueueStoresController extends HttpServlet { protected Logger logger = Logger.NULL; @Inject - public EnqueueStoresController(Map> contexts, TaskQueue taskQueue, + public EnqueueStoresController(Map contexts, TaskQueue taskQueue, @Named(PaasConstants.PROPERTY_PLATFORM_BASE_URL) String baseUrl) { contextNames = contexts.keySet(); this.taskQueue = taskQueue; diff --git a/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java b/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java index cef530d39b..725ba128f6 100644 --- a/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java +++ b/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java @@ -75,7 +75,7 @@ public class StoreTweetsController extends HttpServlet { /** The serialVersionUID */ private static final long serialVersionUID = 7215420527854203714L; - private final Map> contexts; + private final Map contexts; private final Twitter client; private final String container; @@ -84,7 +84,7 @@ public class StoreTweetsController extends HttpServlet { @Inject @VisibleForTesting - public StoreTweetsController(Map> contexts, + public StoreTweetsController(Map contexts, @Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) String container, Twitter client) { this.container = container; this.contexts = contexts; @@ -93,7 +93,7 @@ public class StoreTweetsController extends HttpServlet { @VisibleForTesting public void addMyTweets(String contextName, Iterable responseList) { - BlobStoreContext context = checkNotNull(contexts.get(contextName), "no context for " + contextName + " in " + BlobStoreContext context = checkNotNull(contexts.get(contextName), "no context for " + contextName + " in " + contexts.keySet()); BlobMap map = context.createBlobMap(container); for (Status status : responseList) { diff --git a/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatuses.java b/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatuses.java index 36437544d4..b29ec14549 100644 --- a/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatuses.java +++ b/demos/tweetstore/cf-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatuses.java @@ -18,6 +18,7 @@ */ package org.jclouds.demo.tweetstore.functions; +import java.net.URI; import java.util.Collections; import java.util.Map; import java.util.Set; @@ -27,6 +28,7 @@ import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; +import org.jclouds.Context; import org.jclouds.blobstore.BlobMap; import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; @@ -39,11 +41,11 @@ import com.google.common.collect.Iterables; @Singleton public class ServiceToStoredTweetStatuses implements Function> { - private final Map> contexts; + private final Map contexts; private final String container; @Inject - public ServiceToStoredTweetStatuses(Map> contexts, + public ServiceToStoredTweetStatuses(Map contexts, @Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) String container) { this.contexts = contexts; this.container = container; @@ -53,8 +55,8 @@ public class ServiceToStoredTweetStatuses implements Function apply(String service) { - BlobStoreContext context = contexts.get(service); - String host = context.getProviderSpecificContext().getEndpoint().getHost(); + BlobStoreContext context = contexts.get(service); + String host = URI.create(context.unwrap(Context.class).getProviderMetadata().getEndpoint()).getHost(); try { BlobMap blobMap = context.createBlobMap(container); Set blobs = blobMap.keySet(); diff --git a/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java b/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java index d6989d8bbe..1c93403650 100644 --- a/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java +++ b/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java @@ -25,8 +25,8 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; @@ -46,12 +46,12 @@ import com.google.common.collect.ImmutableSet; @Test(groups = "unit") public class AddTweetsControllerTest { - Map> createServices(String container) throws InterruptedException, + Map createServices(String container) throws InterruptedException, ExecutionException { - Map> services = Maps.newHashMap(); + Map services = Maps.newHashMap(); TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build(); for (String name : new String[] { "1", "2" }) { - BlobStoreContext context = BlobStoreContextBuilder.newBuilder(transientApiMetadata).build(); + BlobStoreContext context = ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class); context.getAsyncBlobStore().createContainerInLocation(null, container).get(); Blob blob = context.getAsyncBlobStore().blobBuilder("1").build(); blob.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, "frank"); @@ -64,7 +64,7 @@ public class AddTweetsControllerTest { public void testStoreTweets() throws IOException, InterruptedException, ExecutionException { String container = "container"; - Map> contexts = createServices(container); + Map contexts = createServices(container); ServiceToStoredTweetStatuses function = new ServiceToStoredTweetStatuses(contexts, container); AddTweetsController controller = new AddTweetsController(contexts, function); diff --git a/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresControllerTest.java b/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresControllerTest.java index c324579f82..3c5e5b1d80 100644 --- a/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresControllerTest.java +++ b/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresControllerTest.java @@ -23,8 +23,8 @@ import static org.easymock.EasyMock.*; import java.net.URI; import java.util.Map; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.demo.paas.RunnableHttpRequest; import org.jclouds.demo.paas.RunnableHttpRequest.Factory; @@ -43,16 +43,16 @@ import com.google.common.collect.ImmutableMultimap; @Test(groups = "unit") public class EnqueueStoresControllerTest { - Map> createBlobStores() { + Map createBlobStores() { TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build(); - Map> contexts = ImmutableMap.>of( - "test1", BlobStoreContextBuilder.newBuilder(transientApiMetadata).build(), - "test2", BlobStoreContextBuilder.newBuilder(transientApiMetadata).build()); + Map contexts = ImmutableMap.of( + "test1", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class), + "test2", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class)); return contexts; } public void testEnqueueStores() { - Map> stores = createBlobStores(); + Map stores = createBlobStores(); TaskQueue taskQueue = createMock(TaskQueue.class); Factory httpRequestFactory = createMock(Factory.class); EnqueueStoresController function = new EnqueueStoresController(stores, diff --git a/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java b/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java index f0deb2c105..3d0cbc4948 100644 --- a/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java +++ b/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java @@ -30,9 +30,9 @@ import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ExecutionException; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobMap; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.reference.TweetStoreConstants; @@ -57,19 +57,19 @@ public class StoreTweetsControllerTest { return createMock(Twitter.class); } - Map> createBlobStores() throws InterruptedException, ExecutionException { + Map createBlobStores() throws InterruptedException, ExecutionException { TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build(); - Map> contexts = ImmutableMap.>of( - "test1", BlobStoreContextBuilder.newBuilder(transientApiMetadata).build(), - "test2", BlobStoreContextBuilder.newBuilder(transientApiMetadata).build()); - for (BlobStoreContext blobstore : contexts.values()) { + Map contexts = ImmutableMap.of( + "test1", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class), + "test2", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class)); + for (BlobStoreContext blobstore : contexts.values()) { blobstore.getAsyncBlobStore().createContainerInLocation(null, "favo").get(); } return contexts; } public void testStoreTweets() throws IOException, InterruptedException, ExecutionException { - Map> stores = createBlobStores(); + Map stores = createBlobStores(); StoreTweetsController function = new StoreTweetsController(stores, "favo", createTwitter()); User frank = createMock(User.class); @@ -101,7 +101,7 @@ public class StoreTweetsControllerTest { verify(jimmy); verify(jimmyStatus); - for (Entry> entry : stores.entrySet()) { + for (Entry entry : stores.entrySet()) { BlobMap map = entry.getValue().createBlobMap("favo"); Blob frankBlob = map.get("1"); assertEquals(frankBlob.getMetadata().getName(), "1"); diff --git a/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java b/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java index 61a6dcfffc..af74b423d5 100644 --- a/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java +++ b/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java @@ -23,9 +23,9 @@ import static org.testng.Assert.assertEquals; import java.io.IOException; import java.util.concurrent.ExecutionException; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobMap; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; @@ -41,8 +41,8 @@ import org.testng.annotations.Test; public class KeyToStoredTweetStatusTest { BlobMap createMap() throws InterruptedException, ExecutionException { - BlobStoreContext context = - BlobStoreContextBuilder.newBuilder(TransientApiMetadata.builder().build()).build(); + BlobStoreContext context = + ContextBuilder.newBuilder(TransientApiMetadata.builder().build()).build(BlobStoreContext.class); context.getBlobStore().createContainerInLocation(null, "test1"); return context.createBlobMap("test1"); } diff --git a/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java b/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java index 54deb948db..5fec52711e 100644 --- a/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java +++ b/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java @@ -24,8 +24,8 @@ import java.io.IOException; import java.util.Map; import java.util.concurrent.ExecutionException; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; @@ -43,12 +43,12 @@ import com.google.common.collect.Iterables; @Test(groups = "unit") public class ServiceToStoredTweetStatusesTest { - Map> createServices(String container) throws InterruptedException, + Map createServices(String container) throws InterruptedException, ExecutionException { - Map> services = Maps.newHashMap(); + Map services = Maps.newHashMap(); TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build(); for (String name : new String[] { "1", "2" }) { - BlobStoreContext context = BlobStoreContextBuilder.newBuilder(transientApiMetadata).build(); + BlobStoreContext context = ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class); context.getAsyncBlobStore().createContainerInLocation(null, container).get(); Blob blob = context.getAsyncBlobStore().blobBuilder("1").build(); blob.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, "frank"); @@ -61,7 +61,7 @@ public class ServiceToStoredTweetStatusesTest { public void testStoreTweets() throws IOException, InterruptedException, ExecutionException { String container = "container"; - Map> contexts = createServices(container); + Map contexts = createServices(container); ServiceToStoredTweetStatuses function = new ServiceToStoredTweetStatuses(contexts, container); diff --git a/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java b/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java index 957945872c..3723d5f250 100644 --- a/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java +++ b/demos/tweetstore/cf-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java @@ -37,8 +37,9 @@ import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; +import org.jclouds.Context; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.demo.tweetstore.config.SpringServletConfig; import org.jclouds.demo.tweetstore.controller.StoreTweetsController; import org.jclouds.logging.log4j.config.Log4JLoggingModule; @@ -73,7 +74,7 @@ public class TweetStoreLiveTest { CloudFoundryServer server; private URL url; - private Map> contexts; + private Map contexts; private String container; private static final Iterable blobstores = @@ -100,8 +101,8 @@ public class TweetStoreLiveTest { this.contexts = Maps.newConcurrentMap(); for (String provider : blobstores) { - contexts.put(provider, BlobStoreContextBuilder.newBuilder(provider) - .modules(wiring).overrides(props).build()); + contexts.put(provider, ContextBuilder.newBuilder(provider).modules(wiring) + .overrides(props).build(BlobStoreContext.class)); } Configuration conf = new ConfigurationBuilder() @@ -116,10 +117,10 @@ public class TweetStoreLiveTest { ResponseList statuses = client.getMentions(); boolean deleted = false; - for (BlobStoreContext context : contexts.values()) { + for (BlobStoreContext context : contexts.values()) { if (context.getBlobStore().containerExists(container)) { - System.err.printf("deleting container %s at %s%n", container, context.getProviderSpecificContext() - .getEndpoint()); + System.err.printf("deleting container %s at %s%n", container, + context.unwrap(Context.class).getProviderMetadata().getEndpoint()); context.getBlobStore().deleteContainer(container); deleted = true; } @@ -128,9 +129,9 @@ public class TweetStoreLiveTest { System.err.println("sleeping 60 seconds to allow containers to clear"); Thread.sleep(60000); } - for (BlobStoreContext context : contexts.values()) { - System.err.printf("creating container %s at %s%n", container, context.getProviderSpecificContext() - .getEndpoint()); + for (BlobStoreContext context : contexts.values()) { + System.err.printf("creating container %s at %s%n", container, + context.unwrap(Context.class).getProviderMetadata().getEndpoint()); context.getBlobStore().createContainerInLocation(null, container); } if (deleted) { @@ -138,7 +139,7 @@ public class TweetStoreLiveTest { Thread.sleep(5000); } - for (Entry> entry : contexts.entrySet()) { + for (Entry entry : contexts.entrySet()) { System.err.printf("filling container %s at %s%n", container, entry.getKey()); controller.addMyTweets(entry.getKey(), statuses); } @@ -205,8 +206,8 @@ public class TweetStoreLiveTest { System.err.println("sleeping 20 seconds to allow for eventual consistency delay"); Thread.sleep(20000); - for (BlobStoreContext context : contexts.values()) { - assert context.createInputStreamMap(container).size() > 0 : context.getProviderSpecificContext().getEndpoint(); + for (BlobStoreContext context : contexts.values()) { + assert context.createInputStreamMap(container).size() > 0 : context.unwrap(Context.class).getProviderMetadata().getEndpoint(); } } diff --git a/demos/tweetstore/gae-tweetstore-spring/pom.xml b/demos/tweetstore/gae-tweetstore-spring/pom.xml index d97b9c09e0..71d682a544 100644 --- a/demos/tweetstore/gae-tweetstore-spring/pom.xml +++ b/demos/tweetstore/gae-tweetstore-spring/pom.xml @@ -52,12 +52,19 @@ org.springframework spring-context - 3.0.0.RELEASE + 3.0.5.RELEASE + + + + commons-logging + commons-logging + + org.springframework spring-webmvc - 3.0.0.RELEASE + 3.0.5.RELEASE cglib diff --git a/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/config/SpringServletConfig.java b/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/config/SpringServletConfig.java index ca84b6dad5..c925dc59a7 100644 --- a/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/config/SpringServletConfig.java +++ b/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/config/SpringServletConfig.java @@ -42,8 +42,8 @@ import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.demo.tweetstore.config.util.CredentialsCollector; import org.jclouds.demo.tweetstore.controller.AddTweetsController; import org.jclouds.demo.tweetstore.controller.EnqueueStoresController; @@ -86,7 +86,7 @@ public class SpringServletConfig extends LoggingConfig implements ServletConfigA private ServletConfig servletConfig; - private Map> providerTypeToBlobStoreMap; + private Map providerTypeToBlobStoreMap; private Twitter twitterClient; private String container; private Queue queue; @@ -116,8 +116,8 @@ public class SpringServletConfig extends LoggingConfig implements ServletConfigA // instantiate and store references to all blobstores by provider name providerTypeToBlobStoreMap = Maps.newHashMap(); for (String hint : getBlobstoreContexts(props)) { - providerTypeToBlobStoreMap.put(hint, BlobStoreContextBuilder - .newBuilder(hint).modules(modules).overrides(props).build()); + providerTypeToBlobStoreMap.put(hint, ContextBuilder.newBuilder(hint) + .modules(modules).overrides(props).build(BlobStoreContext.class)); } // get a queue for submitting store tweet requests @@ -211,7 +211,7 @@ public class SpringServletConfig extends LoggingConfig implements ServletConfigA @PreDestroy public void destroy() throws Exception { LOGGER.trace("About to close contexts."); - for (BlobStoreContext context : providerTypeToBlobStoreMap.values()) { + for (BlobStoreContext context : providerTypeToBlobStoreMap.values()) { context.close(); } LOGGER.trace("Contexts closed."); diff --git a/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/AddTweetsController.java b/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/AddTweetsController.java index 2246479460..918132161e 100644 --- a/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/AddTweetsController.java +++ b/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/AddTweetsController.java @@ -54,14 +54,14 @@ public class AddTweetsController extends HttpServlet implements /** The serialVersionUID */ private static final long serialVersionUID = 3888348023150822683L; - private final Map> contexts; + private final Map contexts; private final ServiceToStoredTweetStatuses blobStoreContextToContainerResult; @Resource protected Logger logger = Logger.NULL; @Inject - public AddTweetsController(Map> contexts, + public AddTweetsController(Map contexts, ServiceToStoredTweetStatuses blobStoreContextToContainerResult) { this.contexts = contexts; this.blobStoreContextToContainerResult = blobStoreContextToContainerResult; diff --git a/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresController.java b/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresController.java index 150dff0f6c..94568e4dec 100644 --- a/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresController.java +++ b/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresController.java @@ -60,7 +60,7 @@ public class EnqueueStoresController extends HttpServlet { protected Logger logger = Logger.NULL; @Inject - public EnqueueStoresController(Map> contexts, + public EnqueueStoresController(Map contexts, Queue taskQueue) { contextNames = contexts.keySet(); this.taskQueue = taskQueue; diff --git a/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java b/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java index 95453e0894..ae00c69d20 100644 --- a/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java +++ b/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java @@ -73,7 +73,7 @@ public class StoreTweetsController extends HttpServlet { /** The serialVersionUID */ private static final long serialVersionUID = 7215420527854203714L; - private final Map> contexts; + private final Map contexts; private final Twitter client; private final String container; @@ -82,7 +82,7 @@ public class StoreTweetsController extends HttpServlet { @Inject @VisibleForTesting - public StoreTweetsController(Map> contexts, + public StoreTweetsController(Map contexts, @Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) String container, Twitter client) { this.container = container; this.contexts = contexts; @@ -91,7 +91,7 @@ public class StoreTweetsController extends HttpServlet { @VisibleForTesting public void addMyTweets(String contextName, Iterable responseList) { - BlobStoreContext context = checkNotNull(contexts.get(contextName), "no context for " + contextName + " in " + BlobStoreContext context = checkNotNull(contexts.get(contextName), "no context for " + contextName + " in " + contexts.keySet()); BlobMap map = context.createBlobMap(container); for (Status status : responseList) { diff --git a/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatuses.java b/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatuses.java index 36437544d4..b29ec14549 100644 --- a/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatuses.java +++ b/demos/tweetstore/gae-tweetstore-spring/src/main/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatuses.java @@ -18,6 +18,7 @@ */ package org.jclouds.demo.tweetstore.functions; +import java.net.URI; import java.util.Collections; import java.util.Map; import java.util.Set; @@ -27,6 +28,7 @@ import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; +import org.jclouds.Context; import org.jclouds.blobstore.BlobMap; import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; @@ -39,11 +41,11 @@ import com.google.common.collect.Iterables; @Singleton public class ServiceToStoredTweetStatuses implements Function> { - private final Map> contexts; + private final Map contexts; private final String container; @Inject - public ServiceToStoredTweetStatuses(Map> contexts, + public ServiceToStoredTweetStatuses(Map contexts, @Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) String container) { this.contexts = contexts; this.container = container; @@ -53,8 +55,8 @@ public class ServiceToStoredTweetStatuses implements Function apply(String service) { - BlobStoreContext context = contexts.get(service); - String host = context.getProviderSpecificContext().getEndpoint().getHost(); + BlobStoreContext context = contexts.get(service); + String host = URI.create(context.unwrap(Context.class).getProviderMetadata().getEndpoint()).getHost(); try { BlobMap blobMap = context.createBlobMap(container); Set blobs = blobMap.keySet(); diff --git a/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java b/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java index d6989d8bbe..1c93403650 100644 --- a/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java +++ b/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java @@ -25,8 +25,8 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; @@ -46,12 +46,12 @@ import com.google.common.collect.ImmutableSet; @Test(groups = "unit") public class AddTweetsControllerTest { - Map> createServices(String container) throws InterruptedException, + Map createServices(String container) throws InterruptedException, ExecutionException { - Map> services = Maps.newHashMap(); + Map services = Maps.newHashMap(); TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build(); for (String name : new String[] { "1", "2" }) { - BlobStoreContext context = BlobStoreContextBuilder.newBuilder(transientApiMetadata).build(); + BlobStoreContext context = ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class); context.getAsyncBlobStore().createContainerInLocation(null, container).get(); Blob blob = context.getAsyncBlobStore().blobBuilder("1").build(); blob.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, "frank"); @@ -64,7 +64,7 @@ public class AddTweetsControllerTest { public void testStoreTweets() throws IOException, InterruptedException, ExecutionException { String container = "container"; - Map> contexts = createServices(container); + Map contexts = createServices(container); ServiceToStoredTweetStatuses function = new ServiceToStoredTweetStatuses(contexts, container); AddTweetsController controller = new AddTweetsController(contexts, function); diff --git a/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresControllerTest.java b/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresControllerTest.java index 435285b62c..5190718e4c 100644 --- a/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresControllerTest.java +++ b/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresControllerTest.java @@ -26,8 +26,8 @@ import static org.easymock.EasyMock.verify; import java.util.Map; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.testng.annotations.Test; @@ -43,16 +43,16 @@ import com.google.common.collect.ImmutableMap; @Test(groups = "unit") public class EnqueueStoresControllerTest { - Map> createBlobStores() { + Map createBlobStores() { TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build(); - Map> contexts = ImmutableMap.>of( - "test1", BlobStoreContextBuilder.newBuilder(transientApiMetadata).build(), - "test2", BlobStoreContextBuilder.newBuilder(transientApiMetadata).build()); + Map contexts = ImmutableMap.of( + "test1", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class), + "test2", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class)); return contexts; } public void testEnqueueStores() { - Map> stores = createBlobStores(); + Map stores = createBlobStores(); Queue taskQueue = createMock(Queue.class); EnqueueStoresController function = new EnqueueStoresController(stores, taskQueue); diff --git a/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java b/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java index 67e05543ae..3afb3db32a 100644 --- a/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java +++ b/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java @@ -30,9 +30,9 @@ import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ExecutionException; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobMap; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.reference.TweetStoreConstants; @@ -57,19 +57,19 @@ public class StoreTweetsControllerTest { return createMock(Twitter.class); } - Map> createBlobStores() throws InterruptedException, ExecutionException { + Map createBlobStores() throws InterruptedException, ExecutionException { TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build(); - Map> contexts = ImmutableMap.>of( - "test1", BlobStoreContextBuilder.newBuilder(transientApiMetadata).build(), - "test2", BlobStoreContextBuilder.newBuilder(transientApiMetadata).build()); - for (BlobStoreContext blobstore : contexts.values()) { + Map contexts = ImmutableMap.of( + "test1", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class), + "test2", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class)); + for (BlobStoreContext blobstore : contexts.values()) { blobstore.getAsyncBlobStore().createContainerInLocation(null, "favo").get(); } return contexts; } public void testStoreTweets() throws IOException, InterruptedException, ExecutionException { - Map> stores = createBlobStores(); + Map stores = createBlobStores(); StoreTweetsController function = new StoreTweetsController(stores, "favo", createTwitter()); User frank = createMock(User.class); @@ -101,7 +101,7 @@ public class StoreTweetsControllerTest { verify(jimmy); verify(jimmyStatus); - for (Entry> entry : stores.entrySet()) { + for (Entry entry : stores.entrySet()) { BlobMap map = entry.getValue().createBlobMap("favo"); Blob frankBlob = map.get("1"); assertEquals(frankBlob.getMetadata().getName(), "1"); diff --git a/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java b/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java index 61a6dcfffc..af74b423d5 100644 --- a/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java +++ b/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java @@ -23,9 +23,9 @@ import static org.testng.Assert.assertEquals; import java.io.IOException; import java.util.concurrent.ExecutionException; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobMap; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; @@ -41,8 +41,8 @@ import org.testng.annotations.Test; public class KeyToStoredTweetStatusTest { BlobMap createMap() throws InterruptedException, ExecutionException { - BlobStoreContext context = - BlobStoreContextBuilder.newBuilder(TransientApiMetadata.builder().build()).build(); + BlobStoreContext context = + ContextBuilder.newBuilder(TransientApiMetadata.builder().build()).build(BlobStoreContext.class); context.getBlobStore().createContainerInLocation(null, "test1"); return context.createBlobMap("test1"); } diff --git a/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java b/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java index 54deb948db..5fec52711e 100644 --- a/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java +++ b/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java @@ -24,8 +24,8 @@ import java.io.IOException; import java.util.Map; import java.util.concurrent.ExecutionException; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; @@ -43,12 +43,12 @@ import com.google.common.collect.Iterables; @Test(groups = "unit") public class ServiceToStoredTweetStatusesTest { - Map> createServices(String container) throws InterruptedException, + Map createServices(String container) throws InterruptedException, ExecutionException { - Map> services = Maps.newHashMap(); + Map services = Maps.newHashMap(); TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build(); for (String name : new String[] { "1", "2" }) { - BlobStoreContext context = BlobStoreContextBuilder.newBuilder(transientApiMetadata).build(); + BlobStoreContext context = ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class); context.getAsyncBlobStore().createContainerInLocation(null, container).get(); Blob blob = context.getAsyncBlobStore().blobBuilder("1").build(); blob.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, "frank"); @@ -61,7 +61,7 @@ public class ServiceToStoredTweetStatusesTest { public void testStoreTweets() throws IOException, InterruptedException, ExecutionException { String container = "container"; - Map> contexts = createServices(container); + Map contexts = createServices(container); ServiceToStoredTweetStatuses function = new ServiceToStoredTweetStatuses(contexts, container); diff --git a/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java b/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java index 0b2a80dceb..7ed1008bab 100644 --- a/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java +++ b/demos/tweetstore/gae-tweetstore-spring/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java @@ -37,8 +37,9 @@ import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; +import org.jclouds.Context; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.demo.tweetstore.config.SpringServletConfig; import org.jclouds.demo.tweetstore.controller.StoreTweetsController; import org.jclouds.logging.log4j.config.Log4JLoggingModule; @@ -73,7 +74,7 @@ public class TweetStoreLiveTest { GoogleDevServer server; private URL url; - private Map> contexts; + private Map contexts; private String container; private static final Iterable blobstores = @@ -100,8 +101,8 @@ public class TweetStoreLiveTest { this.contexts = Maps.newConcurrentMap(); for (String provider : blobstores) { - contexts.put(provider, BlobStoreContextBuilder.newBuilder(provider) - .modules(wiring).overrides(props).build()); + contexts.put(provider, ContextBuilder.newBuilder(provider) + .modules(wiring).overrides(props).build(BlobStoreContext.class)); } Configuration conf = new ConfigurationBuilder() @@ -116,10 +117,10 @@ public class TweetStoreLiveTest { ResponseList statuses = client.getMentions(); boolean deleted = false; - for (BlobStoreContext context : contexts.values()) { + for (BlobStoreContext context : contexts.values()) { if (context.getBlobStore().containerExists(container)) { - System.err.printf("deleting container %s at %s%n", container, context.getProviderSpecificContext() - .getEndpoint()); + System.err.printf("deleting container %s at %s%n", container, + context.unwrap(Context.class).getProviderMetadata().getEndpoint()); context.getBlobStore().deleteContainer(container); deleted = true; } @@ -128,9 +129,9 @@ public class TweetStoreLiveTest { System.err.println("sleeping 60 seconds to allow containers to clear"); Thread.sleep(60000); } - for (BlobStoreContext context : contexts.values()) { - System.err.printf("creating container %s at %s%n", container, context.getProviderSpecificContext() - .getEndpoint()); + for (BlobStoreContext context : contexts.values()) { + System.err.printf("creating container %s at %s%n", container, + context.unwrap(Context.class).getProviderMetadata().getEndpoint()); context.getBlobStore().createContainerInLocation(null, container); } if (deleted) { @@ -138,7 +139,7 @@ public class TweetStoreLiveTest { Thread.sleep(5000); } - for (Entry> entry : contexts.entrySet()) { + for (Entry entry : contexts.entrySet()) { System.err.printf("filling container %s at %s%n", container, entry.getKey()); controller.addMyTweets(entry.getKey(), statuses); } @@ -205,8 +206,8 @@ public class TweetStoreLiveTest { System.err.println("sleeping 20 seconds to allow for eventual consistency delay"); Thread.sleep(20000); - for (BlobStoreContext context : contexts.values()) { - assert context.createInputStreamMap(container).size() > 0 : context.getProviderSpecificContext().getEndpoint(); + for (BlobStoreContext context : contexts.values()) { + assert context.createInputStreamMap(container).size() > 0 : context.unwrap(Context.class).getProviderMetadata().getEndpoint(); } } diff --git a/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java b/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java index 7f9364c47e..2db9a45034 100644 --- a/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java +++ b/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java @@ -38,8 +38,8 @@ import java.util.Set; import javax.servlet.ServletContextEvent; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.demo.tweetstore.config.util.CredentialsCollector; import org.jclouds.demo.tweetstore.controller.AddTweetsController; import org.jclouds.demo.tweetstore.controller.EnqueueStoresController; @@ -73,7 +73,7 @@ import com.google.inject.servlet.ServletModule; public class GuiceServletConfig extends GuiceServletContextListener { public static final String PROPERTY_BLOBSTORE_CONTEXTS = "blobstore.contexts"; - private Map> providerTypeToBlobStoreMap; + private Map providerTypeToBlobStoreMap; private Twitter twitterClient; private String container; private Queue queue; @@ -102,8 +102,8 @@ public class GuiceServletConfig extends GuiceServletContextListener { // instantiate and store references to all blobstores by provider name providerTypeToBlobStoreMap = Maps.newHashMap(); for (String hint : getBlobstoreContexts(props)) { - providerTypeToBlobStoreMap.put(hint, BlobStoreContextBuilder - .newBuilder(hint).modules(modules).overrides(props).build()); + providerTypeToBlobStoreMap.put(hint, ContextBuilder.newBuilder(hint) + .modules(modules).overrides(props).build(BlobStoreContext.class)); } // get a queue for submitting store tweet requests @@ -140,7 +140,7 @@ public class GuiceServletConfig extends GuiceServletContextListener { return Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { - bind(new TypeLiteral>>() { + bind(new TypeLiteral>() { }).toInstance(providerTypeToBlobStoreMap); bind(Twitter.class).toInstance(twitterClient); bind(Queue.class).toInstance(queue); @@ -154,7 +154,7 @@ public class GuiceServletConfig extends GuiceServletContextListener { @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { - for (BlobStoreContext context : providerTypeToBlobStoreMap.values()) { + for (BlobStoreContext context : providerTypeToBlobStoreMap.values()) { context.close(); } queue.purge(); diff --git a/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/AddTweetsController.java b/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/AddTweetsController.java index 299448a481..b681cfb27d 100644 --- a/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/AddTweetsController.java +++ b/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/AddTweetsController.java @@ -54,14 +54,14 @@ public class AddTweetsController extends HttpServlet implements /** The serialVersionUID */ private static final long serialVersionUID = 3888348023150822683L; - private final Map> contexts; + private final Map contexts; private final ServiceToStoredTweetStatuses blobStoreContextToContainerResult; @Resource protected Logger logger = Logger.NULL; @Inject - AddTweetsController(Map> contexts, + AddTweetsController(Map contexts, ServiceToStoredTweetStatuses blobStoreContextToContainerResult) { this.contexts = contexts; this.blobStoreContextToContainerResult = blobStoreContextToContainerResult; diff --git a/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresController.java b/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresController.java index 150dff0f6c..94568e4dec 100644 --- a/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresController.java +++ b/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresController.java @@ -60,7 +60,7 @@ public class EnqueueStoresController extends HttpServlet { protected Logger logger = Logger.NULL; @Inject - public EnqueueStoresController(Map> contexts, + public EnqueueStoresController(Map contexts, Queue taskQueue) { contextNames = contexts.keySet(); this.taskQueue = taskQueue; diff --git a/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java b/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java index 95453e0894..ae00c69d20 100644 --- a/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java +++ b/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java @@ -73,7 +73,7 @@ public class StoreTweetsController extends HttpServlet { /** The serialVersionUID */ private static final long serialVersionUID = 7215420527854203714L; - private final Map> contexts; + private final Map contexts; private final Twitter client; private final String container; @@ -82,7 +82,7 @@ public class StoreTweetsController extends HttpServlet { @Inject @VisibleForTesting - public StoreTweetsController(Map> contexts, + public StoreTweetsController(Map contexts, @Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) String container, Twitter client) { this.container = container; this.contexts = contexts; @@ -91,7 +91,7 @@ public class StoreTweetsController extends HttpServlet { @VisibleForTesting public void addMyTweets(String contextName, Iterable responseList) { - BlobStoreContext context = checkNotNull(contexts.get(contextName), "no context for " + contextName + " in " + BlobStoreContext context = checkNotNull(contexts.get(contextName), "no context for " + contextName + " in " + contexts.keySet()); BlobMap map = context.createBlobMap(container); for (Status status : responseList) { diff --git a/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatuses.java b/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatuses.java index 36437544d4..165c1fc3e4 100644 --- a/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatuses.java +++ b/demos/tweetstore/gae-tweetstore/src/main/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatuses.java @@ -18,6 +18,7 @@ */ package org.jclouds.demo.tweetstore.functions; +import java.net.URI; import java.util.Collections; import java.util.Map; import java.util.Set; @@ -27,6 +28,7 @@ import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; +import org.jclouds.Context; import org.jclouds.blobstore.BlobMap; import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; @@ -39,11 +41,11 @@ import com.google.common.collect.Iterables; @Singleton public class ServiceToStoredTweetStatuses implements Function> { - private final Map> contexts; + private final Map contexts; private final String container; @Inject - public ServiceToStoredTweetStatuses(Map> contexts, + public ServiceToStoredTweetStatuses(Map contexts, @Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) String container) { this.contexts = contexts; this.container = container; @@ -53,8 +55,9 @@ public class ServiceToStoredTweetStatuses implements Function apply(String service) { - BlobStoreContext context = contexts.get(service); - String host = context.getProviderSpecificContext().getEndpoint().getHost(); + BlobStoreContext context = contexts.get(service); + String host = URI.create(context.unwrap(Context.class).getProviderMetadata() + .getEndpoint()).getHost(); try { BlobMap blobMap = context.createBlobMap(container); Set blobs = blobMap.keySet(); diff --git a/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java b/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java index d6989d8bbe..1c93403650 100644 --- a/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java +++ b/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java @@ -25,8 +25,8 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; @@ -46,12 +46,12 @@ import com.google.common.collect.ImmutableSet; @Test(groups = "unit") public class AddTweetsControllerTest { - Map> createServices(String container) throws InterruptedException, + Map createServices(String container) throws InterruptedException, ExecutionException { - Map> services = Maps.newHashMap(); + Map services = Maps.newHashMap(); TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build(); for (String name : new String[] { "1", "2" }) { - BlobStoreContext context = BlobStoreContextBuilder.newBuilder(transientApiMetadata).build(); + BlobStoreContext context = ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class); context.getAsyncBlobStore().createContainerInLocation(null, container).get(); Blob blob = context.getAsyncBlobStore().blobBuilder("1").build(); blob.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, "frank"); @@ -64,7 +64,7 @@ public class AddTweetsControllerTest { public void testStoreTweets() throws IOException, InterruptedException, ExecutionException { String container = "container"; - Map> contexts = createServices(container); + Map contexts = createServices(container); ServiceToStoredTweetStatuses function = new ServiceToStoredTweetStatuses(contexts, container); AddTweetsController controller = new AddTweetsController(contexts, function); diff --git a/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresControllerTest.java b/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresControllerTest.java index 435285b62c..5190718e4c 100644 --- a/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresControllerTest.java +++ b/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresControllerTest.java @@ -26,8 +26,8 @@ import static org.easymock.EasyMock.verify; import java.util.Map; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.testng.annotations.Test; @@ -43,16 +43,16 @@ import com.google.common.collect.ImmutableMap; @Test(groups = "unit") public class EnqueueStoresControllerTest { - Map> createBlobStores() { + Map createBlobStores() { TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build(); - Map> contexts = ImmutableMap.>of( - "test1", BlobStoreContextBuilder.newBuilder(transientApiMetadata).build(), - "test2", BlobStoreContextBuilder.newBuilder(transientApiMetadata).build()); + Map contexts = ImmutableMap.of( + "test1", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class), + "test2", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class)); return contexts; } public void testEnqueueStores() { - Map> stores = createBlobStores(); + Map stores = createBlobStores(); Queue taskQueue = createMock(Queue.class); EnqueueStoresController function = new EnqueueStoresController(stores, taskQueue); diff --git a/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java b/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java index cb89719fd5..e592355bbf 100644 --- a/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java +++ b/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java @@ -30,9 +30,9 @@ import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ExecutionException; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobMap; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.reference.TweetStoreConstants; @@ -57,19 +57,19 @@ public class StoreTweetsControllerTest { return createMock(Twitter.class); } - Map> createBlobStores() throws InterruptedException, ExecutionException { + Map createBlobStores() throws InterruptedException, ExecutionException { TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build(); - Map> contexts = ImmutableMap.>of( - "test1", BlobStoreContextBuilder.newBuilder(transientApiMetadata).build(), - "test2", BlobStoreContextBuilder.newBuilder(transientApiMetadata).build()); - for (BlobStoreContext blobstore : contexts.values()) { + Map contexts = ImmutableMap.of( + "test1", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class), + "test2", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class)); + for (BlobStoreContext blobstore : contexts.values()) { blobstore.getAsyncBlobStore().createContainerInLocation(null, "favo").get(); } return contexts; } public void testStoreTweets() throws IOException, InterruptedException, ExecutionException { - Map> stores = createBlobStores(); + Map stores = createBlobStores(); StoreTweetsController function = new StoreTweetsController(stores, "favo", createTwitter()); User frank = createMock(User.class); @@ -101,7 +101,7 @@ public class StoreTweetsControllerTest { verify(jimmy); verify(jimmyStatus); - for (Entry> entry : stores.entrySet()) { + for (Entry entry : stores.entrySet()) { BlobMap map = entry.getValue().createBlobMap("favo"); Blob frankBlob = map.get("1"); assertEquals(frankBlob.getMetadata().getName(), "1"); diff --git a/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java b/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java index 4c05f7ac68..2667a87fd2 100644 --- a/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java +++ b/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java @@ -23,9 +23,9 @@ import static org.testng.Assert.assertEquals; import java.io.IOException; import java.util.concurrent.ExecutionException; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobMap; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; @@ -41,8 +41,8 @@ import org.testng.annotations.Test; public class KeyToStoredTweetStatusTest { BlobMap createMap() throws InterruptedException, ExecutionException { - BlobStoreContext context = - BlobStoreContextBuilder.newBuilder(TransientApiMetadata.builder().build()).build(); + BlobStoreContext context = + ContextBuilder.newBuilder(TransientApiMetadata.builder().build()).build(BlobStoreContext.class); context.getBlobStore().createContainerInLocation(null, "test1"); return context.createBlobMap("test1"); } diff --git a/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java b/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java index 54deb948db..6bce7f8e8e 100644 --- a/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java +++ b/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java @@ -24,8 +24,8 @@ import java.io.IOException; import java.util.Map; import java.util.concurrent.ExecutionException; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; @@ -43,12 +43,13 @@ import com.google.common.collect.Iterables; @Test(groups = "unit") public class ServiceToStoredTweetStatusesTest { - Map> createServices(String container) throws InterruptedException, + Map createServices(String container) throws InterruptedException, ExecutionException { - Map> services = Maps.newHashMap(); + Map services = Maps.newHashMap(); TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build(); for (String name : new String[] { "1", "2" }) { - BlobStoreContext context = BlobStoreContextBuilder.newBuilder(transientApiMetadata).build(); + BlobStoreContext context = + ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class); context.getAsyncBlobStore().createContainerInLocation(null, container).get(); Blob blob = context.getAsyncBlobStore().blobBuilder("1").build(); blob.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, "frank"); @@ -61,7 +62,7 @@ public class ServiceToStoredTweetStatusesTest { public void testStoreTweets() throws IOException, InterruptedException, ExecutionException { String container = "container"; - Map> contexts = createServices(container); + Map contexts = createServices(container); ServiceToStoredTweetStatuses function = new ServiceToStoredTweetStatuses(contexts, container); diff --git a/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java b/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java index 15073996ec..3265e752e9 100644 --- a/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java +++ b/demos/tweetstore/gae-tweetstore/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java @@ -37,8 +37,9 @@ import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; +import org.jclouds.Context; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.demo.tweetstore.config.GuiceServletConfig; import org.jclouds.demo.tweetstore.controller.StoreTweetsController; import org.jclouds.logging.log4j.config.Log4JLoggingModule; @@ -73,7 +74,7 @@ import com.google.inject.Module; public class TweetStoreLiveTest { GoogleDevServer server; private URL url; - private Map> contexts; + private Map contexts; private String container; private static final Iterable blobstores = Splitter.on(',').split(System.getProperty(PROPERTY_TWEETSTORE_BLOBSTORES, @@ -99,8 +100,8 @@ public class TweetStoreLiveTest { this.contexts = Maps.newConcurrentMap(); for (String provider : blobstores) { - contexts.put(provider, BlobStoreContextBuilder.newBuilder(provider) - .modules(wiring).overrides(props).build()); + contexts.put(provider, ContextBuilder.newBuilder(provider) + .modules(wiring).overrides(props).build(BlobStoreContext.class)); } Configuration conf = new ConfigurationBuilder() @@ -115,11 +116,11 @@ public class TweetStoreLiveTest { ResponseList statuses = client.getMentions(); boolean deleted = false; - for (BlobStoreContext context : contexts.values()) { + for (BlobStoreContext context : contexts.values()) { try { if (context.getBlobStore().containerExists(container)) { - System.err.printf("deleting container %s at %s%n", container, context.getProviderSpecificContext() - .getEndpoint()); + System.err.printf("deleting container %s at %s%n", container, + context.unwrap(Context.class).getProviderMetadata().getEndpoint()); context.getBlobStore().deleteContainer(container); deleted = true; } @@ -131,9 +132,9 @@ public class TweetStoreLiveTest { System.err.println("sleeping 60 seconds to allow containers to clear"); Thread.sleep(60000); } - for (BlobStoreContext context : contexts.values()) { - System.err.printf("creating container %s at %s%n", container, context.getProviderSpecificContext() - .getEndpoint()); + for (BlobStoreContext context : contexts.values()) { + System.err.printf("creating container %s at %s%n", container, + context.unwrap(Context.class).getProviderMetadata().getEndpoint()); context.getBlobStore().createContainerInLocation(null, container); } @@ -142,7 +143,7 @@ public class TweetStoreLiveTest { Thread.sleep(5000); } - for (Entry> entry : contexts.entrySet()) { + for (Entry entry : contexts.entrySet()) { System.err.printf("filling container %s at %s%n", container, entry.getKey()); controller.addMyTweets(entry.getKey(), statuses); } @@ -210,8 +211,8 @@ public class TweetStoreLiveTest { System.err.println("sleeping 20 seconds to allow for eventual consistency delay"); Thread.sleep(20000); - for (BlobStoreContext context : contexts.values()) { - assert context.createInputStreamMap(container).size() > 0 : context.getProviderSpecificContext().getEndpoint(); + for (BlobStoreContext context : contexts.values()) { + assert context.createInputStreamMap(container).size() > 0 : context.unwrap(Context.class).getProviderMetadata().getEndpoint(); } } diff --git a/demos/tweetstore/pom.xml b/demos/tweetstore/pom.xml index 008a7a899a..22255d6eec 100644 --- a/demos/tweetstore/pom.xml +++ b/demos/tweetstore/pom.xml @@ -30,9 +30,11 @@ pom jclouds TweetStore demos project + cf-tweetstore-spring gae-tweetstore gae-tweetstore-spring runatcloud-tweetstore + rhcloud-tweetstore @@ -160,6 +162,135 @@ + + com.ning.maven.plugins + maven-duplicate-finder-plugin + 1.0.3 + + + + + + + com.google.appengine + appengine-api-1.0-sdk + 1.6.1 + + + com.google.appengine + appengine-tools-sdk + 1.6.1 + test + + + + com.google + + + + + + + javax.annotation + jsr250-api + 1.0 + runtime + + + org.apache.tomcat + annotations-api + 6.0.32 + test + + + + javax.annotation + + + + + + + commons-beanutils + commons-beanutils + 1.7.0 + runtime + + + commons-collections + commons-collections + 3.1 + runtime + + + + org.apache.commons.collections + + + + + + + javax.servlet + servlet-api + 2.5 + provided + + + com.google.appengine + appengine-tools-sdk + 1.6.1 + test + + + org.apache.tomcat + servlet-api + 6.0.32 + test + + + + javax.servlet + + + + javax/servlet/resources/XMLSchema.dtd + javax/servlet/resources/datatypes.dtd + javax/servlet/resources/j2ee_1_4.xsd + javax/servlet/resources/j2ee_web_services_client_1_1.xsd + javax/servlet/resources/web-app_2_2.dtd + javax/servlet/resources/web-app_2_3.dtd + javax/servlet/resources/web-app_2_4.xsd + javax/servlet/resources/web-app_2_5.xsd + javax/servlet/resources/xml.xsd + javax/servlet/LocalStrings.properties + javax/servlet/http/LocalStrings.properties + + + + + + + org.apache.tomcat + catalina + 6.0.32 + test + + + org.apache.tomcat + jasper + 6.0.32 + test + + + + org.apache.AnnotationProcessor + org.apache.PeriodicEventListener + + + + + diff --git a/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/paas/config/HttpClientModule.java b/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/paas/config/HttpClientModule.java new file mode 100644 index 0000000000..5aa077b6cd --- /dev/null +++ b/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/paas/config/HttpClientModule.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.demo.paas.config; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.inject.name.Names.bindProperties; +import static org.jclouds.Constants.*; + +import java.util.Properties; + +import javax.servlet.ServletContext; +import javax.ws.rs.core.UriBuilder; + +import org.jclouds.demo.tweetstore.config.util.PropertiesLoader; + +import com.google.inject.AbstractModule; +import com.sun.jersey.api.uri.UriBuilderImpl; + +/** + * @author Andrew Phillips + */ +public class HttpClientModule extends AbstractModule { + private final ServletContext context; + + HttpClientModule(ServletContext context) { + this.context = context; + } + + @Override + protected void configure() { + // URL connection defaults + Properties toBind = defaultProperties(); + toBind.putAll(checkNotNull(new PropertiesLoader(context).get(), "properties")); + toBind.putAll(System.getProperties()); + bindProperties(binder(), toBind); + bind(UriBuilder.class).to(UriBuilderImpl.class); + } + + private static Properties defaultProperties() { + Properties props = new Properties(); + props.setProperty(PROPERTY_MAX_CONNECTIONS_PER_CONTEXT, 20 + ""); + props.setProperty(PROPERTY_MAX_CONNECTIONS_PER_HOST, 0 + ""); + props.setProperty(PROPERTY_SO_TIMEOUT, 60000 + ""); + props.setProperty(PROPERTY_CONNECTION_TIMEOUT, 60000 + ""); + props.setProperty(PROPERTY_USER_THREADS, 0 + ""); + props.setProperty(PROPERTY_IO_WORKER_THREADS, 20 + ""); + return props; + } +} diff --git a/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/paas/config/PlatformServicesInitializer.java b/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/paas/config/PlatformServicesInitializer.java index 5e3bd69892..fd70aaa688 100644 --- a/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/paas/config/PlatformServicesInitializer.java +++ b/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/paas/config/PlatformServicesInitializer.java @@ -19,30 +19,22 @@ package org.jclouds.demo.paas.config; import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.inject.name.Names.bindProperties; import static java.lang.String.format; import static java.util.concurrent.TimeUnit.SECONDS; -import java.util.Properties; - import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; -import javax.ws.rs.core.UriBuilder; -import org.jclouds.PropertiesBuilder; import org.jclouds.concurrent.config.ExecutorServiceModule; import org.jclouds.demo.paas.PlatformServices; import org.jclouds.demo.paas.service.taskqueue.TaskQueue; -import org.jclouds.demo.tweetstore.config.util.PropertiesLoader; import org.jclouds.http.HttpCommandExecutorService; import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap.Builder; -import com.google.inject.AbstractModule; import com.google.inject.Guice; -import com.sun.jersey.api.uri.UriBuilderImpl; /** * @author Andrew Phillips @@ -69,17 +61,8 @@ public class PlatformServicesInitializer implements ServletContextListener { final ServletContext context) { return Guice.createInjector(new ExecutorServiceModule(), new JavaUrlHttpCommandExecutorServiceModule(), - new AbstractModule() { - @Override - protected void configure() { - // URL connection defaults - Properties toBind = new PropertiesBuilder().build(); - toBind.putAll(checkNotNull(new PropertiesLoader(context).get(), "properties")); - toBind.putAll(System.getProperties()); - bindProperties(binder(), toBind); - bind(UriBuilder.class).to(UriBuilderImpl.class); - } - }).getInstance(HttpCommandExecutorService.class); + new HttpClientModule(context)) + .getInstance(HttpCommandExecutorService.class); } protected static String getBaseUrl(ServletContext context) { diff --git a/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java b/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java index a294878748..24d0c94c06 100644 --- a/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java +++ b/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java @@ -38,8 +38,8 @@ import java.util.Set; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.demo.paas.PlatformServices; import org.jclouds.demo.paas.service.taskqueue.TaskQueue; import org.jclouds.demo.tweetstore.config.util.CredentialsCollector; @@ -70,7 +70,7 @@ import com.google.inject.servlet.ServletModule; * @author Adrian Cole */ public class GuiceServletConfig extends GuiceServletContextListener { - private Map> providerTypeToBlobStoreMap; + private Map providerTypeToBlobStoreMap; private Twitter twitterClient; private String container; private TaskQueue queue; @@ -100,8 +100,8 @@ public class GuiceServletConfig extends GuiceServletContextListener { // instantiate and store references to all blobstores by provider name providerTypeToBlobStoreMap = Maps.newHashMap(); for (String hint : getBlobstoreContexts(props)) { - providerTypeToBlobStoreMap.put(hint, BlobStoreContextBuilder - .newBuilder(hint).modules(modules).overrides(props).build()); + providerTypeToBlobStoreMap.put(hint, ContextBuilder.newBuilder(hint) + .modules(modules).overrides(props).build(BlobStoreContext.class)); } // get a queue for submitting store tweet requests and the application's base URL @@ -127,7 +127,7 @@ public class GuiceServletConfig extends GuiceServletContextListener { return Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { - bind(new TypeLiteral>>() {}) + bind(new TypeLiteral>() {}) .toInstance(providerTypeToBlobStoreMap); bind(Twitter.class).toInstance(twitterClient); bind(TaskQueue.class).toInstance(queue); @@ -144,7 +144,7 @@ public class GuiceServletConfig extends GuiceServletContextListener { @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { - for (BlobStoreContext context : providerTypeToBlobStoreMap.values()) { + for (BlobStoreContext context : providerTypeToBlobStoreMap.values()) { context.close(); } queue.destroy(); diff --git a/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/AddTweetsController.java b/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/AddTweetsController.java index 1805ee8f5c..007fbafdef 100644 --- a/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/AddTweetsController.java +++ b/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/AddTweetsController.java @@ -54,14 +54,14 @@ public class AddTweetsController extends HttpServlet implements /** The serialVersionUID */ private static final long serialVersionUID = 3888348023150822683L; - private final Map> contexts; + private final Map contexts; private final ServiceToStoredTweetStatuses blobStoreContextToContainerResult; @Resource protected Logger logger = Logger.NULL; @Inject - AddTweetsController(Map> contexts, + AddTweetsController(Map contexts, ServiceToStoredTweetStatuses blobStoreContextToContainerResult) { this.contexts = contexts; this.blobStoreContextToContainerResult = blobStoreContextToContainerResult; diff --git a/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresController.java b/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresController.java index 1c653c2824..937766c460 100644 --- a/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresController.java +++ b/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresController.java @@ -64,7 +64,7 @@ public class EnqueueStoresController extends HttpServlet { protected Logger logger = Logger.NULL; @Inject - public EnqueueStoresController(Map> contexts, TaskQueue taskQueue, + public EnqueueStoresController(Map contexts, TaskQueue taskQueue, @Named(PaasConstants.PROPERTY_PLATFORM_BASE_URL) String baseUrl) { contextNames = contexts.keySet(); this.taskQueue = taskQueue; diff --git a/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java b/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java index edd750e90d..948c9ff4ca 100644 --- a/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java +++ b/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java @@ -75,7 +75,7 @@ public class StoreTweetsController extends HttpServlet { /** The serialVersionUID */ private static final long serialVersionUID = 7215420527854203714L; - private final Map> contexts; + private final Map contexts; private final Twitter client; private final String container; @@ -84,7 +84,7 @@ public class StoreTweetsController extends HttpServlet { @Inject @VisibleForTesting - public StoreTweetsController(Map> contexts, + public StoreTweetsController(Map contexts, @Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) String container, Twitter client) { this.container = container; this.contexts = contexts; @@ -93,7 +93,7 @@ public class StoreTweetsController extends HttpServlet { @VisibleForTesting public void addMyTweets(String contextName, Iterable responseList) { - BlobStoreContext context = checkNotNull(contexts.get(contextName), "no context for " + contextName + " in " + BlobStoreContext context = checkNotNull(contexts.get(contextName), "no context for " + contextName + " in " + contexts.keySet()); BlobMap map = context.createBlobMap(container); for (Status status : responseList) { diff --git a/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatuses.java b/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatuses.java index 36437544d4..b29ec14549 100644 --- a/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatuses.java +++ b/demos/tweetstore/rhcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatuses.java @@ -18,6 +18,7 @@ */ package org.jclouds.demo.tweetstore.functions; +import java.net.URI; import java.util.Collections; import java.util.Map; import java.util.Set; @@ -27,6 +28,7 @@ import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; +import org.jclouds.Context; import org.jclouds.blobstore.BlobMap; import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; @@ -39,11 +41,11 @@ import com.google.common.collect.Iterables; @Singleton public class ServiceToStoredTweetStatuses implements Function> { - private final Map> contexts; + private final Map contexts; private final String container; @Inject - public ServiceToStoredTweetStatuses(Map> contexts, + public ServiceToStoredTweetStatuses(Map contexts, @Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) String container) { this.contexts = contexts; this.container = container; @@ -53,8 +55,8 @@ public class ServiceToStoredTweetStatuses implements Function apply(String service) { - BlobStoreContext context = contexts.get(service); - String host = context.getProviderSpecificContext().getEndpoint().getHost(); + BlobStoreContext context = contexts.get(service); + String host = URI.create(context.unwrap(Context.class).getProviderMetadata().getEndpoint()).getHost(); try { BlobMap blobMap = context.createBlobMap(container); Set blobs = blobMap.keySet(); diff --git a/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java b/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java index d6989d8bbe..1c93403650 100644 --- a/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java +++ b/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java @@ -25,8 +25,8 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; @@ -46,12 +46,12 @@ import com.google.common.collect.ImmutableSet; @Test(groups = "unit") public class AddTweetsControllerTest { - Map> createServices(String container) throws InterruptedException, + Map createServices(String container) throws InterruptedException, ExecutionException { - Map> services = Maps.newHashMap(); + Map services = Maps.newHashMap(); TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build(); for (String name : new String[] { "1", "2" }) { - BlobStoreContext context = BlobStoreContextBuilder.newBuilder(transientApiMetadata).build(); + BlobStoreContext context = ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class); context.getAsyncBlobStore().createContainerInLocation(null, container).get(); Blob blob = context.getAsyncBlobStore().blobBuilder("1").build(); blob.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, "frank"); @@ -64,7 +64,7 @@ public class AddTweetsControllerTest { public void testStoreTweets() throws IOException, InterruptedException, ExecutionException { String container = "container"; - Map> contexts = createServices(container); + Map contexts = createServices(container); ServiceToStoredTweetStatuses function = new ServiceToStoredTweetStatuses(contexts, container); AddTweetsController controller = new AddTweetsController(contexts, function); diff --git a/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresControllerTest.java b/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresControllerTest.java index c324579f82..3c5e5b1d80 100644 --- a/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresControllerTest.java +++ b/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresControllerTest.java @@ -23,8 +23,8 @@ import static org.easymock.EasyMock.*; import java.net.URI; import java.util.Map; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.demo.paas.RunnableHttpRequest; import org.jclouds.demo.paas.RunnableHttpRequest.Factory; @@ -43,16 +43,16 @@ import com.google.common.collect.ImmutableMultimap; @Test(groups = "unit") public class EnqueueStoresControllerTest { - Map> createBlobStores() { + Map createBlobStores() { TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build(); - Map> contexts = ImmutableMap.>of( - "test1", BlobStoreContextBuilder.newBuilder(transientApiMetadata).build(), - "test2", BlobStoreContextBuilder.newBuilder(transientApiMetadata).build()); + Map contexts = ImmutableMap.of( + "test1", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class), + "test2", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class)); return contexts; } public void testEnqueueStores() { - Map> stores = createBlobStores(); + Map stores = createBlobStores(); TaskQueue taskQueue = createMock(TaskQueue.class); Factory httpRequestFactory = createMock(Factory.class); EnqueueStoresController function = new EnqueueStoresController(stores, diff --git a/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java b/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java index ac7c1332e0..7afdb30384 100644 --- a/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java +++ b/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java @@ -30,9 +30,9 @@ import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ExecutionException; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobMap; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.reference.TweetStoreConstants; @@ -57,19 +57,19 @@ public class StoreTweetsControllerTest { return createMock(Twitter.class); } - Map> createBlobStores() throws InterruptedException, ExecutionException { + Map createBlobStores() throws InterruptedException, ExecutionException { TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build(); - Map> contexts = ImmutableMap.>of( - "test1", BlobStoreContextBuilder.newBuilder(transientApiMetadata).build(), - "test2", BlobStoreContextBuilder.newBuilder(transientApiMetadata).build()); - for (BlobStoreContext blobstore : contexts.values()) { + Map contexts = ImmutableMap.of( + "test1", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class), + "test2", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class)); + for (BlobStoreContext blobstore : contexts.values()) { blobstore.getAsyncBlobStore().createContainerInLocation(null, "favo").get(); } return contexts; } public void testStoreTweets() throws IOException, InterruptedException, ExecutionException { - Map> stores = createBlobStores(); + Map stores = createBlobStores(); StoreTweetsController function = new StoreTweetsController(stores, "favo", createTwitter()); User frank = createMock(User.class); @@ -101,7 +101,7 @@ public class StoreTweetsControllerTest { verify(jimmy); verify(jimmyStatus); - for (Entry> entry : stores.entrySet()) { + for (Entry entry : stores.entrySet()) { BlobMap map = entry.getValue().createBlobMap("favo"); Blob frankBlob = map.get("1"); assertEquals(frankBlob.getMetadata().getName(), "1"); diff --git a/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java b/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java index a85df55fc8..aab06ec0b6 100644 --- a/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java +++ b/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java @@ -23,9 +23,9 @@ import static org.testng.Assert.assertEquals; import java.io.IOException; import java.util.concurrent.ExecutionException; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobMap; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; @@ -41,8 +41,8 @@ import org.testng.annotations.Test; public class KeyToStoredTweetStatusTest { BlobMap createMap() throws InterruptedException, ExecutionException { - BlobStoreContext context = - BlobStoreContextBuilder.newBuilder(TransientApiMetadata.builder().build()).build(); + BlobStoreContext context = + ContextBuilder.newBuilder(TransientApiMetadata.builder().build()).build(BlobStoreContext.class); context.getBlobStore().createContainerInLocation(null, "test1"); return context.createBlobMap("test1"); } diff --git a/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java b/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java index 54deb948db..5fec52711e 100644 --- a/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java +++ b/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java @@ -24,8 +24,8 @@ import java.io.IOException; import java.util.Map; import java.util.concurrent.ExecutionException; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; @@ -43,12 +43,12 @@ import com.google.common.collect.Iterables; @Test(groups = "unit") public class ServiceToStoredTweetStatusesTest { - Map> createServices(String container) throws InterruptedException, + Map createServices(String container) throws InterruptedException, ExecutionException { - Map> services = Maps.newHashMap(); + Map services = Maps.newHashMap(); TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build(); for (String name : new String[] { "1", "2" }) { - BlobStoreContext context = BlobStoreContextBuilder.newBuilder(transientApiMetadata).build(); + BlobStoreContext context = ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class); context.getAsyncBlobStore().createContainerInLocation(null, container).get(); Blob blob = context.getAsyncBlobStore().blobBuilder("1").build(); blob.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, "frank"); @@ -61,7 +61,7 @@ public class ServiceToStoredTweetStatusesTest { public void testStoreTweets() throws IOException, InterruptedException, ExecutionException { String container = "container"; - Map> contexts = createServices(container); + Map contexts = createServices(container); ServiceToStoredTweetStatuses function = new ServiceToStoredTweetStatuses(contexts, container); diff --git a/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java b/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java index 7681cf1297..f66308f244 100644 --- a/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java +++ b/demos/tweetstore/rhcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java @@ -38,8 +38,9 @@ import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; +import org.jclouds.Context; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.demo.tweetstore.controller.StoreTweetsController; import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.rest.AuthorizationException; @@ -73,7 +74,7 @@ public class TweetStoreLiveTest { RhcloudServer server; private URL url; - private Map> contexts; + private Map contexts; private String container; private static final Iterable blobstores = Splitter.on(',').split(getRequiredSystemProperty(PROPERTY_TWEETSTORE_BLOBSTORES)); @@ -97,8 +98,8 @@ public class TweetStoreLiveTest { this.contexts = Maps.newConcurrentMap(); for (String provider : blobstores) { - contexts.put(provider, BlobStoreContextBuilder.newBuilder(provider) - .modules(wiring).overrides(props).build()); + contexts.put(provider, ContextBuilder.newBuilder(provider) + .modules(wiring).overrides(props).build(BlobStoreContext.class)); } Configuration conf = new ConfigurationBuilder() @@ -113,11 +114,11 @@ public class TweetStoreLiveTest { ResponseList statuses = client.getMentions(); boolean deleted = false; - for (BlobStoreContext context : contexts.values()) { + for (BlobStoreContext context : contexts.values()) { try { if (context.getBlobStore().containerExists(container)) { - System.err.printf("deleting container %s at %s%n", container, context.getProviderSpecificContext() - .getEndpoint()); + System.err.printf("deleting container %s at %s%n", container, + context.unwrap(Context.class).getProviderMetadata().getEndpoint()); context.getBlobStore().deleteContainer(container); deleted = true; } @@ -129,9 +130,9 @@ public class TweetStoreLiveTest { System.err.println("sleeping 60 seconds to allow containers to clear"); Thread.sleep(60000); } - for (BlobStoreContext context : contexts.values()) { - System.err.printf("creating container %s at %s%n", container, context.getProviderSpecificContext() - .getEndpoint()); + for (BlobStoreContext context : contexts.values()) { + System.err.printf("creating container %s at %s%n", container, + context.unwrap(Context.class).getProviderMetadata().getEndpoint()); context.getBlobStore().createContainerInLocation(null, container); } @@ -140,7 +141,7 @@ public class TweetStoreLiveTest { Thread.sleep(5000); } - for (Entry> entry : contexts.entrySet()) { + for (Entry entry : contexts.entrySet()) { System.err.printf("filling container %s at %s%n", container, entry.getKey()); controller.addMyTweets(entry.getKey(), statuses); } @@ -209,8 +210,8 @@ public class TweetStoreLiveTest { System.err.println("sleeping 20 seconds to allow for eventual consistency delay"); Thread.sleep(20000); - for (BlobStoreContext context : contexts.values()) { - assert context.createInputStreamMap(container).size() > 0 : context.getProviderSpecificContext().getEndpoint(); + for (BlobStoreContext context : contexts.values()) { + assert context.createInputStreamMap(container).size() > 0 : context.unwrap(Context.class).getProviderMetadata().getEndpoint(); } } diff --git a/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/paas/config/HttpClientModule.java b/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/paas/config/HttpClientModule.java new file mode 100644 index 0000000000..5aa077b6cd --- /dev/null +++ b/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/paas/config/HttpClientModule.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.demo.paas.config; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.inject.name.Names.bindProperties; +import static org.jclouds.Constants.*; + +import java.util.Properties; + +import javax.servlet.ServletContext; +import javax.ws.rs.core.UriBuilder; + +import org.jclouds.demo.tweetstore.config.util.PropertiesLoader; + +import com.google.inject.AbstractModule; +import com.sun.jersey.api.uri.UriBuilderImpl; + +/** + * @author Andrew Phillips + */ +public class HttpClientModule extends AbstractModule { + private final ServletContext context; + + HttpClientModule(ServletContext context) { + this.context = context; + } + + @Override + protected void configure() { + // URL connection defaults + Properties toBind = defaultProperties(); + toBind.putAll(checkNotNull(new PropertiesLoader(context).get(), "properties")); + toBind.putAll(System.getProperties()); + bindProperties(binder(), toBind); + bind(UriBuilder.class).to(UriBuilderImpl.class); + } + + private static Properties defaultProperties() { + Properties props = new Properties(); + props.setProperty(PROPERTY_MAX_CONNECTIONS_PER_CONTEXT, 20 + ""); + props.setProperty(PROPERTY_MAX_CONNECTIONS_PER_HOST, 0 + ""); + props.setProperty(PROPERTY_SO_TIMEOUT, 60000 + ""); + props.setProperty(PROPERTY_CONNECTION_TIMEOUT, 60000 + ""); + props.setProperty(PROPERTY_USER_THREADS, 0 + ""); + props.setProperty(PROPERTY_IO_WORKER_THREADS, 20 + ""); + return props; + } +} diff --git a/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/paas/config/PlatformServicesInitializer.java b/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/paas/config/PlatformServicesInitializer.java index bb02bbbda8..ee74adaf6e 100644 --- a/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/paas/config/PlatformServicesInitializer.java +++ b/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/paas/config/PlatformServicesInitializer.java @@ -19,30 +19,22 @@ package org.jclouds.demo.paas.config; import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.inject.name.Names.bindProperties; import static java.util.concurrent.TimeUnit.SECONDS; -import java.util.Properties; - import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; -import javax.ws.rs.core.UriBuilder; -import org.jclouds.PropertiesBuilder; import org.jclouds.concurrent.config.ExecutorServiceModule; import org.jclouds.demo.paas.PlatformServices; import org.jclouds.demo.paas.service.scheduler.Scheduler; import org.jclouds.demo.paas.service.taskqueue.TaskQueue; -import org.jclouds.demo.tweetstore.config.util.PropertiesLoader; import org.jclouds.http.HttpCommandExecutorService; import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap.Builder; -import com.google.inject.AbstractModule; import com.google.inject.Guice; -import com.sun.jersey.api.uri.UriBuilderImpl; /** * @author Andrew Phillips @@ -69,17 +61,8 @@ public class PlatformServicesInitializer implements ServletContextListener { final ServletContext context) { return Guice.createInjector(new ExecutorServiceModule(), new JavaUrlHttpCommandExecutorServiceModule(), - new AbstractModule() { - @Override - protected void configure() { - // URL connection defaults - Properties toBind = new PropertiesBuilder().build(); - toBind.putAll(checkNotNull(new PropertiesLoader(context).get(), "properties")); - toBind.putAll(System.getProperties()); - bindProperties(binder(), toBind); - bind(UriBuilder.class).to(UriBuilderImpl.class); - } - }).getInstance(HttpCommandExecutorService.class); + new HttpClientModule(context)) + .getInstance(HttpCommandExecutorService.class); } protected static String getBaseUrl(ServletContext context) { diff --git a/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java b/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java index a294878748..24d0c94c06 100644 --- a/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java +++ b/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/config/GuiceServletConfig.java @@ -38,8 +38,8 @@ import java.util.Set; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.demo.paas.PlatformServices; import org.jclouds.demo.paas.service.taskqueue.TaskQueue; import org.jclouds.demo.tweetstore.config.util.CredentialsCollector; @@ -70,7 +70,7 @@ import com.google.inject.servlet.ServletModule; * @author Adrian Cole */ public class GuiceServletConfig extends GuiceServletContextListener { - private Map> providerTypeToBlobStoreMap; + private Map providerTypeToBlobStoreMap; private Twitter twitterClient; private String container; private TaskQueue queue; @@ -100,8 +100,8 @@ public class GuiceServletConfig extends GuiceServletContextListener { // instantiate and store references to all blobstores by provider name providerTypeToBlobStoreMap = Maps.newHashMap(); for (String hint : getBlobstoreContexts(props)) { - providerTypeToBlobStoreMap.put(hint, BlobStoreContextBuilder - .newBuilder(hint).modules(modules).overrides(props).build()); + providerTypeToBlobStoreMap.put(hint, ContextBuilder.newBuilder(hint) + .modules(modules).overrides(props).build(BlobStoreContext.class)); } // get a queue for submitting store tweet requests and the application's base URL @@ -127,7 +127,7 @@ public class GuiceServletConfig extends GuiceServletContextListener { return Guice.createInjector(new ServletModule() { @Override protected void configureServlets() { - bind(new TypeLiteral>>() {}) + bind(new TypeLiteral>() {}) .toInstance(providerTypeToBlobStoreMap); bind(Twitter.class).toInstance(twitterClient); bind(TaskQueue.class).toInstance(queue); @@ -144,7 +144,7 @@ public class GuiceServletConfig extends GuiceServletContextListener { @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { - for (BlobStoreContext context : providerTypeToBlobStoreMap.values()) { + for (BlobStoreContext context : providerTypeToBlobStoreMap.values()) { context.close(); } queue.destroy(); diff --git a/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/AddTweetsController.java b/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/AddTweetsController.java index 1805ee8f5c..007fbafdef 100644 --- a/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/AddTweetsController.java +++ b/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/AddTweetsController.java @@ -54,14 +54,14 @@ public class AddTweetsController extends HttpServlet implements /** The serialVersionUID */ private static final long serialVersionUID = 3888348023150822683L; - private final Map> contexts; + private final Map contexts; private final ServiceToStoredTweetStatuses blobStoreContextToContainerResult; @Resource protected Logger logger = Logger.NULL; @Inject - AddTweetsController(Map> contexts, + AddTweetsController(Map contexts, ServiceToStoredTweetStatuses blobStoreContextToContainerResult) { this.contexts = contexts; this.blobStoreContextToContainerResult = blobStoreContextToContainerResult; diff --git a/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresController.java b/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresController.java index 71b715863b..592eaaa8bd 100644 --- a/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresController.java +++ b/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresController.java @@ -65,7 +65,7 @@ public class EnqueueStoresController extends HttpServlet { protected Logger logger = Logger.NULL; @Inject - public EnqueueStoresController(Map> contexts, TaskQueue taskQueue, + public EnqueueStoresController(Map contexts, TaskQueue taskQueue, @Named(PaasConstants.PROPERTY_PLATFORM_BASE_URL) String baseUrl) { contextNames = contexts.keySet(); this.taskQueue = taskQueue; diff --git a/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java b/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java index edd750e90d..948c9ff4ca 100644 --- a/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java +++ b/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/controller/StoreTweetsController.java @@ -75,7 +75,7 @@ public class StoreTweetsController extends HttpServlet { /** The serialVersionUID */ private static final long serialVersionUID = 7215420527854203714L; - private final Map> contexts; + private final Map contexts; private final Twitter client; private final String container; @@ -84,7 +84,7 @@ public class StoreTweetsController extends HttpServlet { @Inject @VisibleForTesting - public StoreTweetsController(Map> contexts, + public StoreTweetsController(Map contexts, @Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) String container, Twitter client) { this.container = container; this.contexts = contexts; @@ -93,7 +93,7 @@ public class StoreTweetsController extends HttpServlet { @VisibleForTesting public void addMyTweets(String contextName, Iterable responseList) { - BlobStoreContext context = checkNotNull(contexts.get(contextName), "no context for " + contextName + " in " + BlobStoreContext context = checkNotNull(contexts.get(contextName), "no context for " + contextName + " in " + contexts.keySet()); BlobMap map = context.createBlobMap(container); for (Status status : responseList) { diff --git a/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatuses.java b/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatuses.java index 36437544d4..b29ec14549 100644 --- a/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatuses.java +++ b/demos/tweetstore/runatcloud-tweetstore/src/main/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatuses.java @@ -18,6 +18,7 @@ */ package org.jclouds.demo.tweetstore.functions; +import java.net.URI; import java.util.Collections; import java.util.Map; import java.util.Set; @@ -27,6 +28,7 @@ import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; +import org.jclouds.Context; import org.jclouds.blobstore.BlobMap; import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; @@ -39,11 +41,11 @@ import com.google.common.collect.Iterables; @Singleton public class ServiceToStoredTweetStatuses implements Function> { - private final Map> contexts; + private final Map contexts; private final String container; @Inject - public ServiceToStoredTweetStatuses(Map> contexts, + public ServiceToStoredTweetStatuses(Map contexts, @Named(TweetStoreConstants.PROPERTY_TWEETSTORE_CONTAINER) String container) { this.contexts = contexts; this.container = container; @@ -53,8 +55,8 @@ public class ServiceToStoredTweetStatuses implements Function apply(String service) { - BlobStoreContext context = contexts.get(service); - String host = context.getProviderSpecificContext().getEndpoint().getHost(); + BlobStoreContext context = contexts.get(service); + String host = URI.create(context.unwrap(Context.class).getProviderMetadata().getEndpoint()).getHost(); try { BlobMap blobMap = context.createBlobMap(container); Set blobs = blobMap.keySet(); diff --git a/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java b/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java index d6989d8bbe..1c93403650 100644 --- a/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java +++ b/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/AddTweetsControllerTest.java @@ -25,8 +25,8 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; @@ -46,12 +46,12 @@ import com.google.common.collect.ImmutableSet; @Test(groups = "unit") public class AddTweetsControllerTest { - Map> createServices(String container) throws InterruptedException, + Map createServices(String container) throws InterruptedException, ExecutionException { - Map> services = Maps.newHashMap(); + Map services = Maps.newHashMap(); TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build(); for (String name : new String[] { "1", "2" }) { - BlobStoreContext context = BlobStoreContextBuilder.newBuilder(transientApiMetadata).build(); + BlobStoreContext context = ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class); context.getAsyncBlobStore().createContainerInLocation(null, container).get(); Blob blob = context.getAsyncBlobStore().blobBuilder("1").build(); blob.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, "frank"); @@ -64,7 +64,7 @@ public class AddTweetsControllerTest { public void testStoreTweets() throws IOException, InterruptedException, ExecutionException { String container = "container"; - Map> contexts = createServices(container); + Map contexts = createServices(container); ServiceToStoredTweetStatuses function = new ServiceToStoredTweetStatuses(contexts, container); AddTweetsController controller = new AddTweetsController(contexts, function); diff --git a/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresControllerTest.java b/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresControllerTest.java index c324579f82..3c5e5b1d80 100644 --- a/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresControllerTest.java +++ b/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/EnqueueStoresControllerTest.java @@ -23,8 +23,8 @@ import static org.easymock.EasyMock.*; import java.net.URI; import java.util.Map; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.demo.paas.RunnableHttpRequest; import org.jclouds.demo.paas.RunnableHttpRequest.Factory; @@ -43,16 +43,16 @@ import com.google.common.collect.ImmutableMultimap; @Test(groups = "unit") public class EnqueueStoresControllerTest { - Map> createBlobStores() { + Map createBlobStores() { TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build(); - Map> contexts = ImmutableMap.>of( - "test1", BlobStoreContextBuilder.newBuilder(transientApiMetadata).build(), - "test2", BlobStoreContextBuilder.newBuilder(transientApiMetadata).build()); + Map contexts = ImmutableMap.of( + "test1", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class), + "test2", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class)); return contexts; } public void testEnqueueStores() { - Map> stores = createBlobStores(); + Map stores = createBlobStores(); TaskQueue taskQueue = createMock(TaskQueue.class); Factory httpRequestFactory = createMock(Factory.class); EnqueueStoresController function = new EnqueueStoresController(stores, diff --git a/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java b/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java index 767245cdf7..9cc56351f2 100644 --- a/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java +++ b/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/controller/StoreTweetsControllerTest.java @@ -30,9 +30,9 @@ import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ExecutionException; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobMap; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.reference.TweetStoreConstants; @@ -57,19 +57,19 @@ public class StoreTweetsControllerTest { return createMock(Twitter.class); } - Map> createBlobStores() throws InterruptedException, ExecutionException { + Map createBlobStores() throws InterruptedException, ExecutionException { TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build(); - Map> contexts = ImmutableMap.>of( - "test1", BlobStoreContextBuilder.newBuilder(transientApiMetadata).build(), - "test2", BlobStoreContextBuilder.newBuilder(transientApiMetadata).build()); - for (BlobStoreContext blobstore : contexts.values()) { + Map contexts = ImmutableMap.of( + "test1", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class), + "test2", ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class)); + for (BlobStoreContext blobstore : contexts.values()) { blobstore.getAsyncBlobStore().createContainerInLocation(null, "favo").get(); } return contexts; } public void testStoreTweets() throws IOException, InterruptedException, ExecutionException { - Map> stores = createBlobStores(); + Map stores = createBlobStores(); StoreTweetsController function = new StoreTweetsController(stores, "favo", createTwitter()); User frank = createMock(User.class); @@ -101,7 +101,7 @@ public class StoreTweetsControllerTest { verify(jimmy); verify(jimmyStatus); - for (Entry> entry : stores.entrySet()) { + for (Entry entry : stores.entrySet()) { BlobMap map = entry.getValue().createBlobMap("favo"); Blob frankBlob = map.get("1"); assertEquals(frankBlob.getMetadata().getName(), "1"); diff --git a/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java b/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java index a85df55fc8..aab06ec0b6 100644 --- a/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java +++ b/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/KeyToStoredTweetStatusTest.java @@ -23,9 +23,9 @@ import static org.testng.Assert.assertEquals; import java.io.IOException; import java.util.concurrent.ExecutionException; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobMap; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; @@ -41,8 +41,8 @@ import org.testng.annotations.Test; public class KeyToStoredTweetStatusTest { BlobMap createMap() throws InterruptedException, ExecutionException { - BlobStoreContext context = - BlobStoreContextBuilder.newBuilder(TransientApiMetadata.builder().build()).build(); + BlobStoreContext context = + ContextBuilder.newBuilder(TransientApiMetadata.builder().build()).build(BlobStoreContext.class); context.getBlobStore().createContainerInLocation(null, "test1"); return context.createBlobMap("test1"); } diff --git a/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java b/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java index 54deb948db..5fec52711e 100644 --- a/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java +++ b/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/functions/ServiceToStoredTweetStatusesTest.java @@ -24,8 +24,8 @@ import java.io.IOException; import java.util.Map; import java.util.concurrent.ExecutionException; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.blobstore.TransientApiMetadata; import org.jclouds.blobstore.domain.Blob; import org.jclouds.demo.tweetstore.domain.StoredTweetStatus; @@ -43,12 +43,12 @@ import com.google.common.collect.Iterables; @Test(groups = "unit") public class ServiceToStoredTweetStatusesTest { - Map> createServices(String container) throws InterruptedException, + Map createServices(String container) throws InterruptedException, ExecutionException { - Map> services = Maps.newHashMap(); + Map services = Maps.newHashMap(); TransientApiMetadata transientApiMetadata = TransientApiMetadata.builder().build(); for (String name : new String[] { "1", "2" }) { - BlobStoreContext context = BlobStoreContextBuilder.newBuilder(transientApiMetadata).build(); + BlobStoreContext context = ContextBuilder.newBuilder(transientApiMetadata).build(BlobStoreContext.class); context.getAsyncBlobStore().createContainerInLocation(null, container).get(); Blob blob = context.getAsyncBlobStore().blobBuilder("1").build(); blob.getMetadata().getUserMetadata().put(TweetStoreConstants.SENDER_NAME, "frank"); @@ -61,7 +61,7 @@ public class ServiceToStoredTweetStatusesTest { public void testStoreTweets() throws IOException, InterruptedException, ExecutionException { String container = "container"; - Map> contexts = createServices(container); + Map contexts = createServices(container); ServiceToStoredTweetStatuses function = new ServiceToStoredTweetStatuses(contexts, container); diff --git a/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java b/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java index 303e1ec9d9..207ec2b6e6 100644 --- a/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java +++ b/demos/tweetstore/runatcloud-tweetstore/src/test/java/org/jclouds/demo/tweetstore/integration/TweetStoreLiveTest.java @@ -38,8 +38,9 @@ import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; +import org.jclouds.Context; +import org.jclouds.ContextBuilder; import org.jclouds.blobstore.BlobStoreContext; -import org.jclouds.blobstore.BlobStoreContextBuilder; import org.jclouds.demo.tweetstore.controller.StoreTweetsController; import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.rest.AuthorizationException; @@ -73,7 +74,7 @@ public class TweetStoreLiveTest { RunAtCloudServer server; private URL url; - private Map> contexts; + private Map contexts; private String container; private static final Iterable blobstores = Splitter.on(',').split(getRequiredSystemProperty(PROPERTY_TWEETSTORE_BLOBSTORES)); @@ -97,8 +98,8 @@ public class TweetStoreLiveTest { this.contexts = Maps.newConcurrentMap(); for (String provider : blobstores) { - contexts.put(provider, BlobStoreContextBuilder.newBuilder(provider) - .modules(wiring).overrides(props).build()); + contexts.put(provider, ContextBuilder.newBuilder(provider) + .modules(wiring).overrides(props).build(BlobStoreContext.class)); } Configuration conf = new ConfigurationBuilder() @@ -113,11 +114,11 @@ public class TweetStoreLiveTest { ResponseList statuses = client.getMentions(); boolean deleted = false; - for (BlobStoreContext context : contexts.values()) { + for (BlobStoreContext context : contexts.values()) { try { if (context.getBlobStore().containerExists(container)) { - System.err.printf("deleting container %s at %s%n", container, context.getProviderSpecificContext() - .getEndpoint()); + System.err.printf("deleting container %s at %s%n", container, + context.unwrap(Context.class).getProviderMetadata().getEndpoint()); context.getBlobStore().deleteContainer(container); deleted = true; } @@ -129,9 +130,9 @@ public class TweetStoreLiveTest { System.err.println("sleeping 60 seconds to allow containers to clear"); Thread.sleep(60000); } - for (BlobStoreContext context : contexts.values()) { - System.err.printf("creating container %s at %s%n", container, context.getProviderSpecificContext() - .getEndpoint()); + for (BlobStoreContext context : contexts.values()) { + System.err.printf("creating container %s at %s%n", container, + context.unwrap(Context.class).getProviderMetadata().getEndpoint()); context.getBlobStore().createContainerInLocation(null, container); } @@ -140,7 +141,7 @@ public class TweetStoreLiveTest { Thread.sleep(5000); } - for (Entry> entry : contexts.entrySet()) { + for (Entry entry : contexts.entrySet()) { System.err.printf("filling container %s at %s%n", container, entry.getKey()); controller.addMyTweets(entry.getKey(), statuses); } @@ -210,8 +211,8 @@ public class TweetStoreLiveTest { System.err.println("sleeping 20 seconds to allow for eventual consistency delay"); Thread.sleep(20000); - for (BlobStoreContext context : contexts.values()) { - assert context.createInputStreamMap(container).size() > 0 : context.getProviderSpecificContext().getEndpoint(); + for (BlobStoreContext context : contexts.values()) { + assert context.createInputStreamMap(container).size() > 0 : context.unwrap(Context.class).getProviderMetadata().getEndpoint(); } } diff --git a/drivers/jsch/src/main/java/org/jclouds/ssh/jsch/JschSshClient.java b/drivers/jsch/src/main/java/org/jclouds/ssh/jsch/JschSshClient.java index e9ff64628b..85eb3e8d00 100644 --- a/drivers/jsch/src/main/java/org/jclouds/ssh/jsch/JschSshClient.java +++ b/drivers/jsch/src/main/java/org/jclouds/ssh/jsch/JschSshClient.java @@ -48,7 +48,6 @@ import org.jclouds.http.handlers.BackoffLimitedRetryHandler; import org.jclouds.io.Payload; import org.jclouds.io.Payloads; import org.jclouds.logging.Logger; -import org.jclouds.net.IPSocket; import org.jclouds.rest.AuthorizationException; import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshException; @@ -122,10 +121,10 @@ public class JschSshClient implements SshClient { final String user; final String host; - public JschSshClient(BackoffLimitedRetryHandler backoffLimitedRetryHandler, IPSocket socket, + public JschSshClient(BackoffLimitedRetryHandler backoffLimitedRetryHandler, HostAndPort socket, LoginCredentials loginCredentials, int timeout) { this.user = checkNotNull(loginCredentials, "loginCredentials").getUser(); - this.host = checkNotNull(socket, "socket").getAddress(); + this.host = checkNotNull(socket, "socket").getHostText(); checkArgument(socket.getPort() > 0, "ssh port must be greater then zero" + socket.getPort()); checkArgument(loginCredentials.getPassword() != null || loginCredentials.getPrivateKey() != null, "you must specify a password or a key"); diff --git a/drivers/jsch/src/main/java/org/jclouds/ssh/jsch/config/JschSshClientModule.java b/drivers/jsch/src/main/java/org/jclouds/ssh/jsch/config/JschSshClientModule.java index 93f2bde215..a8f4cd7a9f 100644 --- a/drivers/jsch/src/main/java/org/jclouds/ssh/jsch/config/JschSshClientModule.java +++ b/drivers/jsch/src/main/java/org/jclouds/ssh/jsch/config/JschSshClientModule.java @@ -24,13 +24,13 @@ import org.jclouds.Constants; import org.jclouds.domain.Credentials; import org.jclouds.domain.LoginCredentials; import org.jclouds.http.handlers.BackoffLimitedRetryHandler; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.InetSocketAddressConnect; import org.jclouds.predicates.SocketOpen; import org.jclouds.ssh.ConfiguresSshClient; import org.jclouds.ssh.SshClient; import org.jclouds.ssh.jsch.JschSshClient; +import com.google.common.net.HostAndPort; import com.google.inject.AbstractModule; import com.google.inject.Inject; import com.google.inject.Injector; @@ -64,14 +64,14 @@ public class JschSshClientModule extends AbstractModule { } @Override - public SshClient create(IPSocket socket, LoginCredentials credentials) { + public SshClient create(HostAndPort socket, LoginCredentials credentials) { SshClient client = new JschSshClient(backoffLimitedRetryHandler, socket, credentials, timeout); injector.injectMembers(client);// add logger return client; } @Override - public SshClient create(IPSocket socket, Credentials credentials) { + public SshClient create(HostAndPort socket, Credentials credentials) { return create(socket, LoginCredentials.fromCredentials(credentials)); } } diff --git a/drivers/jsch/src/test/java/org/jclouds/ssh/jsch/JschSshClientLiveTest.java b/drivers/jsch/src/test/java/org/jclouds/ssh/jsch/JschSshClientLiveTest.java index 71175793b3..f2a098b826 100644 --- a/drivers/jsch/src/test/java/org/jclouds/ssh/jsch/JschSshClientLiveTest.java +++ b/drivers/jsch/src/test/java/org/jclouds/ssh/jsch/JschSshClientLiveTest.java @@ -36,7 +36,6 @@ import org.jclouds.domain.LoginCredentials; import org.jclouds.io.Payload; import org.jclouds.io.Payloads; import org.jclouds.logging.slf4j.config.SLF4JLoggingModule; -import org.jclouds.net.IPSocket; import org.jclouds.ssh.SshClient; import org.jclouds.ssh.jsch.config.JschSshClientModule; import org.jclouds.util.Strings2; @@ -46,6 +45,7 @@ import org.testng.annotations.Test; import com.google.common.base.Strings; import com.google.common.base.Suppliers; import com.google.common.io.Closeables; +import com.google.common.net.HostAndPort; import com.google.inject.Guice; import com.google.inject.Injector; @@ -136,10 +136,10 @@ public class JschSshClientLiveTest { SshClient.Factory factory = i.getInstance(SshClient.Factory.class); SshClient connection; if (Strings.emptyToNull(sshKeyFile) != null) { - connection = factory.create(new IPSocket(sshHost, port), LoginCredentials.builder().user(sshUser) + connection = factory.create(HostAndPort.fromParts(sshHost, port), LoginCredentials.builder().user(sshUser) .privateKey(Strings2.toStringAndClose(new FileInputStream(sshKeyFile))).build()); } else { - connection = factory.create(new IPSocket(sshHost, port), + connection = factory.create(HostAndPort.fromParts(sshHost, port), LoginCredentials.builder().user(sshUser).password(sshPass).build()); } connection.connect(); diff --git a/drivers/jsch/src/test/java/org/jclouds/ssh/jsch/JschSshClientTest.java b/drivers/jsch/src/test/java/org/jclouds/ssh/jsch/JschSshClientTest.java index e15694d069..b62103a36e 100644 --- a/drivers/jsch/src/test/java/org/jclouds/ssh/jsch/JschSshClientTest.java +++ b/drivers/jsch/src/test/java/org/jclouds/ssh/jsch/JschSshClientTest.java @@ -27,13 +27,13 @@ import java.util.Properties; import org.jclouds.domain.LoginCredentials; import org.jclouds.logging.slf4j.config.SLF4JLoggingModule; -import org.jclouds.net.IPSocket; import org.jclouds.rest.AuthorizationException; import org.jclouds.ssh.SshClient; import org.jclouds.ssh.jsch.config.JschSshClientModule; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; +import com.google.common.net.HostAndPort; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; @@ -68,7 +68,7 @@ public class JschSshClientTest { } }, new SLF4JLoggingModule()); SshClient.Factory factory = i.getInstance(SshClient.Factory.class); - JschSshClient ssh = JschSshClient.class.cast(factory.create(new IPSocket("localhost", 22), LoginCredentials + JschSshClient ssh = JschSshClient.class.cast(factory.create(HostAndPort.fromParts("localhost", 22), LoginCredentials .builder().user("username").password("password").build())); return ssh; } diff --git a/drivers/jsch/src/test/java/org/jclouds/ssh/jsch/config/JschSshClientModuleTest.java b/drivers/jsch/src/test/java/org/jclouds/ssh/jsch/config/JschSshClientModuleTest.java index 135a511081..4793153db9 100644 --- a/drivers/jsch/src/test/java/org/jclouds/ssh/jsch/config/JschSshClientModuleTest.java +++ b/drivers/jsch/src/test/java/org/jclouds/ssh/jsch/config/JschSshClientModuleTest.java @@ -22,11 +22,11 @@ import java.net.UnknownHostException; import org.jclouds.domain.LoginCredentials; import org.jclouds.logging.slf4j.config.SLF4JLoggingModule; -import org.jclouds.net.IPSocket; import org.jclouds.ssh.SshClient; import org.jclouds.ssh.jsch.JschSshClient; import org.testng.annotations.Test; +import com.google.common.net.HostAndPort; import com.google.inject.Guice; import com.google.inject.Injector; @@ -42,7 +42,7 @@ public class JschSshClientModuleTest { Injector i = Guice.createInjector(new JschSshClientModule(), new SLF4JLoggingModule()); SshClient.Factory factory = i.getInstance(SshClient.Factory.class); - SshClient connection = factory.create(new IPSocket("localhost", 22), LoginCredentials.builder().user("username") + SshClient connection = factory.create(HostAndPort.fromParts("localhost", 22), LoginCredentials.builder().user("username") .password("password").build()); assert connection instanceof JschSshClient; } diff --git a/drivers/sshj/src/main/java/org/jclouds/sshj/SshjSshClient.java b/drivers/sshj/src/main/java/org/jclouds/sshj/SshjSshClient.java index 6318db8270..ed78a53091 100644 --- a/drivers/sshj/src/main/java/org/jclouds/sshj/SshjSshClient.java +++ b/drivers/sshj/src/main/java/org/jclouds/sshj/SshjSshClient.java @@ -63,7 +63,6 @@ import org.jclouds.http.handlers.BackoffLimitedRetryHandler; import org.jclouds.io.Payload; import org.jclouds.io.Payloads; import org.jclouds.logging.Logger; -import org.jclouds.net.IPSocket; import org.jclouds.rest.AuthorizationException; import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshException; @@ -142,10 +141,10 @@ public class SshjSshClient implements SshClient { private final BackoffLimitedRetryHandler backoffLimitedRetryHandler; - public SshjSshClient(BackoffLimitedRetryHandler backoffLimitedRetryHandler, IPSocket socket, + public SshjSshClient(BackoffLimitedRetryHandler backoffLimitedRetryHandler, HostAndPort socket, LoginCredentials loginCredentials, int timeout) { this.user = checkNotNull(loginCredentials, "loginCredentials").getUser(); - this.host = checkNotNull(socket, "socket").getAddress(); + this.host = checkNotNull(socket, "socket").getHostText(); checkArgument(socket.getPort() > 0, "ssh port must be greater then zero" + socket.getPort()); checkArgument(loginCredentials.getPassword() != null || loginCredentials.getPrivateKey() != null, "you must specify a password or a key"); diff --git a/drivers/sshj/src/main/java/org/jclouds/sshj/config/SshjSshClientModule.java b/drivers/sshj/src/main/java/org/jclouds/sshj/config/SshjSshClientModule.java index 7b2621e1ba..b49b6b43a5 100644 --- a/drivers/sshj/src/main/java/org/jclouds/sshj/config/SshjSshClientModule.java +++ b/drivers/sshj/src/main/java/org/jclouds/sshj/config/SshjSshClientModule.java @@ -24,13 +24,13 @@ import org.jclouds.Constants; import org.jclouds.domain.Credentials; import org.jclouds.domain.LoginCredentials; import org.jclouds.http.handlers.BackoffLimitedRetryHandler; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.InetSocketAddressConnect; import org.jclouds.predicates.SocketOpen; import org.jclouds.ssh.ConfiguresSshClient; import org.jclouds.ssh.SshClient; import org.jclouds.sshj.SshjSshClient; +import com.google.common.net.HostAndPort; import com.google.inject.AbstractModule; import com.google.inject.Inject; import com.google.inject.Injector; @@ -64,14 +64,14 @@ public class SshjSshClientModule extends AbstractModule { } @Override - public SshClient create(IPSocket socket, LoginCredentials credentials) { + public SshClient create(HostAndPort socket, LoginCredentials credentials) { SshClient client = new SshjSshClient(backoffLimitedRetryHandler, socket, credentials, timeout); injector.injectMembers(client);// add logger return client; } @Override - public SshClient create(IPSocket socket, Credentials credentials) { + public SshClient create(HostAndPort socket, Credentials credentials) { return create(socket, LoginCredentials.fromCredentials(credentials)); } } diff --git a/drivers/sshj/src/test/java/org/jclouds/sshj/SshjSshClientLiveTest.java b/drivers/sshj/src/test/java/org/jclouds/sshj/SshjSshClientLiveTest.java index 2888fe7846..f0d78dd3c7 100644 --- a/drivers/sshj/src/test/java/org/jclouds/sshj/SshjSshClientLiveTest.java +++ b/drivers/sshj/src/test/java/org/jclouds/sshj/SshjSshClientLiveTest.java @@ -36,7 +36,6 @@ import org.jclouds.domain.LoginCredentials; import org.jclouds.io.Payload; import org.jclouds.io.Payloads; import org.jclouds.logging.slf4j.config.SLF4JLoggingModule; -import org.jclouds.net.IPSocket; import org.jclouds.ssh.SshClient; import org.jclouds.sshj.config.SshjSshClientModule; import org.jclouds.util.Strings2; @@ -46,6 +45,7 @@ import org.testng.annotations.Test; import com.google.common.base.Strings; import com.google.common.base.Suppliers; import com.google.common.io.Closeables; +import com.google.common.net.HostAndPort; import com.google.inject.Guice; import com.google.inject.Injector; @@ -135,10 +135,10 @@ public class SshjSshClientLiveTest { SshClient.Factory factory = i.getInstance(SshClient.Factory.class); SshClient connection; if (Strings.emptyToNull(sshKeyFile) != null) { - connection = factory.create(new IPSocket(sshHost, port), LoginCredentials.builder().user(sshUser) + connection = factory.create(HostAndPort.fromParts(sshHost, port), LoginCredentials.builder().user(sshUser) .privateKey(Strings2.toStringAndClose(new FileInputStream(sshKeyFile))).build()); } else { - connection = factory.create(new IPSocket(sshHost, port), + connection = factory.create(HostAndPort.fromParts(sshHost, port), LoginCredentials.builder().user(sshUser).password(sshPass).build()); } connection.connect(); diff --git a/drivers/sshj/src/test/java/org/jclouds/sshj/SshjSshClientTest.java b/drivers/sshj/src/test/java/org/jclouds/sshj/SshjSshClientTest.java index 3316aee861..a3946527b9 100644 --- a/drivers/sshj/src/test/java/org/jclouds/sshj/SshjSshClientTest.java +++ b/drivers/sshj/src/test/java/org/jclouds/sshj/SshjSshClientTest.java @@ -42,7 +42,6 @@ import org.jclouds.domain.LoginCredentials; import org.jclouds.logging.BufferLogger; import org.jclouds.logging.BufferLogger.Record; import org.jclouds.logging.slf4j.config.SLF4JLoggingModule; -import org.jclouds.net.IPSocket; import org.jclouds.rest.AuthorizationException; import org.jclouds.ssh.SshClient; import org.jclouds.sshj.config.SshjSshClientModule; @@ -50,6 +49,7 @@ import org.testng.Assert; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; +import com.google.common.net.HostAndPort; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; @@ -83,7 +83,7 @@ public class SshjSshClientTest { }, new SLF4JLoggingModule()); SshClient.Factory factory = i.getInstance(SshClient.Factory.class); - SshjSshClient ssh = SshjSshClient.class.cast(factory.create(new IPSocket("localhost", 22), LoginCredentials + SshjSshClient ssh = SshjSshClient.class.cast(factory.create(HostAndPort.fromParts("localhost", 22), LoginCredentials .builder().user("username").password("password").build())); return ssh; } diff --git a/drivers/sshj/src/test/java/org/jclouds/sshj/config/SshjSshClientModuleTest.java b/drivers/sshj/src/test/java/org/jclouds/sshj/config/SshjSshClientModuleTest.java index af8aace9c4..e0a61ccf6a 100644 --- a/drivers/sshj/src/test/java/org/jclouds/sshj/config/SshjSshClientModuleTest.java +++ b/drivers/sshj/src/test/java/org/jclouds/sshj/config/SshjSshClientModuleTest.java @@ -20,11 +20,11 @@ package org.jclouds.sshj.config; import org.jclouds.domain.LoginCredentials; import org.jclouds.logging.slf4j.config.SLF4JLoggingModule; -import org.jclouds.net.IPSocket; import org.jclouds.ssh.SshClient; import org.jclouds.sshj.SshjSshClient; import org.testng.annotations.Test; +import com.google.common.net.HostAndPort; import com.google.inject.Guice; import com.google.inject.Injector; @@ -40,7 +40,7 @@ public class SshjSshClientModuleTest { Injector i = Guice.createInjector(new SshjSshClientModule(), new SLF4JLoggingModule()); SshClient.Factory factory = i.getInstance(SshClient.Factory.class); - SshClient connection = factory.create(new IPSocket("localhost", 22), LoginCredentials.builder().user("username") + SshClient connection = factory.create(HostAndPort.fromParts("localhost", 22), LoginCredentials.builder().user("username") .password("password").build()); assert connection instanceof SshjSshClient; } diff --git a/labs/cdmi/pom.xml b/labs/cdmi/pom.xml new file mode 100644 index 0000000000..5a2a5293e3 --- /dev/null +++ b/labs/cdmi/pom.xml @@ -0,0 +1,135 @@ + + + + 4.0.0 + + org.jclouds + jclouds-project + 1.5.0-SNAPSHOT + ../../project/pom.xml + + org.jclouds.labs + cdmi + jcloud cdmi api + jclouds components to access an implementation of SNIA CDMI + bundle + + + http://localhost:8080 + 1.0.1 + + tenantId:IDENTITY + FIXME_CREDENTIALS + FIXME_HTTPURL + FIXME_HTTPMD5 + + + + + org.jclouds + jclouds-blobstore + ${project.version} + + + org.jclouds + jclouds-core + ${project.version} + test-jar + test + + + org.jclouds + jclouds-blobstore + ${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.cdmi.endpoint} + ${test.cdmi.api-version} + ${test.cdmi.build-version} + ${test.cdmi.identity} + ${test.cdmi.credential} + ${jclouds.blobstore.httpstream.url} + ${jclouds.blobstore.httpstream.md5} + + + + + + + + + + + + + + org.apache.felix + maven-bundle-plugin + + + ${project.artifactId} + org.jclouds.snia.cdmi.v1*;version="${project.version}" + + org.jclouds.blobstore.internal;version="${project.version}", + org.jclouds.rest.internal;version="${project.version}", + org.jclouds*;version="${project.version}", + * + + + + + + + + diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/CDMIApiMetadata.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/CDMIApiMetadata.java new file mode 100644 index 0000000000..a01b8c47ca --- /dev/null +++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/CDMIApiMetadata.java @@ -0,0 +1,93 @@ +/** + * 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.snia.cdmi.v1; + +import java.net.URI; +import java.util.Properties; + +import org.jclouds.apis.ApiMetadata; +import org.jclouds.rest.RestContext; +import org.jclouds.rest.internal.BaseRestApiMetadata; +import org.jclouds.snia.cdmi.v1.config.CDMIRestClientModule; + +import com.google.common.collect.ImmutableSet; +import com.google.common.reflect.TypeToken; +import com.google.inject.Module; + +/** + * Implementation of {@link ApiMetadata} for CDMI 1.0.1 API + * + * @author Adrian Cole + */ +public class CDMIApiMetadata extends BaseRestApiMetadata { + + /** The serialVersionUID */ + private static final long serialVersionUID = 6725672099385580694L; + + public static final TypeToken> CONTEXT_TOKEN = new TypeToken>() { + private static final long serialVersionUID = -5070937833892503232L; + }; + + @Override + public Builder toBuilder() { + return new Builder().fromApiMetadata(this); + } + + public CDMIApiMetadata() { + this(new Builder()); + } + + protected CDMIApiMetadata(Builder builder) { + super(builder); + } + + public static Properties defaultProperties() { + Properties properties = BaseRestApiMetadata.defaultProperties(); + return properties; + } + + public static class Builder extends BaseRestApiMetadata.Builder { + + protected Builder() { + super(CDMIClient.class, CDMIAsyncClient.class); + id("cdmi") + .name("SNIA CDMI API") + .identityName("tenantId:user") + .credentialName("password") + .documentation(URI.create("http://www.snia.org/cdmi")) + .version("1.0.1") + .defaultEndpoint("http://localhost:8080") + .defaultProperties(CDMIApiMetadata.defaultProperties()) + .defaultModules(ImmutableSet.> of(CDMIRestClientModule.class)); + } + + @Override + public CDMIApiMetadata build() { + return new CDMIApiMetadata(this); + } + + @Override + public Builder fromApiMetadata(ApiMetadata in) { + super.fromApiMetadata(in); + return this; + } + + } + +} diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/CDMIAsyncClient.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/CDMIAsyncClient.java new file mode 100644 index 0000000000..e8c80e56b8 --- /dev/null +++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/CDMIAsyncClient.java @@ -0,0 +1,53 @@ +/** + * 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.snia.cdmi.v1; + +import org.jclouds.rest.annotations.Delegate; +import org.jclouds.snia.cdmi.v1.features.ContainerAsyncClient; +import org.jclouds.snia.cdmi.v1.features.DataAsyncClient; +import org.jclouds.snia.cdmi.v1.features.DomainAsyncClient; + +/** + * Provides asynchronous access to CDMI via their REST API. + *

+ * + * @see CDMIClient + * @see api doc + * @author Adrian Cole + */ +public interface CDMIAsyncClient { + + /** + * Provides asynchronous access to Domain Object Resource Operations. + */ + @Delegate + DomainAsyncClient getDomainClient(); + + /** + * Provides asynchronous access to Container Object Resource Operations. + */ + @Delegate + ContainerAsyncClient getContainerClient(); + + /** + * Provides asynchronous access to Data Object Resource Operations. + */ + @Delegate + DataAsyncClient getDataClient(); +} diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/CDMIClient.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/CDMIClient.java new file mode 100644 index 0000000000..3f1d369e67 --- /dev/null +++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/CDMIClient.java @@ -0,0 +1,57 @@ +/** + * 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.snia.cdmi.v1; + +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.rest.annotations.Delegate; +import org.jclouds.snia.cdmi.v1.features.ContainerClient; +import org.jclouds.snia.cdmi.v1.features.DataClient; +import org.jclouds.snia.cdmi.v1.features.DomainClient; + +/** + * Provides synchronous access to CDMI. + *

+ * + * @see CDMIAsyncClient + * @see api doc + * @author Adrian Cole + */ +@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) +public interface CDMIClient { + + /** + * Provides synchronous access to Domain Object Resource Operations. + */ + @Delegate + DomainClient getDomainClient(); + + /** + * Provides synchronous access to Container Object Resource Operations. + */ + @Delegate + ContainerClient getContainerClient(); + + /** + * Provides synchronous access to Data Object Resource Operations. + */ + @Delegate + DataClient getDataClient(); +} diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/ObjectTypes.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/ObjectTypes.java new file mode 100644 index 0000000000..e387eb9af2 --- /dev/null +++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/ObjectTypes.java @@ -0,0 +1,31 @@ +/** + * 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.snia.cdmi.v1; + + +/** + * Object Types used in CDMI. + * + * @see javax.ws.rs.core.MediaType; + */ +public interface ObjectTypes { + + public static final String CONTAINER = "application/cdmi-container"; + +} \ No newline at end of file diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/config/CDMIProperties.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/config/CDMIProperties.java new file mode 100644 index 0000000000..77beee510e --- /dev/null +++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/config/CDMIProperties.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.snia.cdmi.v1.config; + +/** + * Configuration properties and constants used in SNIA CDMI connections. + * + * @author Adrian Cole + */ +public class CDMIProperties { + +} diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/config/CDMIRestClientModule.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/config/CDMIRestClientModule.java new file mode 100644 index 0000000000..cfe0250965 --- /dev/null +++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/config/CDMIRestClientModule.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.snia.cdmi.v1.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.rest.ConfiguresRestClient; +import org.jclouds.rest.config.RestClientModule; +import org.jclouds.snia.cdmi.v1.CDMIAsyncClient; +import org.jclouds.snia.cdmi.v1.CDMIClient; +import org.jclouds.snia.cdmi.v1.features.ContainerAsyncClient; +import org.jclouds.snia.cdmi.v1.features.ContainerClient; +import org.jclouds.snia.cdmi.v1.features.DataAsyncClient; +import org.jclouds.snia.cdmi.v1.features.DataClient; +import org.jclouds.snia.cdmi.v1.features.DomainAsyncClient; +import org.jclouds.snia.cdmi.v1.features.DomainClient; +import org.jclouds.snia.cdmi.v1.handlers.CDMIErrorHandler; + +import com.google.common.collect.ImmutableMap; + +/** + * Configures the CDMI connection. + * + * @author Adrian Cole + */ +@ConfiguresRestClient +public class CDMIRestClientModule extends RestClientModule { + + public static final Map, Class> DELEGATE_MAP = ImmutableMap., Class> builder().put( + DomainClient.class, DomainAsyncClient.class).put(ContainerClient.class, ContainerAsyncClient.class).put( + DataClient.class, DataAsyncClient.class).build(); + + public CDMIRestClientModule() { + super(DELEGATE_MAP); + } + + @Override + protected void bindErrorHandlers() { + bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(CDMIErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(CDMIErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(CDMIErrorHandler.class); + } +} diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/domain/CDMIObject.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/domain/CDMIObject.java new file mode 100644 index 0000000000..59508653ed --- /dev/null +++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/domain/CDMIObject.java @@ -0,0 +1,165 @@ +/** + * 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.snia.cdmi.v1.domain; + +import static com.google.common.base.Objects.equal; +import static com.google.common.base.Preconditions.checkNotNull; + +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; + +/** + * The base type for all objects in the CDMI model. + * + * @author Adrian Cole + */ +public class CDMIObject { + + public static Builder builder() { + return new ConcreteBuilder(); + } + + public Builder toBuilder() { + return builder().fromCDMIObject(this); + } + + private static class ConcreteBuilder extends Builder { + } + + public static abstract class Builder> { + private String objectID; + private String objectType; + private String objectName; + + @SuppressWarnings("unchecked") + protected B self() { + return (B) this; + } + + /** + * @see CDMIObject#getObjectID() + */ + public B objectID(String objectID) { + this.objectID = objectID; + return self(); + } + + /** + * @see CDMIObject#getObjectType() + */ + public B objectType(String objectType) { + this.objectType = objectType; + return self(); + } + + /** + * @see CDMIObject#getObjectName() + */ + public B objectName(String objectName) { + this.objectName = objectName; + return self(); + } + + public CDMIObject build() { + return new CDMIObject(this); + } + + protected B fromCDMIObject(CDMIObject in) { + return objectID(in.getObjectID()).objectType(in.getObjectType()).objectName(in.getObjectName()); + } + } + + private final String objectID; + private final String objectType; + private final String objectName; + + protected CDMIObject(Builder builder) { + this.objectID = checkNotNull(builder.objectID, "objectID"); + this.objectType = checkNotNull(builder.objectType, "objectType"); + this.objectName = builder.objectName; + } + + /** + * Object ID of the object
+ * Every object stored within a CDMI-compliant system shall have a globally unique object + * identifier (ID) assigned at creation time. The CDMI object ID is a string with requirements + * for how it is generated and how it obtains its uniqueness. Each offering that implements CDMI + * is able to produce these identifiers without conflicting with other offerings. + */ + public String getObjectID() { + return objectID; + } + + /** + * + * type of the object + */ + public String getObjectType() { + return objectType; + } + + /** + * For objects in a container, the objectName field shall be returned. For objects not in a + * container (objects that are only accessible by ID), the objectName field shall not be + * returned. + * + * Name of the object + */ + @Nullable + public String getObjectName() { + return objectName; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + CDMIObject that = CDMIObject.class.cast(o); + return equal(this.objectID, that.objectID) && equal(this.objectName, that.objectName) + && equal(this.objectType, that.objectType); + } + + public boolean clone(Object o) { + if (this == o) + return false; + if (o == null || getClass() != o.getClass()) + return false; + CDMIObject that = CDMIObject.class.cast(o); + return equal(this.objectType, that.objectType); + } + + @Override + public int hashCode() { + return Objects.hashCode(objectID, objectName, objectType); + } + + @Override + public String toString() { + return string().toString(); + } + + protected ToStringHelper string() { + return Objects.toStringHelper("").add("objectID", objectID).add("objectName", objectName).add("objectType", + objectType); + } +} diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/domain/Container.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/domain/Container.java new file mode 100644 index 0000000000..f0d1affb08 --- /dev/null +++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/domain/Container.java @@ -0,0 +1,134 @@ +/** + * 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.snia.cdmi.v1.domain; + +import static com.google.common.base.Objects.equal; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; +import java.util.Set; + +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; + +/** + * + * @author Adrian Cole + */ +public class Container extends CDMIObject { + + public static Builder builder() { + return new ConcreteBuilder(); + } + + @Override + public Builder toBuilder() { + return builder().fromContainer(this); + } + + public static class Builder> extends CDMIObject.Builder { + + private Set children = ImmutableSet.of(); + private Map metadata = Maps.newHashMap(); + + /** + * @see Container#getChildren() + */ + public B children(String... children) { + return children(ImmutableSet.copyOf(checkNotNull(children, "children"))); + } + + /** + * @see Container#getChildren() + */ + public B children(Set children) { + this.children = ImmutableSet.copyOf(checkNotNull(children, "children")); + return self(); + } + + /** + * @see Container#getMetadata() + */ + public B metadata(Map metadata) { + this.metadata = ImmutableMap.copyOf(checkNotNull(metadata, "metadata")); + return self(); + } + + @Override + public Container build() { + return new Container(this); + } + + public B fromContainer(Container in) { + return fromCDMIObject(in).children(in.getChildren()).metadata(in.getMetadata()); + } + } + + private static class ConcreteBuilder extends Builder { + } + + private final Set children; + private final Map metadata; + + protected Container(Builder builder) { + super(builder); + this.children = ImmutableSet.copyOf(checkNotNull(builder.children, "children")); + this.metadata = ImmutableMap.copyOf(checkNotNull(builder.metadata, "metadata")); + } + + /** + * Names of the children objects in the container object. Child container objects end with "/". + */ + public Set getChildren() { + return children; + } + + /** + * Metadata for the container object. This field includes any user and data system metadata + * specified in the request body metadata field, along with storage system metadata generated by + * the cloud storage system. + */ + public Map getMetadata() { + return metadata; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + Container that = Container.class.cast(o); + return super.equals(that) && equal(this.children, that.children) && equal(this.metadata, that.metadata); + } + + @Override + public int hashCode() { + return Objects.hashCode(super.hashCode(), children, metadata); + } + + @Override + public ToStringHelper string() { + return super.string().add("children", children).add("metadata", metadata); + } + +} diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/ContainerAsyncClient.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/ContainerAsyncClient.java new file mode 100644 index 0000000000..1bbf7257f8 --- /dev/null +++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/ContainerAsyncClient.java @@ -0,0 +1,60 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.snia.cdmi.v1.features; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.core.MediaType; + +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.Headers; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SkipEncoding; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; +import org.jclouds.snia.cdmi.v1.ObjectTypes; +import org.jclouds.snia.cdmi.v1.domain.Container; +import org.jclouds.snia.cdmi.v1.filters.BasicAuthenticationAndTenantId; +import org.jclouds.snia.cdmi.v1.filters.StripExtraAcceptHeader; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Container Object Resource Operations + * + * @see ContainerClient + * @author Adrian Cole + * @see api doc + */ +@SkipEncoding( { '/', '=' }) +@RequestFilters( { BasicAuthenticationAndTenantId.class, StripExtraAcceptHeader.class }) +@Headers(keys="X-CDMI-Specification-Version", values = "{jclouds.api-version}") +public interface ContainerAsyncClient { + + /** + * @see ContainerClient#listContainers() + */ + @GET + @Consumes( { ObjectTypes.CONTAINER, MediaType.APPLICATION_JSON }) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @Path("/{containerName}/") + ListenableFuture getContainer(@PathParam("containerName") String containerName); + +} diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/ContainerClient.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/ContainerClient.java new file mode 100644 index 0000000000..76df5c73d8 --- /dev/null +++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/ContainerClient.java @@ -0,0 +1,38 @@ +/** + * 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.snia.cdmi.v1.features; + +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.snia.cdmi.v1.domain.Container; + +/** + * Container Object Resource Operations + * + * @see ContainerAsyncClient + * @author Adrian Cole + * @see api doc + */ +@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS) +public interface ContainerClient { + + Container getContainer(String containerName); + +} diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataAsyncClient.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataAsyncClient.java new file mode 100644 index 0000000000..5fc289bbf0 --- /dev/null +++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataAsyncClient.java @@ -0,0 +1,39 @@ +/** + * 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.snia.cdmi.v1.features; + +import org.jclouds.rest.annotations.Headers; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SkipEncoding; +import org.jclouds.snia.cdmi.v1.filters.BasicAuthenticationAndTenantId; +import org.jclouds.snia.cdmi.v1.filters.StripExtraAcceptHeader; + +/** + * Data Object Resource Operations + * + * @see DataClient + * @author Adrian Cole + * @see api doc + */ +@SkipEncoding( { '/', '=' }) +@RequestFilters( { BasicAuthenticationAndTenantId.class, StripExtraAcceptHeader.class }) +@Headers(keys="X-CDMI-Specification-Version", values = "{jclouds.api-version}") +public interface DataAsyncClient { + +} diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataClient.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataClient.java new file mode 100644 index 0000000000..f6dea31e45 --- /dev/null +++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DataClient.java @@ -0,0 +1,35 @@ +/** + * 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.snia.cdmi.v1.features; + +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; + +/** + * Data Object Resource Operations + * + * @see DataAsyncClient + * @author Adrian Cole + * @see api doc + */ +@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS) +public interface DataClient { + +} diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DomainAsyncClient.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DomainAsyncClient.java new file mode 100644 index 0000000000..db00154a4a --- /dev/null +++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DomainAsyncClient.java @@ -0,0 +1,40 @@ +/** + * 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.snia.cdmi.v1.features; + +import org.jclouds.rest.annotations.Headers; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SkipEncoding; +import org.jclouds.snia.cdmi.v1.filters.BasicAuthenticationAndTenantId; +import org.jclouds.snia.cdmi.v1.filters.StripExtraAcceptHeader; + +/** + * Domain Object Resource Operations + * + * @see DomainClient + * @author Adrian Cole + * @see api doc + */ +@SkipEncoding( { '/', '=' }) +@RequestFilters( { BasicAuthenticationAndTenantId.class, StripExtraAcceptHeader.class }) +@Headers(keys="X-CDMI-Specification-Version", values = "{jclouds.api-version}") +public interface DomainAsyncClient { + + +} diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DomainClient.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DomainClient.java new file mode 100644 index 0000000000..c0488895bc --- /dev/null +++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/features/DomainClient.java @@ -0,0 +1,36 @@ +/** + * 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.snia.cdmi.v1.features; + +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; + +/** + * Domain Object Resource Operations + * + * @see DomainAsyncClient + * @author Adrian Cole + * @see api doc + */ +@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS) +public interface DomainClient { + + +} diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/filters/BasicAuthenticationAndTenantId.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/filters/BasicAuthenticationAndTenantId.java new file mode 100644 index 0000000000..fff38e56dd --- /dev/null +++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/filters/BasicAuthenticationAndTenantId.java @@ -0,0 +1,62 @@ +/** + * 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.snia.cdmi.v1.filters; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.crypto.Crypto; +import org.jclouds.http.HttpException; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpRequestFilter; +import org.jclouds.http.filters.BasicAuthentication; +import org.jclouds.http.utils.ModifyRequest; +import org.jclouds.rest.AuthorizationException; +import org.jclouds.rest.annotations.Credential; +import org.jclouds.rest.annotations.Identity; + +/** + * Uses Basic Authentication to sign the request, and adds the {@code TID} header. + * + * @see + * @author Adrian Cole + * + */ +@Singleton +public class BasicAuthenticationAndTenantId implements HttpRequestFilter { + private final String tenantId; + private final BasicAuthentication basicAuthentication; + + @Inject + public BasicAuthenticationAndTenantId(@Identity String tenantIdAndUsername, @Credential String password, + Crypto crypto) { + if (tenantIdAndUsername.indexOf(':') == -1) { + throw new AuthorizationException(String.format("Identity %s does not match format tenantId:username", + tenantIdAndUsername), null); + } + this.tenantId = tenantIdAndUsername.substring(0, tenantIdAndUsername.indexOf(':')); + String username = tenantIdAndUsername.substring(tenantIdAndUsername.indexOf(':') + 1); + this.basicAuthentication = new BasicAuthentication(username, password, crypto); + } + + @Override + public HttpRequest filter(HttpRequest request) throws HttpException { + return basicAuthentication.filter(ModifyRequest.replaceHeader(request, "TID", tenantId)); + } +} \ No newline at end of file diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/filters/StripExtraAcceptHeader.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/filters/StripExtraAcceptHeader.java new file mode 100644 index 0000000000..3130533c9e --- /dev/null +++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/filters/StripExtraAcceptHeader.java @@ -0,0 +1,43 @@ +/** + * 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.snia.cdmi.v1.filters; + +import javax.inject.Singleton; + +import org.jclouds.http.HttpException; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpRequestFilter; +import org.jclouds.http.utils.ModifyRequest; + +/** + * current CDMI spec doesn't indicate the form of the response. It would be nice, if it could take 2 + * {@code Accept} headers. Until then, let's strip off the mediaType header, which we use to ensure + * responses are parsed with json. + * + * @author Adrian Cole + * + */ +@Singleton +public class StripExtraAcceptHeader implements HttpRequestFilter { + + @Override + public HttpRequest filter(HttpRequest request) throws HttpException { + return ModifyRequest.replaceHeader(request, "Accept", request.getFirstHeaderOrNull("Accept")); + } +} \ No newline at end of file diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/handlers/CDMIErrorHandler.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/handlers/CDMIErrorHandler.java new file mode 100644 index 0000000000..30f51c0758 --- /dev/null +++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/handlers/CDMIErrorHandler.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.snia.cdmi.v1.handlers; + +import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.inject.Singleton; + +import org.jclouds.blobstore.ContainerNotFoundException; +import org.jclouds.blobstore.KeyNotFoundException; +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; + +/** + * This will parse and set an appropriate exception on the command data. + * + * @author Adrian Cole + * + */ +// TODO: is there error spec someplace? let's type errors, etc. +@Singleton +public class CDMIErrorHandler implements HttpErrorHandler { + public static final String PREFIX = "^/v[0-9][^/]*/[a-zA-Z]+_[^/]+/"; + public static final Pattern CONTAINER_PATH = Pattern.compile(PREFIX + "([^/]+)$"); + public static final Pattern CONTAINER_KEY_PATH = Pattern.compile(PREFIX + "([^/]+)/(.*)"); + + 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 401: + exception = new AuthorizationException(exception.getMessage(), exception); + break; + case 404: + if (!command.getCurrentRequest().getMethod().equals("DELETE")) { + String path = command.getCurrentRequest().getEndpoint().getPath(); + Matcher matcher = CONTAINER_PATH.matcher(path); + Exception oldException = exception; + if (matcher.find()) { + exception = new ContainerNotFoundException(matcher.group(1), message); + exception.initCause(oldException); + } else { + matcher = CONTAINER_KEY_PATH.matcher(path); + if (matcher.find()) { + exception = new KeyNotFoundException(matcher.group(1), matcher.group(2), message); + exception.initCause(oldException); + } + } + } + break; + } + command.setException(exception); + } +} diff --git a/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/options/ListContainersOptions.java b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/options/ListContainersOptions.java new file mode 100644 index 0000000000..efa468f48e --- /dev/null +++ b/labs/cdmi/src/main/java/org/jclouds/snia/cdmi/v1/options/ListContainersOptions.java @@ -0,0 +1,78 @@ +/** + * 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.snia.cdmi.v1.options; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +import org.jclouds.http.options.BaseHttpRequestOptions; + +/** + * Contains options supported in the REST API for the GET container operation.

+ */ +public class ListContainersOptions extends BaseHttpRequestOptions { + public static final ListContainersOptions NONE = new ListContainersOptions(); + + /** + * Given a string value x, return data names greater in value than the specified marker. + */ + public ListContainersOptions marker(String marker) { + queryParameters.put("marker", checkNotNull(marker, "marker")); + return this; + } + + public String getMarker() { + return getFirstQueryOrNull("marker"); + } + + /** + * For an integer value n, limits the number of results to n values. + */ + public ListContainersOptions limit(int limit) { + checkState(limit >= 0, "limit must be >= 0"); + checkState(limit <= 10000, "limit must be <= 10000"); + queryParameters.put("limit", Integer.toString(limit)); + return this; + } + + public int getLimit() { + String val = getFirstQueryOrNull("limit"); + return val != null ? new Integer(val) : 10000; + } + + public static class Builder { + + /** + * @see ListContainersOptions#marker(String) + */ + public static ListContainersOptions marker(String marker) { + ListContainersOptions options = new ListContainersOptions(); + return options.marker(marker); + } + + /** + * @see ListContainersOptions#limit(int) + */ + public static ListContainersOptions limit(int limit) { + ListContainersOptions options = new ListContainersOptions(); + return options.limit(limit); + } + + } +} diff --git a/labs/cdmi/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata b/labs/cdmi/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata new file mode 100644 index 0000000000..19b5767f88 --- /dev/null +++ b/labs/cdmi/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata @@ -0,0 +1 @@ +org.jclouds.snia.cdmi.v1.CDMIApiMetadata diff --git a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/CDMIApiMetadataTest.java b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/CDMIApiMetadataTest.java new file mode 100644 index 0000000000..3a967e51ad --- /dev/null +++ b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/CDMIApiMetadataTest.java @@ -0,0 +1,38 @@ +/** + * 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.snia.cdmi.v1; + +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 Adrian Cole + */ +@Test(groups = "unit", testName = "CDMIApiMetadataTest") +// public class CDMIApiMetadataTest extends BaseBlobStoreApiMetadataTest { +public class CDMIApiMetadataTest extends BaseApiMetadataTest { + public CDMIApiMetadataTest() { + super(new CDMIApiMetadata(), ImmutableSet.> of()); + } +} diff --git a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/CDMIErrorHandlerTest.java b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/CDMIErrorHandlerTest.java new file mode 100644 index 0000000000..1d114a0502 --- /dev/null +++ b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/CDMIErrorHandlerTest.java @@ -0,0 +1,120 @@ +/** + * 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.snia.cdmi.v1; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.reportMatcher; +import static org.easymock.EasyMock.verify; + +import java.net.URI; + +import org.easymock.IArgumentMatcher; +import org.jclouds.blobstore.ContainerNotFoundException; +import org.jclouds.blobstore.KeyNotFoundException; +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.io.Payloads; +import org.jclouds.snia.cdmi.v1.handlers.CDMIErrorHandler; +import org.jclouds.util.Strings2; +import org.testng.annotations.Test; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "CDMIErrorHandlerTest") +public class CDMIErrorHandlerTest { + + @Test + public void test404SetsKeyNotFoundExceptionMosso() { + assertCodeMakes("HEAD", URI + .create("http://host/v1/MossoCloudFS_7064cdb1d49d4dcba3c899ac33e8409d/adriancole-blobstore1/key"), 404, + "Not Found", "", KeyNotFoundException.class); + } + + @Test + public void test404SetsKeyNotFoundExceptionCDMI() { + assertCodeMakes("HEAD", URI + .create("http://67.202.39.175:8080/v1/AUTH_7064cdb1d49d4dcba3c899ac33e8409d/adriancole-blobstore1/key"), + 404, "Not Found", "", KeyNotFoundException.class); + } + + @Test + public void test404SetsContainerNotFoundExceptionMosso() { + assertCodeMakes("HEAD", URI + .create("http://host/v1/MossoCloudFS_7064cdb1d49d4dcba3c899ac33e8409d/adriancole-blobstore1"), 404, + "Not Found", "", ContainerNotFoundException.class); + } + + @Test + public void test404SetsContainerNotFoundExceptionCDMI() { + assertCodeMakes("HEAD", URI + .create("http://67.202.39.175:8080/v1/AUTH_7064cdb1d49d4dcba3c899ac33e8409d/adriancole-blobstore1"), + 404, "Not Found", "", ContainerNotFoundException.class); + } + + private void assertCodeMakes(String method, URI uri, int statusCode, String message, String content, + Class expected) { + assertCodeMakes(method, uri, statusCode, message, "text/plain", content, expected); + } + + private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType, + String content, Class expected) { + + CDMIErrorHandler function = new CDMIErrorHandler(); + + HttpCommand command = createMock(HttpCommand.class); + HttpRequest request = new HttpRequest(method, uri); + HttpResponse response = new HttpResponse(statusCode, message, Payloads.newInputStreamPayload(Strings2 + .toInputStream(content))); + response.getPayload().getContentMetadata().setContentType(contentType); + + expect(command.getCurrentRequest()).andReturn(request).atLeastOnce(); + command.setException(classEq(expected)); + + replay(command); + + function.handleError(command, response); + + verify(command); + } + + public static Exception classEq(final Class in) { + reportMatcher(new IArgumentMatcher() { + + @Override + public void appendTo(StringBuffer buffer) { + buffer.append("classEq("); + buffer.append(in); + buffer.append(")"); + } + + @Override + public boolean matches(Object arg) { + return arg.getClass() == in; + } + + }); + return null; + } + +} diff --git a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/ContainerClientExpectTest.java b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/ContainerClientExpectTest.java new file mode 100644 index 0000000000..55d57aadad --- /dev/null +++ b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/ContainerClientExpectTest.java @@ -0,0 +1,67 @@ +/** + * 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.snia.cdmi.v1.features; + +import static org.testng.Assert.assertEquals; + +import java.net.URI; + +import org.jclouds.crypto.CryptoStreams; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.snia.cdmi.v1.CDMIClient; +import org.jclouds.snia.cdmi.v1.internal.BaseCDMIClientExpectTest; +import org.jclouds.snia.cdmi.v1.parse.ParseContainerTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMultimap; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "ContainerAsyncClientTest") +public class ContainerClientExpectTest extends BaseCDMIClientExpectTest { + + public void testGetContainerWhenResponseIs2xx() throws Exception { + + HttpRequest getContainer = HttpRequest.builder() + .method("GET") + .endpoint(URI.create("http://localhost:8080/MyContainer/")) + .headers(ImmutableMultimap. builder() + .put("X-CDMI-Specification-Version", "1.0.1") + .put("Accept", "application/cdmi-container") + .put("TID", "tenantId") + .put("Authorization", "Basic " + CryptoStreams.base64("username:password".getBytes())) + .build()) + .build(); + + HttpResponse getContainerResponse = HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResource("/container.json")) + .build(); + + CDMIClient clientWhenContainersExist = requestSendsResponse(getContainer, getContainerResponse); + + assertEquals( + clientWhenContainersExist.getContainerClient().getContainer("MyContainer"), + new ParseContainerTest().expected()); + } + +} diff --git a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/ContainerClientLiveTest.java b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/ContainerClientLiveTest.java new file mode 100644 index 0000000000..1ee33f40f8 --- /dev/null +++ b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/ContainerClientLiveTest.java @@ -0,0 +1,48 @@ +/** + * 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.snia.cdmi.v1.features; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; + +import org.jclouds.snia.cdmi.v1.ObjectTypes; +import org.jclouds.snia.cdmi.v1.domain.Container; +import org.jclouds.snia.cdmi.v1.internal.BaseCDMIClientLiveTest; +import org.testng.annotations.Test; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "live", testName = "ContainerClientLiveTest") +public class ContainerClientLiveTest extends BaseCDMIClientLiveTest { + + @Test + public void testGetContainer() throws Exception { + ContainerClient client = cdmiContext.getApi().getContainerClient(); + Container container = client.getContainer("TODO: figure out how to list containers"); + assertNotNull(container); + assertEquals(container.getObjectType(), ObjectTypes.CONTAINER); + assertNotNull(container.getObjectID()); + assertNotNull(container.getObjectName()); + assertNotNull(container.getChildren()); + assertNotNull(container.getMetadata()); + } + +} diff --git a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/DataClientExpectTest.java b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/DataClientExpectTest.java new file mode 100644 index 0000000000..8ca2a21af2 --- /dev/null +++ b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/DataClientExpectTest.java @@ -0,0 +1,30 @@ +/** + * 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.snia.cdmi.v1.features; + +import org.jclouds.snia.cdmi.v1.internal.BaseCDMIClientExpectTest; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "DataAsyncClientTest") +public class DataClientExpectTest extends BaseCDMIClientExpectTest { + +} diff --git a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/DataClientLiveTest.java b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/DataClientLiveTest.java new file mode 100644 index 0000000000..0d1a07fc3c --- /dev/null +++ b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/DataClientLiveTest.java @@ -0,0 +1,30 @@ +/** + * 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.snia.cdmi.v1.features; + +import org.jclouds.snia.cdmi.v1.internal.BaseCDMIClientLiveTest; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = "live", testName = "DataClientLiveTest") +public class DataClientLiveTest extends BaseCDMIClientLiveTest { + +} diff --git a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/DomainClientExpectTest.java b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/DomainClientExpectTest.java new file mode 100644 index 0000000000..368f99fb06 --- /dev/null +++ b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/DomainClientExpectTest.java @@ -0,0 +1,30 @@ +/** + * 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 + * + * Unles 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 expres or implied. See the License for the + * specific language governing permisions and limitations + * under the License. + */ +package org.jclouds.snia.cdmi.v1.features; + +import org.jclouds.snia.cdmi.v1.internal.BaseCDMIClientExpectTest; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "DomainClientExpectTest") +public class DomainClientExpectTest extends BaseCDMIClientExpectTest { + +} diff --git a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/DomainClientLiveTest.java b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/DomainClientLiveTest.java new file mode 100644 index 0000000000..6d21f4d66f --- /dev/null +++ b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/features/DomainClientLiveTest.java @@ -0,0 +1,30 @@ +/** + * 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.snia.cdmi.v1.features; + +import org.jclouds.snia.cdmi.v1.internal.BaseCDMIClientLiveTest; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = "live", testName = "ContainerClientLiveTest") +public class DomainClientLiveTest extends BaseCDMIClientLiveTest { + +} diff --git a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/internal/BaseCDMIAsyncClientExpectTest.java b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/internal/BaseCDMIAsyncClientExpectTest.java new file mode 100644 index 0000000000..46ca56bc76 --- /dev/null +++ b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/internal/BaseCDMIAsyncClientExpectTest.java @@ -0,0 +1,39 @@ +/** + * 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.snia.cdmi.v1.internal; + +import java.util.Properties; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.snia.cdmi.v1.CDMIAsyncClient; + +import com.google.common.base.Function; +import com.google.inject.Module; + +/** + * Base class for writing KeyStone Rest Client Expect tests + * + * @author Adrian Cole + */ +public class BaseCDMIAsyncClientExpectTest extends BaseCDMIExpectTest { + public CDMIAsyncClient createClient(Function fn, Module module, Properties props) { + return createInjector(fn, module, props).getInstance(CDMIAsyncClient.class); + } +} diff --git a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/internal/BaseCDMIClientExpectTest.java b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/internal/BaseCDMIClientExpectTest.java new file mode 100644 index 0000000000..2e6871e9dc --- /dev/null +++ b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/internal/BaseCDMIClientExpectTest.java @@ -0,0 +1,30 @@ +/** + * 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.snia.cdmi.v1.internal; + +import org.jclouds.snia.cdmi.v1.CDMIClient; + +/** + * Base class for writing KeyStone Rest Client Expect tests + * + * @author Adrian Cole + */ +public class BaseCDMIClientExpectTest extends BaseCDMIExpectTest { + +} diff --git a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/internal/BaseCDMIClientLiveTest.java b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/internal/BaseCDMIClientLiveTest.java new file mode 100644 index 0000000000..0958b6e73b --- /dev/null +++ b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/internal/BaseCDMIClientLiveTest.java @@ -0,0 +1,64 @@ +/** + * 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.snia.cdmi.v1.internal; + +import org.jclouds.apis.BaseContextLiveTest; +import org.jclouds.rest.RestContext; +import org.jclouds.snia.cdmi.v1.CDMIApiMetadata; +import org.jclouds.snia.cdmi.v1.CDMIAsyncClient; +import org.jclouds.snia.cdmi.v1.CDMIClient; +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 CDMIClient} + * + * @author Adrian Cole + */ +@Test(groups = "live") +public class BaseCDMIClientLiveTest extends BaseContextLiveTest> { + + public BaseCDMIClientLiveTest() { + provider = "cdmi"; + } + + protected RestContext cdmiContext; + + @BeforeGroups(groups = { "integration", "live" }) + @Override + public void setupContext() { + super.setupContext(); + cdmiContext = context; + } + + @AfterGroups(groups = "live") + protected void tearDown() { + if (cdmiContext != null) + cdmiContext.close(); + } + + @Override + protected TypeToken> contextType() { + return CDMIApiMetadata.CONTEXT_TOKEN; + } + +} diff --git a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/internal/BaseCDMIExpectTest.java b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/internal/BaseCDMIExpectTest.java new file mode 100644 index 0000000000..84457451ec --- /dev/null +++ b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/internal/BaseCDMIExpectTest.java @@ -0,0 +1,36 @@ +/** + * 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.snia.cdmi.v1.internal; + +import org.jclouds.rest.internal.BaseRestClientExpectTest; + +/** + * Base class for writing CDMI Expect tests + * + * @author Adrian Cole + */ +public class BaseCDMIExpectTest extends BaseRestClientExpectTest { + + public BaseCDMIExpectTest() { + provider = "cdmi"; + // now, createContext arg will need tenant prefix + identity = "tenantId:username"; + credential = "password"; + } +} diff --git a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/options/ListContainersOptionsTest.java b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/options/ListContainersOptionsTest.java new file mode 100644 index 0000000000..7753483dda --- /dev/null +++ b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/options/ListContainersOptionsTest.java @@ -0,0 +1,96 @@ +/** + * 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.snia.cdmi.v1.options; + +import static org.jclouds.snia.cdmi.v1.options.ListContainersOptions.Builder.limit; +import static org.jclouds.snia.cdmi.v1.options.ListContainersOptions.Builder.marker; +import static org.testng.Assert.assertEquals; + +import java.util.Collections; + +import org.jclouds.http.options.HttpRequestOptions; +import org.testng.annotations.Test; + +/** + * Tests possible uses of ListContainerOptions and ListContainerOptions.Builder.* + * + * @author Adrian Cole + */ +@Test(testName = "ListContainersOptionsTest") +public class ListContainersOptionsTest { + + @Test + public void testAssignability() { + assert HttpRequestOptions.class.isAssignableFrom(ListContainersOptions.class); + assert !String.class.isAssignableFrom(ListContainersOptions.class); + } + @Test + public void testNoOptionsQueryString() { + HttpRequestOptions options = new ListContainersOptions(); + assertEquals(options.buildQueryParameters().size(), 0); + } + + @Test + public void testMarker() { + ListContainersOptions options = new ListContainersOptions(); + options.marker("test"); + assertEquals(options.buildQueryParameters().get("marker"), Collections.singletonList("test")); + } + + @Test + public void testNullMarker() { + ListContainersOptions options = new ListContainersOptions(); + assertEquals(options.buildQueryParameters().get("marker"), Collections.EMPTY_LIST); + } + + @Test + public void testMarkerStatic() { + ListContainersOptions options = marker("test"); + assertEquals(options.buildQueryParameters().get("marker"), Collections.singletonList("test")); + } + + @Test(expectedExceptions = NullPointerException.class) + public void testMarkerNPE() { + marker(null); + } + + @Test + public void testLimit() { + ListContainersOptions options = new ListContainersOptions(); + options.limit(1000); + assertEquals(options.buildQueryParameters().get("limit"), Collections.singletonList("1000")); + } + + @Test + public void testNullLimit() { + ListContainersOptions options = new ListContainersOptions(); + assertEquals(options.buildQueryParameters().get("limit"), Collections.EMPTY_LIST); + } + + @Test + public void testLimitStatic() { + ListContainersOptions options = limit(1000); + assertEquals(options.buildQueryParameters().get("limit"), Collections.singletonList("1000")); + } + + @Test(expectedExceptions = IllegalStateException.class) + public void testLimitNegative() { + limit(-1); + } +} diff --git a/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/parse/ParseContainerTest.java b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/parse/ParseContainerTest.java new file mode 100644 index 0000000000..14fea2114b --- /dev/null +++ b/labs/cdmi/src/test/java/org/jclouds/snia/cdmi/v1/parse/ParseContainerTest.java @@ -0,0 +1,58 @@ +/** + * 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.snia.cdmi.v1.parse; + +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; + +import org.jclouds.json.BaseItemParserTest; +import org.jclouds.snia.cdmi.v1.domain.Container; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "ParseContainerTest") +public class ParseContainerTest extends BaseItemParserTest { + + @Override + public String resource() { + return "/container.json"; + } + + @Override + @Consumes(MediaType.APPLICATION_JSON) + public Container expected() { + return Container.builder() + .objectType("application/cdmi-container") + .objectID("00007E7F00102E230ED82694DAA975D2") + .objectName("MyContainer/") + .metadata(ImmutableMap.builder() + .put("cdmi_size", "83") + .build()) + .children(ImmutableSet.builder() + .add("MyDataObject.txt") + .build()) + .build(); + } +} diff --git a/labs/cdmi/src/test/resources/container.json b/labs/cdmi/src/test/resources/container.json new file mode 100644 index 0000000000..601a54d529 --- /dev/null +++ b/labs/cdmi/src/test/resources/container.json @@ -0,0 +1,17 @@ +{ + "objectType" : "application/cdmi-container", + "objectID" : "00007E7F00102E230ED82694DAA975D2", + "objectName" : "MyContainer/", + "parentURI" : "/", + "parentID" : "00007E7F0010128E42D87EE34F5A6560", + "domainURI" : "/cdmi_domains/MyDomain/", + "capabilitiesURI" : "/cdmi_capabilities/container/", + "completionStatus" : "Complete", + "metadata" : { + "cdmi_size" : "83" + }, + "childrenrange" : "0-0", + "children" : [ + "MyDataObject.txt" + ] +} \ No newline at end of file diff --git a/labs/cdmi/src/test/resources/logback.xml b/labs/cdmi/src/test/resources/logback.xml new file mode 100644 index 0000000000..bd89efb8c0 --- /dev/null +++ b/labs/cdmi/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/dmtf/src/main/java/org/jclouds/dmtf/CIMPredicates.java b/labs/dmtf/src/main/java/org/jclouds/dmtf/CIMPredicates.java new file mode 100644 index 0000000000..485877b765 --- /dev/null +++ b/labs/dmtf/src/main/java/org/jclouds/dmtf/CIMPredicates.java @@ -0,0 +1,59 @@ +/** + * 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.dmtf; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Set; + +import org.jclouds.dmtf.cim.ResourceAllocationSettingData; +import org.jclouds.dmtf.cim.ResourceAllocationSettingData.ResourceType; + +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableSet; + +/** + * + * @author danikov + */ +public class CIMPredicates { + + /** + * Return resource allocations of the specific type. + * + * @param type + * type to match the items + * @return predicate + */ + public static Predicate resourceTypeIn(final ResourceType... types) { + checkNotNull(types, "resourceTypes"); + final Set resourceTypes = ImmutableSet.copyOf(types); + return new Predicate() { + @Override + public boolean apply(ResourceAllocationSettingData in) { + return resourceTypes.contains(in.getResourceType()); + } + + @Override + public String toString() { + return "resourceTypeIn(" + resourceTypes + ")"; + } + }; + } +} diff --git a/labs/dmtf/src/main/java/org/jclouds/dmtf/cim/functions/HardwareBuilderFromResourceAllocations.java b/labs/dmtf/src/main/java/org/jclouds/dmtf/cim/functions/HardwareBuilderFromResourceAllocations.java new file mode 100644 index 0000000000..f881fa8343 --- /dev/null +++ b/labs/dmtf/src/main/java/org/jclouds/dmtf/cim/functions/HardwareBuilderFromResourceAllocations.java @@ -0,0 +1,75 @@ +/** + * 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.dmtf.cim.functions; + +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.find; +import static com.google.common.collect.Iterables.transform; + +import javax.inject.Singleton; + +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.domain.Processor; +import org.jclouds.compute.domain.Volume; +import org.jclouds.compute.domain.internal.VolumeImpl; +import org.jclouds.dmtf.CIMPredicates; +import org.jclouds.dmtf.cim.ResourceAllocationSettingData; +import org.jclouds.dmtf.cim.ResourceAllocationSettingData.ResourceType; + +import com.google.common.base.Function; + +/** + * @author Adrian Cole + */ +@Singleton +public class HardwareBuilderFromResourceAllocations implements + Function, HardwareBuilder> { + @Override + public HardwareBuilder apply(Iterable from) { + HardwareBuilder builder = new HardwareBuilder(); + builder.volumes(transform(filter(from, CIMPredicates.resourceTypeIn(ResourceType.DISK_DRIVE, + ResourceType.BASE_PARTITIONABLE_UNIT, ResourceType.PARTITIONABLE_UNIT)), + new Function() { + + @Override + public Volume apply(ResourceAllocationSettingData from) { + return HardwareBuilderFromResourceAllocations.this.apply(from); + } + + })); + + builder.ram((int) find(from, CIMPredicates.resourceTypeIn(ResourceType.MEMORY)).getVirtualQuantity().longValue()); + + builder.processors(transform(filter(from, CIMPredicates.resourceTypeIn(ResourceType.PROCESSOR)), + new Function() { + + @Override + public Processor apply(ResourceAllocationSettingData arg0) { + return new Processor(arg0.getVirtualQuantity().longValue(), 1); + } + })); + return builder; + } + + public Volume apply(ResourceAllocationSettingData from) { + return new VolumeImpl(from.getAddressOnParent() + "", Volume.Type.LOCAL, from.getVirtualQuantity() == null ? null + : from.getVirtualQuantity().longValue() / 1024 / 1024f, null, "0".equals(from.getAddressOnParent()) + || ResourceType.BASE_PARTITIONABLE_UNIT.equals(from.getResourceType()), true); + } +} \ No newline at end of file diff --git a/labs/glesys/src/test/java/org/jclouds/glesys/features/IpClientLiveTest.java b/labs/glesys/src/test/java/org/jclouds/glesys/features/IpClientLiveTest.java index 0ba66e1ade..092f16d1f5 100644 --- a/labs/glesys/src/test/java/org/jclouds/glesys/features/IpClientLiveTest.java +++ b/labs/glesys/src/test/java/org/jclouds/glesys/features/IpClientLiveTest.java @@ -63,7 +63,7 @@ public class IpClientLiveTest extends BaseGleSYSClientLiveTest { assertEquals(ipDetails.getIpversion(), "4"); // TODO: Ask Glesys to include address in response for OpenVZ? - // assertEquals(ipDetails.getAddress(), openVzIp); + // assertEquals(ipDetails.getHostText(), openVzIp); } @Test diff --git a/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/JenkinsAsyncClient.java b/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/JenkinsAsyncClient.java index aac4675d44..eec53e9615 100644 --- a/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/JenkinsAsyncClient.java +++ b/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/JenkinsAsyncClient.java @@ -18,8 +18,21 @@ */ package org.jclouds.jenkins.v1; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.core.MediaType; + +import org.jclouds.jenkins.v1.domain.Node; import org.jclouds.jenkins.v1.features.ComputerAsyncClient; +import org.jclouds.jenkins.v1.features.JobAsyncClient; +import org.jclouds.jenkins.v1.filters.BasicAuthenticationUnlessAnonymous; import org.jclouds.rest.annotations.Delegate; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; /** * Provides asynchronous access to Jenkins via their REST API. @@ -29,13 +42,27 @@ import org.jclouds.rest.annotations.Delegate; * @see api doc * @author Adrian Cole */ +@RequestFilters(BasicAuthenticationUnlessAnonymous.class) public interface JenkinsAsyncClient { - - + + /** + * @see JenkinsClient#getMaster + */ + @GET + @Path("/api/json") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getMaster(); + /** * Provides asynchronous access to Computer features. */ @Delegate ComputerAsyncClient getComputerClient(); - + + /** + * Provides asynchronous access to Job features. + */ + @Delegate + JobAsyncClient getJobClient(); } diff --git a/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/JenkinsClient.java b/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/JenkinsClient.java index b0653af12b..93db464829 100644 --- a/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/JenkinsClient.java +++ b/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/JenkinsClient.java @@ -21,7 +21,9 @@ package org.jclouds.jenkins.v1; import java.util.concurrent.TimeUnit; import org.jclouds.concurrent.Timeout; +import org.jclouds.jenkins.v1.domain.Node; import org.jclouds.jenkins.v1.features.ComputerClient; +import org.jclouds.jenkins.v1.features.JobClient; import org.jclouds.rest.annotations.Delegate; /** @@ -34,11 +36,20 @@ import org.jclouds.rest.annotations.Delegate; */ @Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) public interface JenkinsClient { + /** + * @return the master computer + */ + Node getMaster(); /** * Provides synchronous access to Computer features. */ @Delegate ComputerClient getComputerClient(); - + + /** + * Provides synchronous access to Job features. + */ + @Delegate + JobClient getJobClient(); } diff --git a/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/config/JenkinsRestClientModule.java b/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/config/JenkinsRestClientModule.java index b0e11aa31c..37a957f4a9 100644 --- a/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/config/JenkinsRestClientModule.java +++ b/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/config/JenkinsRestClientModule.java @@ -28,6 +28,8 @@ import org.jclouds.jenkins.v1.JenkinsAsyncClient; import org.jclouds.jenkins.v1.JenkinsClient; import org.jclouds.jenkins.v1.features.ComputerAsyncClient; import org.jclouds.jenkins.v1.features.ComputerClient; +import org.jclouds.jenkins.v1.features.JobAsyncClient; +import org.jclouds.jenkins.v1.features.JobClient; import org.jclouds.jenkins.v1.handlers.JenkinsErrorHandler; import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.config.RestClientModule; @@ -44,6 +46,7 @@ public class JenkinsRestClientModule extends RestClientModule, Class> DELEGATE_MAP = ImmutableMap., Class> builder() .put(ComputerClient.class, ComputerAsyncClient.class) + .put(JobClient.class, JobAsyncClient.class) .build(); public JenkinsRestClientModule() { diff --git a/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/domain/Job.java b/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/domain/Job.java new file mode 100644 index 0000000000..b003617fe0 --- /dev/null +++ b/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/domain/Job.java @@ -0,0 +1,157 @@ +/** + * 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.jenkins.v1.domain; + +import static com.google.common.base.Objects.equal; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.net.URI; + +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; + +/** + * Minimal info about a Job + * + * @author Adrian Cole + */ +public class Job { + + public static Builder builder() { + return new ConcreteBuilder(); + } + + public Builder toBuilder() { + return builder().fromJob(this); + } + + private static class ConcreteBuilder extends Builder { + } + + public static abstract class Builder> { + private String name; + private URI url; + private String color; + + @SuppressWarnings("unchecked") + protected B self() { + return (B) this; + } + + /** + * @see Job#getName() + */ + public B name(String name) { + this.name = name; + return self(); + } + + /** + * @see Job#getUrl() + */ + public B url(URI url) { + this.url = url; + return self(); + } + + /** + * @see Job#getColor() + */ + public B color(String color) { + this.color = color; + return self(); + } + + public Job build() { + return new Job(this); + } + + protected B fromJob(Job in) { + return name(in.getName()).color(in.getColor()).url(in.getUrl()); + } + } + + private final String name; + private final String color; + private final URI url; + + protected Job(Builder builder) { + this.name = checkNotNull(builder.name, "name"); + this.color = checkNotNull(builder.color, "color"); + this.url = checkNotNull(builder.url, "url"); + } + + /** + * name of the job + */ + public String getName() { + return name; + } + + /** + * + * color of the job + */ + public String getColor() { + return color; + } + + /** + * + * url of the job + */ + public URI getUrl() { + return url; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + Job that = Job.class.cast(o); + return equal(this.name, that.name) && equal(this.url, that.url) + && equal(this.color, that.color); + } + + public boolean clone(Object o) { + if (this == o) + return false; + if (o == null || getClass() != o.getClass()) + return false; + Job that = Job.class.cast(o); + return equal(this.color, that.color); + } + + @Override + public int hashCode() { + return Objects.hashCode(name, url, color); + } + + @Override + public String toString() { + return string().toString(); + } + + protected ToStringHelper string() { + return Objects.toStringHelper("").add("name", name).add("url", url).add("color", + color); + } +} diff --git a/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/domain/JobDetails.java b/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/domain/JobDetails.java new file mode 100644 index 0000000000..09519baae2 --- /dev/null +++ b/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/domain/JobDetails.java @@ -0,0 +1,62 @@ +/** + * 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.jenkins.v1.domain; + +import com.google.common.base.Objects.ToStringHelper; + +/** + * + * @author Adrian Cole + */ +public class JobDetails extends Job { + + public static Builder builder() { + return new ConcreteBuilder(); + } + + @Override + public Builder toBuilder() { + return builder().fromJobDetails(this); + } + + public static class Builder> extends Job.Builder { + + @Override + public JobDetails build() { + return new JobDetails(this); + } + + public B fromJobDetails(JobDetails in) { + return fromJob(in); + } + } + + private static class ConcreteBuilder extends Builder { + } + + protected JobDetails(Builder builder) { + super(builder); + } + + @Override + public ToStringHelper string() { + return super.string(); // .add("field", field); + } + +} diff --git a/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/domain/Node.java b/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/domain/Node.java new file mode 100644 index 0000000000..ab4f15cd6c --- /dev/null +++ b/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/domain/Node.java @@ -0,0 +1,147 @@ +package org.jclouds.jenkins.v1.domain; + +import static com.google.common.base.Objects.equal; +import static com.google.common.base.Objects.toStringHelper; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Set; + +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; +import com.google.common.collect.ImmutableSet; +import com.google.gson.annotations.SerializedName; + +/** + * @author Adrian Cole + * @see api + * doc + */ +public class Node implements Comparable { + + public static Builder builder() { + return new Builder(); + } + + public Builder toBuilder() { + return builder().fromNodeMetadata(this); + } + + public static class Builder { + protected String name; + protected String description; + protected Set jobs = ImmutableSet.of(); + + /** + * @see Node#getName() + */ + public Builder name(String name) { + this.name = checkNotNull(name, "name"); + return this; + } + + /** + * @see Node#getDescription() + */ + public Builder description(String description) { + this.description = description; + return this; + } + + /** + * @see Node#getJobs() + */ + public Builder jobs(Job... jobs) { + return jobs(ImmutableSet.copyOf(checkNotNull(jobs, "jobs"))); + } + + /** + * @see Node#getJobs() + */ + public Builder jobs(Set jobs) { + this.jobs = ImmutableSet.copyOf(checkNotNull(jobs, "jobs")); + return this; + } + + public Node build() { + return new Node(name, description, jobs); + } + + public Builder fromNodeMetadata(Node from) { + return name(from.getName()).description(from.getDescription()).jobs(from.getJobs()); + } + } + + @SerializedName("nodeName") + protected final String name; + @SerializedName("nodeDescription") + protected final String description; + protected final Set jobs; + + public Node(String name, String description, Set jobs) { + this.name = checkNotNull(name, "name"); + this.description = description; + this.jobs = ImmutableSet.copyOf(checkNotNull(jobs, "jobs")); + } + + /** + * + * @return the name of the node + */ + public String getName() { + return name; + } + + /** + * + * @return the description of the node + */ + public String getDescription() { + return description; + } + + /** + * @return the jobs on this node + */ + public Set getJobs() { + return jobs; + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object instanceof Node) { + final Node other = Node.class.cast(object); + return equal(getName(), other.getName()) && equal(getDescription(), other.getDescription()) + && equal(getJobs(), other.getJobs()); + } else { + return false; + } + } + + @Override + public int hashCode() { + return Objects.hashCode(getName(), getDescription(), getJobs()); + } + + @Override + public String toString() { + return string().toString(); + } + + protected ToStringHelper string() { + return toStringHelper("").add("name", getName()).add("description", getDescription()).add("jobs", getJobs()); + } + + @Override + public int compareTo(Node that) { + if (that == null) + return 1; + if (this == that) + return 0; + return this.getName().compareTo(that.getName()); + } + +} diff --git a/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/features/ComputerAsyncClient.java b/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/features/ComputerAsyncClient.java index 0ef8154e58..30953985a4 100644 --- a/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/features/ComputerAsyncClient.java +++ b/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/features/ComputerAsyncClient.java @@ -46,19 +46,20 @@ import com.google.common.util.concurrent.ListenableFuture; public interface ComputerAsyncClient { /** - * @see ComputerClient#getComputerView + * @see ComputerClient#getView */ @GET @Path("/computer/api/json") @Consumes(MediaType.APPLICATION_JSON) - ListenableFuture getComputerView(); + ListenableFuture getView(); /** - * @see ComputerClient#getComputer + * @see ComputerClient#get */ @GET @Path("/computer/{displayName}/api/json") @Consumes(MediaType.APPLICATION_JSON) @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getComputer(@PathParam("displayName") String displayName); + ListenableFuture get(@PathParam("displayName") String displayName); + } diff --git a/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/features/ComputerClient.java b/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/features/ComputerClient.java index 1ab93add18..25beb3fcf5 100644 --- a/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/features/ComputerClient.java +++ b/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/features/ComputerClient.java @@ -37,12 +37,13 @@ public interface ComputerClient { /** * @return overview of all configured computers */ - ComputerView getComputerView(); + ComputerView getView(); /** * * @param displayName display name of the computer * @return computer or null if not found */ - Computer getComputer(String displayName); + Computer get(String displayName); + } diff --git a/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/features/JobAsyncClient.java b/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/features/JobAsyncClient.java new file mode 100644 index 0000000000..45b612aa5d --- /dev/null +++ b/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/features/JobAsyncClient.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 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.jenkins.v1.features; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; + +import org.jclouds.jenkins.v1.domain.JobDetails; +import org.jclouds.jenkins.v1.filters.BasicAuthenticationUnlessAnonymous; +import org.jclouds.jenkins.v1.functions.ReturnVoidOn302Or404; +import org.jclouds.rest.annotations.BinderParam; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.binders.BindToStringPayload; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Job Services + * + * @see JobClient + * @author Adrian Cole + * @see api doc + */ +@RequestFilters(BasicAuthenticationUnlessAnonymous.class) +public interface JobAsyncClient { + + /** + * @see JobClient#createFromXML + */ + @POST + @Path("/createItem") + @Produces(MediaType.TEXT_XML) + ListenableFuture createFromXML(@QueryParam("name") String displayName, @BinderParam(BindToStringPayload.class) String xml); + + /** + * @see JobClient#get + */ + @GET + @Path("/job/{displayName}/api/json") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture get(@PathParam("displayName") String displayName); + + /** + * @see JobClient#delete + */ + @POST + @Path("/job/{displayName}/doDelete") + @ExceptionParser(ReturnVoidOn302Or404.class) + ListenableFuture delete(@PathParam("displayName") String displayName); + + /** + * @see JobClient#buildJob + */ + @POST + @Path("/job/{displayName}/build") + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture build(@PathParam("displayName") String displayName); + + /** + * @see JobClient#fetchConfigXML + */ + @GET + @Path("/job/{displayName}/config.xml") + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture fetchConfigXML(@PathParam("displayName") String displayName); + +} diff --git a/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/features/JobClient.java b/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/features/JobClient.java new file mode 100644 index 0000000000..cce44bcdfc --- /dev/null +++ b/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/features/JobClient.java @@ -0,0 +1,60 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.jenkins.v1.features; + +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.jenkins.v1.domain.JobDetails; + +/** + * Job Services + * + * @see JobAsyncClient + * @author Adrian Cole + * @see api doc + */ +@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS) +public interface JobClient { + + /** + * creates a job, given the payload + * + * @param displayName + * @param xml + */ + void createFromXML(String displayName, String xml); + + JobDetails get(String displayName); + + void delete(String displayName); + + /** + * Build a job via API + * + * If security is enabled, provide username/password of an account with build permission in the request. + * Another alternative (but deprecated) is to configure the 'Trigger builds remotely' section in the job configuration. + * + * @param displayName + */ + void build(String displayName); + + String fetchConfigXML(String displayName); + +} diff --git a/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/functions/ReturnVoidOn302Or404.java b/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/functions/ReturnVoidOn302Or404.java new file mode 100644 index 0000000000..0306c7f161 --- /dev/null +++ b/labs/jenkins/src/main/java/org/jclouds/jenkins/v1/functions/ReturnVoidOn302Or404.java @@ -0,0 +1,43 @@ +/** + * 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.jenkins.v1.functions; + +import static com.google.common.base.Predicates.equalTo; +import static org.jclouds.http.HttpUtils.returnValueOnCodeOrNull; + +import javax.inject.Singleton; + +import com.google.common.base.Function; +import com.google.common.base.Predicates; +import com.google.common.base.Throwables; + +/** + * + * @author Adrian Cole + */ +@Singleton +public class ReturnVoidOn302Or404 implements Function { + + public Void apply(Exception from) { + Boolean returnVal = returnValueOnCodeOrNull(from, true, Predicates.or(equalTo(302), equalTo(404))); + if (returnVal != null && returnVal) + return null; + throw Throwables.propagate(from); + } +} \ No newline at end of file diff --git a/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/JenkinsClientExpectTest.java b/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/JenkinsClientExpectTest.java new file mode 100644 index 0000000000..77ae552d59 --- /dev/null +++ b/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/JenkinsClientExpectTest.java @@ -0,0 +1,58 @@ +/** + * 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.jenkins.v1; + +import static org.testng.Assert.assertEquals; + +import java.net.URI; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.jenkins.v1.internal.BaseJenkinsClientExpectTest; +import org.jclouds.jenkins.v1.parse.ParseNodeTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMultimap; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "JenkinsClientExpectTest") +public class JenkinsClientExpectTest extends BaseJenkinsClientExpectTest { + + public void testGetMasterWhenResponseIs2xx() { + HttpRequest getMaster = HttpRequest + .builder() + .method("GET") + .endpoint(URI.create("http://localhost:8080/api/json")) + .headers( + ImmutableMultimap. builder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()).build(); + + HttpResponse getMasterResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/master.json")).build(); + + JenkinsClient clientWhenMasterExists = requestSendsResponse(getMaster, getMasterResponse); + + assertEquals(clientWhenMasterExists.getMaster().toString(), + new ParseNodeTest().expected().toString()); + } +} diff --git a/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/JenkinsClientLiveTest.java b/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/JenkinsClientLiveTest.java new file mode 100644 index 0000000000..ae1b83c3b7 --- /dev/null +++ b/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/JenkinsClientLiveTest.java @@ -0,0 +1,41 @@ +/** + * 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.jenkins.v1; + +import static org.testng.Assert.assertNotNull; + +import org.jclouds.jenkins.v1.domain.Node; +import org.jclouds.jenkins.v1.internal.BaseJenkinsClientLiveTest; +import org.testng.annotations.Test; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "live", testName = "JenkinsClientLiveTest") +public class JenkinsClientLiveTest extends BaseJenkinsClientLiveTest { + + public void testGetMaster(){ + Node master = context.getApi().getMaster(); + assertNotNull(master); + assertNotNull(master.getName()); + assertNotNull(master.getJobs()); + } + +} \ No newline at end of file diff --git a/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/features/ComputerClientExpectTest.java b/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/features/ComputerClientExpectTest.java index 47ebdcff41..0dfe1d659d 100644 --- a/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/features/ComputerClientExpectTest.java +++ b/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/features/ComputerClientExpectTest.java @@ -53,7 +53,7 @@ public class ComputerClientExpectTest extends BaseJenkinsClientExpectTest { JenkinsClient clientWhenServersExist = requestSendsResponse(getComputerView, getComputerViewResponse); - assertEquals(clientWhenServersExist.getComputerClient().getComputerView().toString(), + assertEquals(clientWhenServersExist.getComputerClient().getView().toString(), new ParseComputerViewTest().expected().toString()); } @@ -71,7 +71,7 @@ public class ComputerClientExpectTest extends BaseJenkinsClientExpectTest { JenkinsClient clientWhenServersExist = requestSendsResponse(getComputer, getComputerResponse); - assertEquals(clientWhenServersExist.getComputerClient().getComputer("Ruboto").toString(), + assertEquals(clientWhenServersExist.getComputerClient().get("Ruboto").toString(), new ParseComputerTest().expected().toString()); } } diff --git a/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/features/ComputerClientLiveTest.java b/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/features/ComputerClientLiveTest.java index 45d0b3d90c..753c9f9ca9 100644 --- a/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/features/ComputerClientLiveTest.java +++ b/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/features/ComputerClientLiveTest.java @@ -34,13 +34,13 @@ import org.testng.annotations.Test; public class ComputerClientLiveTest extends BaseJenkinsClientLiveTest { public void testGetComputerView(){ - ComputerView view = getClient().getComputerView(); + ComputerView view = getClient().getView(); assertNotNull(view); assertNotNull(view.getDisplayName()); for (Computer computerFromView : view.getComputers()) { assertNotNull(computerFromView.getDisplayName()); if (!"master".equals(computerFromView.getDisplayName())) { - Computer computerFromGetRequest = getClient().getComputer(computerFromView.getDisplayName()); + Computer computerFromGetRequest = getClient().get(computerFromView.getDisplayName()); assertEquals(computerFromGetRequest, computerFromView); } } diff --git a/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/features/JobClientExpectTest.java b/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/features/JobClientExpectTest.java new file mode 100644 index 0000000000..e41d1b6bf6 --- /dev/null +++ b/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/features/JobClientExpectTest.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.jenkins.v1.features; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +import java.io.IOException; +import java.net.URI; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.jenkins.v1.JenkinsClient; +import org.jclouds.jenkins.v1.internal.BaseJenkinsClientExpectTest; +import org.jclouds.jenkins.v1.parse.ParseJobDetailsTest; +import org.jclouds.util.Strings2; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMultimap; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "JobClientExpectTest") +public class JobClientExpectTest extends BaseJenkinsClientExpectTest { + + public void testCreateJobStringWhenResponseIs2xx() throws IOException { + HttpRequest createJob = HttpRequest.builder() + .method("POST") + .endpoint(URI.create("http://localhost:8080/createItem?name=blagoo")) + .headers(ImmutableMultimap. builder() + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .payload(payloadFromResourceWithContentType("/sample_job.xml", "text/xml")) + .build(); + + HttpResponse createJobResponse = HttpResponse.builder().statusCode(200).build(); + + JenkinsClient createJobWhenCreated = requestSendsResponse(createJob, createJobResponse); + + createJobWhenCreated.getJobClient().createFromXML("blagoo", Strings2.toStringAndClose(getClass().getResourceAsStream("/sample_job.xml"))); + } + + public void testDeleteJobWhenResponseIs2xx() { + HttpRequest deleteJob = HttpRequest.builder() + .method("POST") + .endpoint(URI.create("http://localhost:8080/job/blagoo/doDelete")) + .headers(ImmutableMultimap. builder() + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .build(); + + HttpResponse deleteJobResponse = HttpResponse.builder().statusCode(200).build(); + + JenkinsClient deleteJobWhenDeleted = requestSendsResponse(deleteJob, deleteJobResponse); + + deleteJobWhenDeleted.getJobClient().delete("blagoo"); + } + + public void testDeleteJobWhenResponseIs404() { + HttpRequest deleteJob = HttpRequest.builder() + .method("POST") + .endpoint(URI.create("http://localhost:8080/job/blagoo/doDelete")) + .headers(ImmutableMultimap. builder() + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .build(); + + HttpResponse deleteJobResponse = HttpResponse.builder().statusCode(404).build(); + + JenkinsClient deleteJobWhenDeleted = requestSendsResponse(deleteJob, deleteJobResponse); + + deleteJobWhenDeleted.getJobClient().delete("blagoo"); + } + + HttpRequest getJob = HttpRequest.builder() + .method("GET") + .endpoint(URI.create("http://localhost:8080/job/ddd/api/json")) + .headers(ImmutableMultimap. builder() + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .build(); + + public void testGetJobWhenResponseIs2xx() { + HttpResponse getJobResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResource("/job.json")).build(); + JenkinsClient clientWhenJobExists = requestSendsResponse(getJob, getJobResponse); + assertEquals(clientWhenJobExists.getJobClient().get("ddd").toString(), + new ParseJobDetailsTest().expected().toString()); + } + + public void testGetJobWhenResponseIs404() { + HttpResponse getJobResponse = HttpResponse.builder().statusCode(404).build(); + JenkinsClient getJobWhenGetd = requestSendsResponse(getJob, getJobResponse); + assertNull(getJobWhenGetd.getJobClient().get("ddd")); + } + + HttpRequest buildJob = HttpRequest.builder() + .method("POST") + .endpoint(URI.create("http://localhost:8080/job/ddd/build")) + .headers(ImmutableMultimap. builder() + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .build(); + + public void testBuildJobWhenResponseIs2xx() { + HttpResponse buildJobResponse = HttpResponse.builder().statusCode(200).build(); + JenkinsClient clientWhenJobExists = requestSendsResponse(buildJob, buildJobResponse); + clientWhenJobExists.getJobClient().build("ddd"); + } + + public void testBuildJobWhenResponseIs404() { + HttpResponse getJobResponse = HttpResponse.builder().statusCode(404).build(); + JenkinsClient getJobWhenGetd = requestSendsResponse(buildJob, getJobResponse); + getJobWhenGetd.getJobClient().build("ddd"); + } + + HttpRequest fetchConfig = HttpRequest.builder() + .method("GET") + .endpoint(URI.create("http://localhost:8080/job/ddd/config.xml")) + .headers(ImmutableMultimap. builder() + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .build(); + + public void testFetchConfigXMLWhenResponseIs2xx() { + HttpResponse fetchConfigResponse = HttpResponse.builder().statusCode(200) + .payload(payloadFromResourceWithContentType("/sample_job.xml", "text/xml")).build(); + JenkinsClient clientWhenJobExists = requestSendsResponse(fetchConfig, fetchConfigResponse); + String configXML = clientWhenJobExists.getJobClient().fetchConfigXML("ddd"); + //TODO enable this assertion + //assertEquals(configXML, Strings2.toStringAndClose(getClass().getResourceAsStream("/sample_job.xml"))); + } + + public void testFetchConfigXMLWhenResponseIs404() { + HttpResponse fetchConfigResponse = HttpResponse.builder().statusCode(404).build(); + JenkinsClient getJobWhenGetd = requestSendsResponse(fetchConfig, fetchConfigResponse); + getJobWhenGetd.getJobClient().fetchConfigXML("ddd"); + } +} diff --git a/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/features/JobClientLiveTest.java b/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/features/JobClientLiveTest.java new file mode 100644 index 0000000000..ae7218b056 --- /dev/null +++ b/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/features/JobClientLiveTest.java @@ -0,0 +1,80 @@ +/** + * 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.jenkins.v1.features; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; + +import java.io.IOException; + +import org.jclouds.jenkins.v1.domain.JobDetails; +import org.jclouds.jenkins.v1.internal.BaseJenkinsClientLiveTest; +import org.jclouds.util.Strings2; +import org.testng.annotations.AfterClass; +import org.testng.annotations.Test; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "live", testName = "JobClientLiveTest") +public class JobClientLiveTest extends BaseJenkinsClientLiveTest { + + public void testCreateJob() throws IOException { + getClient().delete("blagoo"); + getClient().createFromXML("blagoo", Strings2.toStringAndClose(getClass().getResourceAsStream("/sample_job.xml"))); + } + + @Test(dependsOnMethods = "testCreateJob") + public void testFetchConfigXML() throws IOException { + String configXML = getClient().fetchConfigXML("blagoo"); + assertNotNull(configXML); + //TODO enable this assertion + //assertEquals(configXML, Strings2.toStringAndClose(getClass().getResourceAsStream("/sample_job.xml"))); + } + + @Test(dependsOnMethods = "testFetchConfigXML") + public void testGetJob() throws IOException { + JobDetails job = getClient().get("blagoo"); + assertNotNull(job); + assertEquals(job.getName(), "blagoo"); + } + + @Test(dependsOnMethods = "testGetJob") + public void testBuildJob() throws IOException { + getClient().build("blagoo"); + } + + @Test(dependsOnMethods = "testBuildJob") + public void testDeleteJob() { + getClient().delete("blagoo"); + } + + @AfterClass(groups = { "integration", "live" }) + @Override + protected void tearDownContext() { + getClient().delete("blagoo"); + getClient().delete("blagooCopy"); + super.tearDownContext(); + } + + private JobClient getClient() { + return context.getApi().getJobClient(); + } +} \ No newline at end of file diff --git a/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/filters/BasicAuthenticationUnlessAnonymousExpectTest.java b/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/filters/BasicAuthenticationUnlessAnonymousExpectTest.java index f281b7920f..46729de877 100644 --- a/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/filters/BasicAuthenticationUnlessAnonymousExpectTest.java +++ b/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/filters/BasicAuthenticationUnlessAnonymousExpectTest.java @@ -56,7 +56,7 @@ public class BasicAuthenticationUnlessAnonymousExpectTest extends BaseJenkinsCli JenkinsClient clientWhenServersExist = requestSendsResponse(getComputerView, getComputerViewResponse); - assertEquals(clientWhenServersExist.getComputerClient().getComputerView().toString(), + assertEquals(clientWhenServersExist.getComputerClient().getView().toString(), new ParseComputerViewTest().expected().toString()); } } diff --git a/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/internal/BaseJenkinsClientLiveTest.java b/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/internal/BaseJenkinsClientLiveTest.java index e934c87467..90bedb5c0d 100644 --- a/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/internal/BaseJenkinsClientLiveTest.java +++ b/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/internal/BaseJenkinsClientLiveTest.java @@ -23,8 +23,7 @@ import org.jclouds.jenkins.v1.JenkinsApiMetadata; import org.jclouds.jenkins.v1.JenkinsAsyncClient; import org.jclouds.jenkins.v1.JenkinsClient; import org.jclouds.rest.RestContext; -import org.testng.annotations.AfterGroups; -import org.testng.annotations.BeforeGroups; +import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import com.google.common.reflect.TypeToken; @@ -42,20 +41,14 @@ public class BaseJenkinsClientLiveTest extends BaseContextLiveTest jenkinsContext; - - @BeforeGroups(groups = { "integration", "live" }) + + @BeforeClass(groups = { "integration", "live" }) @Override public void setupContext() { super.setupContext(); jenkinsContext = context; } - @AfterGroups(groups = "live") - protected void tearDown() { - if (jenkinsContext != null) - jenkinsContext.close(); - } - @Override protected TypeToken> contextType() { return JenkinsApiMetadata.CONTEXT_TOKEN; diff --git a/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/parse/ParseJobDetailsTest.java b/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/parse/ParseJobDetailsTest.java new file mode 100644 index 0000000000..cf2934fc76 --- /dev/null +++ b/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/parse/ParseJobDetailsTest.java @@ -0,0 +1,50 @@ +/** + * 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.jenkins.v1.parse; + +import java.net.URI; + +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; + +import org.jclouds.jenkins.v1.domain.JobDetails; +import org.jclouds.json.BaseItemParserTest; +import org.testng.annotations.Test; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "ParseJobDetailsTest") +public class ParseJobDetailsTest extends BaseItemParserTest { + + @Override + public String resource() { + return "/job.json"; + } + + @Override + @Consumes(MediaType.APPLICATION_JSON) + public JobDetails expected() { + return JobDetails.builder() + .name("ddd") + .url(URI.create("http://localhost:8080/job/ddd/")) + .color("grey").build(); + } +} diff --git a/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/parse/ParseNodeTest.java b/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/parse/ParseNodeTest.java new file mode 100644 index 0000000000..d2ec328d32 --- /dev/null +++ b/labs/jenkins/src/test/java/org/jclouds/jenkins/v1/parse/ParseNodeTest.java @@ -0,0 +1,55 @@ +/** + * 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.jenkins.v1.parse; + +import java.net.URI; + +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; + +import org.jclouds.jenkins.v1.domain.Job; +import org.jclouds.jenkins.v1.domain.Node; +import org.jclouds.json.BaseItemParserTest; +import org.testng.annotations.Test; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "ParseNodeTest") +public class ParseNodeTest extends BaseItemParserTest { + + @Override + public String resource() { + return "/master.json"; + } + + @Override + @Consumes(MediaType.APPLICATION_JSON) + public Node expected() { + return Node.builder() + .name("") + .description("the master Jenkins node") + .jobs(Job.builder() + .name("ddd") + .url(URI.create("http://localhost:8080/job/ddd/")) + .color("grey").build()) + .build(); + } +} diff --git a/labs/jenkins/src/test/resources/job.json b/labs/jenkins/src/test/resources/job.json new file mode 100644 index 0000000000..ebf43f35fb --- /dev/null +++ b/labs/jenkins/src/test/resources/job.json @@ -0,0 +1,29 @@ +{ + "actions": [], + "description": "", + "displayName": "ddd", + "displayNameOrNull": null, + "name": "ddd", + "url": "http://localhost:8080/job/ddd/", + "buildable": true, + "builds": [], + "color": "grey", + "firstBuild": null, + "healthReport": [], + "inQueue": false, + "keepDependencies": false, + "lastBuild": null, + "lastCompletedBuild": null, + "lastFailedBuild": null, + "lastStableBuild": null, + "lastSuccessfulBuild": null, + "lastUnstableBuild": null, + "lastUnsuccessfulBuild": null, + "nextBuildNumber": 1, + "property": [], + "queueItem": null, + "concurrentBuild": false, + "downstreamProjects": [], + "scm": {}, + "upstreamProjects": [] +} \ No newline at end of file diff --git a/labs/jenkins/src/test/resources/master.json b/labs/jenkins/src/test/resources/master.json new file mode 100644 index 0000000000..8e5c622b95 --- /dev/null +++ b/labs/jenkins/src/test/resources/master.json @@ -0,0 +1,26 @@ +{ + "assignedLabels": [{}], + "mode": "NORMAL", + "nodeDescription": "the master Jenkins node", + "nodeName": "", + "numExecutors": 2, + "description": null, + "jobs": [{ + "name": "ddd", + "url": "http://localhost:8080/job/ddd/", + "color": "grey" + }], + "overallLoad": {}, + "primaryView": { + "name": "All", + "url": "http://localhost:8080/" + }, + "quietingDown": false, + "slaveAgentPort": 0, + "useCrumbs": false, + "useSecurity": false, + "views": [{ + "name": "All", + "url": "http://localhost:8080/" + }] +} \ No newline at end of file diff --git a/labs/jenkins/src/test/resources/sample_job.xml b/labs/jenkins/src/test/resources/sample_job.xml new file mode 100644 index 0000000000..9b74eb35a0 --- /dev/null +++ b/labs/jenkins/src/test/resources/sample_job.xml @@ -0,0 +1,21 @@ + + + + + false + + + true + false + false + false + + false + + + echo hello + + + + + \ No newline at end of file diff --git a/labs/joyent-sdc/pom.xml b/labs/joyent-sdc/pom.xml new file mode 100644 index 0000000000..58f0315af9 --- /dev/null +++ b/labs/joyent-sdc/pom.xml @@ -0,0 +1,123 @@ + + + + 4.0.0 + + org.jclouds + jclouds-project + 1.5.0-SNAPSHOT + ../../project/pom.xml + + org.jclouds.labs + joyent-sdc + jcloud joyent-sdc api + jclouds components to access an implementation of Joyent SDC + bundle + + + https://api.joyentcloud.com + ~6.5 + + FIXME_IDENTITY + FIXME_CREDENTIALS + + + + + org.jclouds + jclouds-core + ${project.version} + + + org.jclouds + jclouds-core + ${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.joyent-sdc.endpoint} + ${test.joyent-sdc.api-version} + ${test.joyent-sdc.build-version} + ${test.joyent-sdc.identity} + ${test.joyent-sdc.credential} + + + + + + + + + + + + + + org.apache.felix + maven-bundle-plugin + + + ${project.artifactId} + org.jclouds.joyent.sdc.v6_5*;version="${project.version}" + + org.jclouds.rest.internal;version="${project.version}", + org.jclouds*;version="${project.version}", + * + + + + + + + + diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/SDCApiMetadata.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/SDCApiMetadata.java new file mode 100644 index 0000000000..c3042a9dfe --- /dev/null +++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/SDCApiMetadata.java @@ -0,0 +1,93 @@ +/** + * 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.joyent.sdc.v6_5; + +import java.net.URI; +import java.util.Properties; + +import org.jclouds.apis.ApiMetadata; +import org.jclouds.joyent.sdc.v6_5.config.SDCRestClientModule; +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 SDC ~6.5 API + * + * @author Adrian Cole + */ +public class SDCApiMetadata extends BaseRestApiMetadata { + + /** The serialVersionUID */ + private static final long serialVersionUID = 6725672099385580694L; + + public static final TypeToken> CONTEXT_TOKEN = new TypeToken>() { + private static final long serialVersionUID = -5070937833892503232L; + }; + + @Override + public Builder toBuilder() { + return new Builder().fromApiMetadata(this); + } + + public SDCApiMetadata() { + this(new Builder()); + } + + protected SDCApiMetadata(Builder builder) { + super(builder); + } + + public static Properties defaultProperties() { + Properties properties = BaseRestApiMetadata.defaultProperties(); + return properties; + } + + public static class Builder extends BaseRestApiMetadata.Builder { + + protected Builder() { + super(SDCClient.class, SDCAsyncClient.class); + id("joyent-sdc") + .name("Joyent SDC API") + .identityName("username") + .credentialName("password") + .documentation(URI.create("http://sdc.joyent.org/sdcapi.html")) + .version("~6.5") + .defaultEndpoint("https://api.joyentcloud.com") + .defaultProperties(SDCApiMetadata.defaultProperties()) + .defaultModules(ImmutableSet.>of(SDCRestClientModule.class)); + } + + @Override + public SDCApiMetadata build() { + return new SDCApiMetadata(this); + } + + @Override + public Builder fromApiMetadata(ApiMetadata in) { + super.fromApiMetadata(in); + return this; + } + + } + +} diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/SDCAsyncClient.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/SDCAsyncClient.java new file mode 100644 index 0000000000..e4e42de97b --- /dev/null +++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/SDCAsyncClient.java @@ -0,0 +1,40 @@ +/** + * 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.joyent.sdc.v6_5; + +import org.jclouds.joyent.sdc.v6_5.features.DatacenterAsyncClient; +import org.jclouds.rest.annotations.Delegate; + +/** + * Provides asynchronous access to SDC via their REST API. + *

+ * + * @see SDCClient + * @see api doc + * @author Adrian Cole + */ +public interface SDCAsyncClient { + + /** + * Provides asynchronous access to Datacenter features. + */ + @Delegate + DatacenterAsyncClient getDatacenterClient(); + +} diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/SDCClient.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/SDCClient.java new file mode 100644 index 0000000000..47ebe9fa27 --- /dev/null +++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/SDCClient.java @@ -0,0 +1,44 @@ +/** + * 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.joyent.sdc.v6_5; + +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.joyent.sdc.v6_5.features.DatacenterClient; +import org.jclouds.rest.annotations.Delegate; + +/** + * Provides synchronous access to SDC. + *

+ * + * @see SDCAsyncClient + * @see api doc + * @author Adrian Cole + */ +@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) +public interface SDCClient { + + /** + * Provides synchronous access to Datacenter features. + */ + @Delegate + DatacenterClient getDatacenterClient(); + +} diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/config/SDCProperties.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/config/SDCProperties.java new file mode 100644 index 0000000000..dd0190e258 --- /dev/null +++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/config/SDCProperties.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.joyent.sdc.v6_5.config; + +/** + * Configuration properties and constants used in joyent SDC connections. + * + * @author Adrian Cole + */ +public class SDCProperties { + +} diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/config/SDCRestClientModule.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/config/SDCRestClientModule.java new file mode 100644 index 0000000000..201cb77bd4 --- /dev/null +++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/config/SDCRestClientModule.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.joyent.sdc.v6_5.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.joyent.sdc.v6_5.SDCAsyncClient; +import org.jclouds.joyent.sdc.v6_5.SDCClient; +import org.jclouds.joyent.sdc.v6_5.features.DatacenterAsyncClient; +import org.jclouds.joyent.sdc.v6_5.features.DatacenterClient; +import org.jclouds.joyent.sdc.v6_5.handlers.SDCErrorHandler; +import org.jclouds.json.config.GsonModule.DateAdapter; +import org.jclouds.json.config.GsonModule.Iso8601DateAdapter; +import org.jclouds.rest.ConfiguresRestClient; +import org.jclouds.rest.config.RestClientModule; + +import com.google.common.collect.ImmutableMap; + +/** + * Configures the SDC connection. + * + * @author Adrian Cole + */ +@ConfiguresRestClient +public class SDCRestClientModule extends RestClientModule { + public static final Map, Class> DELEGATE_MAP = ImmutableMap., Class> builder() + .put(DatacenterClient.class, DatacenterAsyncClient.class) + .build(); + + public SDCRestClientModule() { + super(DELEGATE_MAP); + } + + @Override + protected void configure() { + bind(DateAdapter.class).to(Iso8601DateAdapter.class); + super.configure(); + } + + @Override + protected void bindErrorHandlers() { + bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(SDCErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(SDCErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(SDCErrorHandler.class); + } +} diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/DatacenterAsyncClient.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/DatacenterAsyncClient.java new file mode 100644 index 0000000000..0c549137eb --- /dev/null +++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/DatacenterAsyncClient.java @@ -0,0 +1,58 @@ +/** + * 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.joyent.sdc.v6_5.features; + +import java.net.URI; +import java.util.Map; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.core.MediaType; + +import org.jclouds.http.filters.BasicAuthentication; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.Headers; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SkipEncoding; +import org.jclouds.rest.functions.ReturnEmptyMapOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Datacenter Services + * + * @see DatacenterClient + * @author Adrian Cole + * @see api doc + */ +@SkipEncoding( { '/', '=' }) +@Headers(keys="X-Api-Version", values="{jclouds.api-version}") +@RequestFilters(BasicAuthentication.class) +public interface DatacenterAsyncClient { + + /** + * @see DatacenterClient#getDatacenters + */ + @GET + @Path("/my/datacenters") + @Consumes(MediaType.APPLICATION_JSON) + @ExceptionParser(ReturnEmptyMapOnNotFoundOr404.class) + ListenableFuture> getDatacenters(); +} diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/DatacenterClient.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/DatacenterClient.java new file mode 100644 index 0000000000..c0224194c7 --- /dev/null +++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/features/DatacenterClient.java @@ -0,0 +1,43 @@ +/** + * 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.joyent.sdc.v6_5.features; + +import java.net.URI; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; + +/** + * Datacenter Services + * + * @see DatacenterAsyncClient + * @author Adrian Cole + * @see api doc + */ +@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) +public interface DatacenterClient { + + /** + * Provides a list of all datacenters this cloud is aware of. + * + * @return keys are the datacenter name, and the value is the URL. + */ + Map getDatacenters(); +} diff --git a/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/handlers/SDCErrorHandler.java b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/handlers/SDCErrorHandler.java new file mode 100644 index 0000000000..856ee47b45 --- /dev/null +++ b/labs/joyent-sdc/src/main/java/org/jclouds/joyent/sdc/v6_5/handlers/SDCErrorHandler.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.joyent.sdc.v6_5.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 Adrian Cole + * + */ +// TODO: is there error spec someplace? let's type errors, etc. +@Singleton +public class SDCErrorHandler 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/joyent-sdc/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata b/labs/joyent-sdc/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata new file mode 100644 index 0000000000..88003aa840 --- /dev/null +++ b/labs/joyent-sdc/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata @@ -0,0 +1 @@ +org.jclouds.joyent.sdc.v6_5.SDCApiMetadata diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/SDCApiMetadataTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/SDCApiMetadataTest.java new file mode 100644 index 0000000000..c78131f27f --- /dev/null +++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/SDCApiMetadataTest.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.joyent.sdc.v6_5; + +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 Adrian Cole + */ +@Test(groups = "unit", testName = "SDCApiMetadataTest") +public class SDCApiMetadataTest extends BaseApiMetadataTest { + public SDCApiMetadataTest() { + super(new SDCApiMetadata(), ImmutableSet.> of()); + } +} diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/DatacenterClientExpectTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/DatacenterClientExpectTest.java new file mode 100644 index 0000000000..fd4711e884 --- /dev/null +++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/DatacenterClientExpectTest.java @@ -0,0 +1,70 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unles 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 expres or implied. See the License for the + * specific language governing permisions and limitations + * under the License. + */ +package org.jclouds.joyent.sdc.v6_5.features; + +import static org.testng.Assert.assertEquals; + +import java.net.URI; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.joyent.sdc.v6_5.SDCClient; +import org.jclouds.joyent.sdc.v6_5.internal.BaseSDCClientExpectTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; + +/** + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "DatacenterClientExpectTest") +public class DatacenterClientExpectTest extends BaseSDCClientExpectTest { + HttpRequest getDatacenters = HttpRequest.builder() + .method("GET") + .endpoint(URI.create("https://api.joyentcloud.com/my/datacenters")) + .headers(ImmutableMultimap. builder() + .put("X-Api-Version", "~6.5") + .put("Accept", "application/json") + .put("Authorization", "Basic aWRlbnRpdHk6Y3JlZGVudGlhbA==").build()) + .build(); + + public void testGetDatacentersWhenResponseIs2xx() { + HttpResponse getDatacentersResponse = HttpResponse.builder() + .statusCode(200) + .payload(payloadFromResource("/datacenters.json")).build(); + + SDCClient clientWhenDatacentersExists = requestSendsResponse(getDatacenters, getDatacentersResponse); + + assertEquals(clientWhenDatacentersExists.getDatacenterClient().getDatacenters(), + ImmutableMap. builder() + .put("us-east-1", URI.create("https://us-east-1.api.joyentcloud.com")) + .put("us-west-1", URI.create("https://us-west-1.api.joyentcloud.com")) + .put("us-sw-1", URI.create("https://us-sw-1.api.joyentcloud.com")) + .put("eu-ams-1", URI.create("https://eu-ams-1.api.joyentcloud.com")).build()); + } + + public void testGetDatacentersWhenResponseIs404() { + HttpResponse getDatacentersResponse = HttpResponse.builder().statusCode(404).build(); + + SDCClient getDatacentersWhenNone = requestSendsResponse(getDatacenters, getDatacentersResponse); + + assertEquals(getDatacentersWhenNone.getDatacenterClient().getDatacenters(), ImmutableMap.of()); + } +} diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/DatacenterClientLiveTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/DatacenterClientLiveTest.java new file mode 100644 index 0000000000..7d14711b3b --- /dev/null +++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/features/DatacenterClientLiveTest.java @@ -0,0 +1,41 @@ +/** + * 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.joyent.sdc.v6_5.features; + +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +import java.net.URI; +import java.util.Map; + +import org.jclouds.joyent.sdc.v6_5.internal.BaseSDCClientLiveTest; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = "live", testName = "DatacenterClientLiveTest") +public class DatacenterClientLiveTest extends BaseSDCClientLiveTest { + + public void testGetDatacenters(){ + Map dcs = sdcContext.getApi().getDatacenterClient().getDatacenters(); + assertNotNull(dcs); + assertTrue(dcs.size() > 0); + } +} diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/handlers/SDCErrorHandlerTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/handlers/SDCErrorHandlerTest.java new file mode 100644 index 0000000000..8d5db2ad6a --- /dev/null +++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/handlers/SDCErrorHandlerTest.java @@ -0,0 +1,91 @@ +/** + * 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.joyent.sdc.v6_5.handlers; + +import static org.easymock.EasyMock.createMockBuilder; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.reportMatcher; +import static org.easymock.EasyMock.verify; + +import java.net.URI; + +import org.easymock.IArgumentMatcher; +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.io.Payloads; +import org.jclouds.util.Strings2; +import org.testng.annotations.Test; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "SDCErrorHandlerTest") +public class SDCErrorHandlerTest { + + + private void assertCodeMakes(String method, URI uri, int statusCode, String message, String content, + Class expected) { + assertCodeMakes(method, uri, statusCode, message, "text/plain", content, expected); + } + + private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType, + String content, Class expected) { + + SDCErrorHandler function = new SDCErrorHandler(); + + HttpCommand command = createMockBuilder(HttpCommand.class).createMock(); + HttpRequest request = new HttpRequest(method, uri); + HttpResponse response = new HttpResponse(statusCode, message, Payloads.newInputStreamPayload(Strings2 + .toInputStream(content))); + response.getPayload().getContentMetadata().setContentType(contentType); + + expect(command.getCurrentRequest()).andReturn(request).atLeastOnce(); + command.setException(classEq(expected)); + + replay(command); + + function.handleError(command, response); + + verify(command); + } + + public static Exception classEq(final Class in) { + reportMatcher(new IArgumentMatcher() { + + @Override + public void appendTo(StringBuffer buffer) { + buffer.append("classEq("); + buffer.append(in); + buffer.append(")"); + } + + @Override + public boolean matches(Object arg) { + return arg.getClass() == in; + } + + }); + return null; + } + + +} diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/internal/BaseSDCAsyncClientExpectTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/internal/BaseSDCAsyncClientExpectTest.java new file mode 100644 index 0000000000..2c8436dad3 --- /dev/null +++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/internal/BaseSDCAsyncClientExpectTest.java @@ -0,0 +1,39 @@ +/** + * 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.joyent.sdc.v6_5.internal; + +import java.util.Properties; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.joyent.sdc.v6_5.SDCAsyncClient; + +import com.google.common.base.Function; +import com.google.inject.Module; + +/** + * Base class for writing KeyStone Rest Client Expect tests + * + * @author Adrian Cole + */ +public class BaseSDCAsyncClientExpectTest extends BaseSDCExpectTest { + public SDCAsyncClient createClient(Function fn, Module module, Properties props) { + return createInjector(fn, module, props).getInstance(SDCAsyncClient.class); + } +} diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/internal/BaseSDCClientExpectTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/internal/BaseSDCClientExpectTest.java new file mode 100644 index 0000000000..cd342cee76 --- /dev/null +++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/internal/BaseSDCClientExpectTest.java @@ -0,0 +1,30 @@ +/** + * 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.joyent.sdc.v6_5.internal; + +import org.jclouds.joyent.sdc.v6_5.SDCClient; + +/** + * Base class for writing KeyStone Rest Client Expect tests + * + * @author Adrian Cole + */ +public class BaseSDCClientExpectTest extends BaseSDCExpectTest { + +} diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/internal/BaseSDCClientLiveTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/internal/BaseSDCClientLiveTest.java new file mode 100644 index 0000000000..39ab68f913 --- /dev/null +++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/internal/BaseSDCClientLiveTest.java @@ -0,0 +1,64 @@ +/** + * 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.joyent.sdc.v6_5.internal; + +import org.jclouds.apis.BaseContextLiveTest; +import org.jclouds.joyent.sdc.v6_5.SDCApiMetadata; +import org.jclouds.joyent.sdc.v6_5.SDCAsyncClient; +import org.jclouds.joyent.sdc.v6_5.SDCClient; +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 SDCClient} + * + * @author Adrian Cole + */ +@Test(groups = "live") +public class BaseSDCClientLiveTest extends BaseContextLiveTest> { + + public BaseSDCClientLiveTest() { + provider = "joyent-sdc"; + } + + protected RestContext sdcContext; + + @BeforeGroups(groups = { "integration", "live" }) + @Override + public void setupContext() { + super.setupContext(); + sdcContext = context; + } + + @AfterGroups(groups = "live") + protected void tearDown() { + if (sdcContext != null) + sdcContext.close(); + } + + @Override + protected TypeToken> contextType() { + return SDCApiMetadata.CONTEXT_TOKEN; + } + +} diff --git a/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/internal/BaseSDCExpectTest.java b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/internal/BaseSDCExpectTest.java new file mode 100644 index 0000000000..095b171888 --- /dev/null +++ b/labs/joyent-sdc/src/test/java/org/jclouds/joyent/sdc/v6_5/internal/BaseSDCExpectTest.java @@ -0,0 +1,33 @@ +/** + * 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.joyent.sdc.v6_5.internal; + +import org.jclouds.rest.internal.BaseRestClientExpectTest; + +/** + * Base class for writing SDC Expect tests + * + * @author Adrian Cole + */ +public class BaseSDCExpectTest extends BaseRestClientExpectTest { + + public BaseSDCExpectTest() { + provider = "joyent-sdc"; + } +} diff --git a/labs/joyent-sdc/src/test/resources/datacenters.json b/labs/joyent-sdc/src/test/resources/datacenters.json new file mode 100644 index 0000000000..7f4cdc3783 --- /dev/null +++ b/labs/joyent-sdc/src/test/resources/datacenters.json @@ -0,0 +1 @@ +{"us-east-1":"https://us-east-1.api.joyentcloud.com","us-west-1":"https://us-west-1.api.joyentcloud.com","us-sw-1":"https://us-sw-1.api.joyentcloud.com","eu-ams-1":"https://eu-ams-1.api.joyentcloud.com"} \ No newline at end of file diff --git a/labs/joyent-sdc/src/test/resources/logback.xml b/labs/joyent-sdc/src/test/resources/logback.xml new file mode 100644 index 0000000000..b77c1b041f --- /dev/null +++ b/labs/joyent-sdc/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-compute.log + + + %d %-5p [%c] [%thread] %m%n + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/labs/openstack-glance/pom.xml b/labs/openstack-glance/pom.xml new file mode 100644 index 0000000000..2d3beff43c --- /dev/null +++ b/labs/openstack-glance/pom.xml @@ -0,0 +1,139 @@ + + + + 4.0.0 + + org.jclouds + jclouds-project + 1.5.0-SNAPSHOT + ../../project/pom.xml + + org.jclouds.labs + openstack-glance + jcloud openstack-glance api + jclouds components to access an implementation of OpenStack Glance + 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-glance.endpoint} + ${test.openstack-glance.api-version} + ${test.openstack-glance.build-version} + ${test.openstack-glance.identity} + ${test.openstack-glance.credential} + ${test.jclouds.keystone.credential-type} + + + + + + + + + + + + + + org.apache.felix + maven-bundle-plugin + + + ${project.artifactId} + org.jclouds.openstack.glance.v1_0*;version="${project.version}" + + org.jclouds.rest.internal;version="${project.version}", + org.jclouds*;version="${project.version}", + * + + + + + + + + diff --git a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/GlanceApiMetadata.java b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/GlanceApiMetadata.java new file mode 100644 index 0000000000..cdb817696f --- /dev/null +++ b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/GlanceApiMetadata.java @@ -0,0 +1,100 @@ +/** + * 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.glance.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.glance.v1_0.config.GlanceRestClientModule; +import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties; +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 Glance 1.0 API + * + * @author Adrian Cole + */ +public class GlanceApiMetadata extends BaseRestApiMetadata { + + /** The serialVersionUID */ + private static final long serialVersionUID = 6725672099385580694L; + + public static final TypeToken> CONTEXT_TOKEN = new TypeToken>() { + private static final long serialVersionUID = -5070937833892503232L; + }; + + @Override + public Builder toBuilder() { + return new Builder().fromApiMetadata(this); + } + + public GlanceApiMetadata() { + this(new Builder()); + } + + protected GlanceApiMetadata(Builder builder) { + super(builder); + } + + public static Properties defaultProperties() { + Properties properties = BaseRestApiMetadata.defaultProperties(); + properties.setProperty(SERVICE_TYPE, ServiceType.IMAGE); + // 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(GlanceClient.class, GlanceAsyncClient.class); + id("openstack-glance") + .name("OpenStack Glance API") + .identityName("tenantId:user") + .credentialName("password") + .documentation(URI.create("http://glance.openstack.org/glanceapi.html")) + .version("1.0") + .defaultEndpoint("http://localhost:5000") + .defaultProperties(GlanceApiMetadata.defaultProperties()) + .defaultModules(ImmutableSet.>of(GlanceRestClientModule.class)); + } + + @Override + public GlanceApiMetadata build() { + return new GlanceApiMetadata(this); + } + + @Override + public Builder fromApiMetadata(ApiMetadata in) { + super.fromApiMetadata(in); + return this; + } + + } + +} diff --git a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/GlanceAsyncClient.java b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/GlanceAsyncClient.java new file mode 100644 index 0000000000..c2d80c5892 --- /dev/null +++ b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/GlanceAsyncClient.java @@ -0,0 +1,55 @@ +/** + * 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.glance.v1_0; + +import java.util.Set; + +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.location.Region; +import org.jclouds.location.functions.RegionToEndpoint; +import org.jclouds.openstack.glance.v1_0.features.ImageAsyncClient; +import org.jclouds.rest.annotations.Delegate; +import org.jclouds.rest.annotations.EndpointParam; + +import com.google.inject.Provides; + +/** + * Provides asynchronous access to Glance via their REST API. + *

+ * + * @see GlanceClient + * @see api doc + * @author Adrian Cole + */ +public interface GlanceAsyncClient { + /** + * + * @return the Region codes configured + */ + @Provides + @Region + Set getConfiguredRegions(); + + /** + * Provides asynchronous access to Image features. + */ + @Delegate + ImageAsyncClient getImageClientForRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region); + +} diff --git a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/GlanceClient.java b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/GlanceClient.java new file mode 100644 index 0000000000..46c745e8a5 --- /dev/null +++ b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/GlanceClient.java @@ -0,0 +1,58 @@ +/** + * 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.glance.v1_0; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +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.glance.v1_0.features.ImageClient; +import org.jclouds.rest.annotations.Delegate; +import org.jclouds.rest.annotations.EndpointParam; + +import com.google.inject.Provides; + +/** + * Provides synchronous access to Glance. + *

+ * + * @see GlanceAsyncClient + * @see api doc + * @author Adrian Cole + */ +@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS) +public interface GlanceClient { + /** + * + * @return the Region codes configured + */ + @Provides + @Region + Set getConfiguredRegions(); + + /** + * Provides synchronous access to Image features. + */ + @Delegate + ImageClient getImageClientForRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region); + +} diff --git a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/config/GlanceProperties.java b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/config/GlanceProperties.java new file mode 100644 index 0000000000..51861dfd88 --- /dev/null +++ b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/config/GlanceProperties.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.glance.v1_0.config; + +/** + * Configuration properties and constants used in openstack Glance connections. + * + * @author Adrian Cole + */ +public class GlanceProperties { + +} diff --git a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/config/GlanceRestClientModule.java b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/config/GlanceRestClientModule.java new file mode 100644 index 0000000000..88fc8067f1 --- /dev/null +++ b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/config/GlanceRestClientModule.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.glance.v1_0.config; + +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.glance.v1_0.GlanceAsyncClient; +import org.jclouds.openstack.glance.v1_0.GlanceClient; +import org.jclouds.openstack.glance.v1_0.handlers.GlanceErrorHandler; +import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule; +import org.jclouds.rest.ConfiguresRestClient; +import org.jclouds.rest.config.RestClientModule; + +/** + * Configures the Glance connection. + * + * @author Adrian Cole + */ +@ConfiguresRestClient +public class GlanceRestClientModule extends RestClientModule { + + @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(GlanceErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(GlanceErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(GlanceErrorHandler.class); + } +} diff --git a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/features/ImageAsyncClient.java b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/features/ImageAsyncClient.java new file mode 100644 index 0000000000..09879510f6 --- /dev/null +++ b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/features/ImageAsyncClient.java @@ -0,0 +1,36 @@ +/** + * 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.glance.v1_0.features; + +import org.jclouds.openstack.filters.AuthenticateRequest; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SkipEncoding; + +/** + * Image Services + * + * @see ImageClient + * @author Adrian Cole + * @see api doc + */ +@SkipEncoding( { '/', '=' }) +@RequestFilters(AuthenticateRequest.class) +public interface ImageAsyncClient { + +} diff --git a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/features/ImageClient.java b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/features/ImageClient.java new file mode 100644 index 0000000000..a99d41282b --- /dev/null +++ b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/features/ImageClient.java @@ -0,0 +1,35 @@ +/** + * 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.glance.v1_0.features; + +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; + +/** + * Image Services + * + * @see ImageAsyncClient + * @author Adrian Cole + * @see api doc + */ +@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS) +public interface ImageClient { + +} diff --git a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/handlers/GlanceErrorHandler.java b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/handlers/GlanceErrorHandler.java new file mode 100644 index 0000000000..f16cd66b1f --- /dev/null +++ b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/handlers/GlanceErrorHandler.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.glance.v1_0.handlers; + +import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +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 Adrian Cole + * + */ +// TODO: is there error spec someplace? let's type errors, etc. +@Singleton +public class GlanceErrorHandler 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-glance/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata b/labs/openstack-glance/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata new file mode 100644 index 0000000000..c0103666b5 --- /dev/null +++ b/labs/openstack-glance/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata @@ -0,0 +1 @@ +org.jclouds.openstack.glance.v1_0.GlanceApiMetadata diff --git a/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/GlanceApiMetadataTest.java b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/GlanceApiMetadataTest.java new file mode 100644 index 0000000000..cddcde9557 --- /dev/null +++ b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/GlanceApiMetadataTest.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.glance.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 Adrian Cole + */ +@Test(groups = "unit", testName = "GlanceApiMetadataTest") +public class GlanceApiMetadataTest extends BaseApiMetadataTest { + public GlanceApiMetadataTest() { + super(new GlanceApiMetadata(), ImmutableSet.> of()); + } +} diff --git a/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/features/ImageClientExpectTest.java b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/features/ImageClientExpectTest.java new file mode 100644 index 0000000000..9f165e7995 --- /dev/null +++ b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/features/ImageClientExpectTest.java @@ -0,0 +1,30 @@ +/** + * 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 + * + * Unles 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 expres or implied. See the License for the + * specific language governing permisions and limitations + * under the License. + */ +package org.jclouds.openstack.glance.v1_0.features; + +import org.jclouds.openstack.glance.v1_0.internal.BaseGlanceClientExpectTest; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "ImageClientExpectTest") +public class ImageClientExpectTest extends BaseGlanceClientExpectTest { + +} diff --git a/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/features/ImageClientLiveTest.java b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/features/ImageClientLiveTest.java new file mode 100644 index 0000000000..d4f88f3acb --- /dev/null +++ b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/features/ImageClientLiveTest.java @@ -0,0 +1,30 @@ +/** + * 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.glance.v1_0.features; + +import org.jclouds.openstack.glance.v1_0.internal.BaseGlanceClientLiveTest; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = "live", testName = "ImageClientLiveTest") +public class ImageClientLiveTest extends BaseGlanceClientLiveTest { + +} diff --git a/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/handlers/GlanceErrorHandlerTest.java b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/handlers/GlanceErrorHandlerTest.java new file mode 100644 index 0000000000..9e92847304 --- /dev/null +++ b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/handlers/GlanceErrorHandlerTest.java @@ -0,0 +1,91 @@ +/** + * 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.glance.v1_0.handlers; + +import static org.easymock.EasyMock.createMockBuilder; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.reportMatcher; +import static org.easymock.EasyMock.verify; + +import java.net.URI; + +import org.easymock.IArgumentMatcher; +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.io.Payloads; +import org.jclouds.util.Strings2; +import org.testng.annotations.Test; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "GlanceErrorHandlerTest") +public class GlanceErrorHandlerTest { + + + private void assertCodeMakes(String method, URI uri, int statusCode, String message, String content, + Class expected) { + assertCodeMakes(method, uri, statusCode, message, "text/plain", content, expected); + } + + private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType, + String content, Class expected) { + + GlanceErrorHandler function = new GlanceErrorHandler(); + + HttpCommand command = createMockBuilder(HttpCommand.class).createMock(); + HttpRequest request = new HttpRequest(method, uri); + HttpResponse response = new HttpResponse(statusCode, message, Payloads.newInputStreamPayload(Strings2 + .toInputStream(content))); + response.getPayload().getContentMetadata().setContentType(contentType); + + expect(command.getCurrentRequest()).andReturn(request).atLeastOnce(); + command.setException(classEq(expected)); + + replay(command); + + function.handleError(command, response); + + verify(command); + } + + public static Exception classEq(final Class in) { + reportMatcher(new IArgumentMatcher() { + + @Override + public void appendTo(StringBuffer buffer) { + buffer.append("classEq("); + buffer.append(in); + buffer.append(")"); + } + + @Override + public boolean matches(Object arg) { + return arg.getClass() == in; + } + + }); + return null; + } + + +} diff --git a/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/internal/BaseGlanceAsyncClientExpectTest.java b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/internal/BaseGlanceAsyncClientExpectTest.java new file mode 100644 index 0000000000..92d4bfab1f --- /dev/null +++ b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/internal/BaseGlanceAsyncClientExpectTest.java @@ -0,0 +1,39 @@ +/** + * 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.glance.v1_0.internal; + +import java.util.Properties; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.openstack.glance.v1_0.GlanceAsyncClient; + +import com.google.common.base.Function; +import com.google.inject.Module; + +/** + * Base class for writing KeyStone Rest Client Expect tests + * + * @author Adrian Cole + */ +public class BaseGlanceAsyncClientExpectTest extends BaseGlanceExpectTest { + public GlanceAsyncClient createClient(Function fn, Module module, Properties props) { + return createInjector(fn, module, props).getInstance(GlanceAsyncClient.class); + } +} diff --git a/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/internal/BaseGlanceClientExpectTest.java b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/internal/BaseGlanceClientExpectTest.java new file mode 100644 index 0000000000..bd5b327b58 --- /dev/null +++ b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/internal/BaseGlanceClientExpectTest.java @@ -0,0 +1,30 @@ +/** + * 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.glance.v1_0.internal; + +import org.jclouds.openstack.glance.v1_0.GlanceClient; + +/** + * Base class for writing KeyStone Rest Client Expect tests + * + * @author Adrian Cole + */ +public class BaseGlanceClientExpectTest extends BaseGlanceExpectTest { + +} diff --git a/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/internal/BaseGlanceClientLiveTest.java b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/internal/BaseGlanceClientLiveTest.java new file mode 100644 index 0000000000..b86d5cecb3 --- /dev/null +++ b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/internal/BaseGlanceClientLiveTest.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.glance.v1_0.internal; + +import java.util.Properties; + +import org.jclouds.apis.BaseContextLiveTest; +import org.jclouds.openstack.glance.v1_0.GlanceApiMetadata; +import org.jclouds.openstack.glance.v1_0.GlanceAsyncClient; +import org.jclouds.openstack.glance.v1_0.GlanceClient; +import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties; +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 GlanceClient} + * + * @author Adrian Cole + */ +@Test(groups = "live") +public class BaseGlanceClientLiveTest extends BaseContextLiveTest> { + + public BaseGlanceClientLiveTest() { + provider = "openstack-glance"; + } + + protected RestContext glanceContext; + + @BeforeGroups(groups = { "integration", "live" }) + @Override + public void setupContext() { + super.setupContext(); + glanceContext = context; + } + + @Override + protected Properties setupProperties() { + Properties props = super.setupProperties(); + setIfTestSystemPropertyPresent(props, KeystoneProperties.CREDENTIAL_TYPE); + return props; + } + + @AfterGroups(groups = "live") + protected void tearDown() { + if (glanceContext != null) + glanceContext.close(); + } + + @Override + protected TypeToken> contextType() { + return GlanceApiMetadata.CONTEXT_TOKEN; + } + +} diff --git a/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/internal/BaseGlanceExpectTest.java b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/internal/BaseGlanceExpectTest.java new file mode 100644 index 0000000000..2e93c84ba5 --- /dev/null +++ b/labs/openstack-glance/src/test/java/org/jclouds/openstack/glance/v1_0/internal/BaseGlanceExpectTest.java @@ -0,0 +1,52 @@ +/** + * 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.glance.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 Glance Expect tests + * + * @author Adrian Cole + */ +public class BaseGlanceExpectTest extends BaseRestClientExpectTest { + protected HttpRequest keystoneAuthWithUsernameAndPassword; + protected HttpRequest keystoneAuthWithAccessKeyAndSecretKey; + protected String authToken; + protected HttpResponse responseWithKeystoneAccess; + protected HttpRequest extensionsOfGlanceRequest; + protected HttpResponse extensionsOfGlanceResponse; + protected HttpResponse unmatchedExtensionsOfGlanceResponse; + + public BaseGlanceExpectTest() { + provider = "openstack-glance"; + 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-glance/src/test/resources/logback.xml b/labs/openstack-glance/src/test/resources/logback.xml new file mode 100644 index 0000000000..bd89efb8c0 --- /dev/null +++ b/labs/openstack-glance/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-keystone/pom.xml b/labs/openstack-keystone/pom.xml new file mode 100644 index 0000000000..57fd0b756c --- /dev/null +++ b/labs/openstack-keystone/pom.xml @@ -0,0 +1,134 @@ + + + + 4.0.0 + + org.jclouds + jclouds-project + 1.5.0-SNAPSHOT + ../../project/pom.xml + + org.jclouds.labs + openstack-keystone + jcloud openstack-keystone api + jclouds components to access an implementation of OpenStack Keystone + bundle + + + + http://localhost:5000 + + 2.0 + + FIXME_IDENTITY + FIXME_CREDENTIALS + passwordCredentials + + + + + org.jclouds.common + openstack-common + ${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-keystone.endpoint} + ${test.openstack-keystone.api-version} + ${test.openstack-keystone.build-version} + ${test.openstack-keystone.identity} + ${test.openstack-keystone.credential} + ${test.jclouds.keystone.credential-type} + + + + + + + + + + + + + + org.apache.felix + maven-bundle-plugin + + + ${project.artifactId} + org.jclouds.openstack.keystone.v2_0*;version="${project.version}" + + org.jclouds.rest.internal;version="${project.version}", + org.jclouds*;version="${project.version}", + * + + + + + + + + diff --git a/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AdminAsyncClient.java b/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AdminAsyncClient.java new file mode 100644 index 0000000000..fa58e3b901 --- /dev/null +++ b/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AdminAsyncClient.java @@ -0,0 +1,177 @@ +/** + * 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.keystone.v2_0; + +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.HEAD; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; + +import org.jclouds.openstack.filters.AuthenticateRequest; +import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata; +import org.jclouds.openstack.keystone.v2_0.domain.Endpoint; +import org.jclouds.openstack.keystone.v2_0.domain.Role; +import org.jclouds.openstack.keystone.v2_0.domain.Tenant; +import org.jclouds.openstack.keystone.v2_0.domain.Token; +import org.jclouds.openstack.keystone.v2_0.domain.User; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SelectJson; +import org.jclouds.rest.annotations.SkipEncoding; +import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides asynchronous access to Admin via their REST API. + *

+ * + * @see AdminClient + * @see + * @author Adam Lowe + */ +@SkipEncoding({ '/', '=' }) +public interface AdminAsyncClient { + /** + * @see AdminClient#getApiMetadata() + */ + @GET + @SelectJson("version") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/") + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getApiMetadata(); + + /** + * @see AdminClient#listTenants() + */ + @GET + @SelectJson("tenants") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/tenants") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listTenants(); + + /** @see AdminClient#getToken(String) */ + @GET + @SelectJson("token") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/tokens/{token}") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getToken(@PathParam("token") String token); + + /** @see AdminClient#getUserOfToken(String) */ + @GET + @SelectJson("user") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/tokens/{token}") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getUserOfToken(@PathParam("token") String token); + + /** @see AdminClient#checkTokenIsValid(String) */ + @HEAD + @Path("/tokens/{token}") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnFalseOnNotFoundOr404.class) + ListenableFuture checkTokenIsValid(@PathParam("token") String token); + + /** @see AdminClient#getEndpointsForToken(String) */ + @GET + @SelectJson("endpoints") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/tokens/{token}/endpoints") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> getEndpointsForToken(@PathParam("token") String token); + + /** @see AdminClient#getTenant(String) */ + @GET + @SelectJson("tenant") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/tenants/{tenantId}") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getTenant(@PathParam("tenantId") String tenantId); + + /** @see AdminClient#getTenantByName(String) */ + @GET + @SelectJson("tenant") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/tenants") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getTenantByName(@QueryParam("name") String tenantName); + + /** @see AdminClient#listUsers() */ + @GET + @SelectJson("users") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/users") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listUsers(); + + /** @see AdminClient#getUser(String) */ + @GET + @SelectJson("user") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/users/{userId}") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getUser(@PathParam("userId") String userId); + + /** @see AdminClient#getUserByName(String) */ + @GET + @SelectJson("user") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/users") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getUserByName(@QueryParam("name") String userName); + + /** @see AdminClient#listRolesOfUser(String) */ + @GET + @SelectJson("roles") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/users/{userId}/roles") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listRolesOfUser(@PathParam("userId") String userId); + + /** @see AdminClient#listRolesOfUserOnTenant(String, String) */ + @GET + @SelectJson("roles") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/tenants/{tenantId}/users/{userId}/roles") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listRolesOfUserOnTenant(@PathParam("userId") String userId, @PathParam("tenantId") String tenantId); +} diff --git a/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AdminClient.java b/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AdminClient.java new file mode 100644 index 0000000000..def212949f --- /dev/null +++ b/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AdminClient.java @@ -0,0 +1,145 @@ +/** + * 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.keystone.v2_0; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata; +import org.jclouds.openstack.keystone.v2_0.domain.Endpoint; +import org.jclouds.openstack.keystone.v2_0.domain.Role; +import org.jclouds.openstack.keystone.v2_0.domain.Tenant; +import org.jclouds.openstack.keystone.v2_0.domain.Token; +import org.jclouds.openstack.keystone.v2_0.domain.User; + +/** + * Provides synchronous access to the KeyStone Admin API. + *

+ * + * @author Adam Lowe + * @see AdminAsyncClient + * @see + */ +@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) +public interface AdminClient { + + /** + * Discover API version information, links to documentation (PDF, HTML, WADL), and supported media types + * + * @return the requested information + */ + ApiMetadata getApiMetadata(); + + /** + * The operation returns a list of tenants which the current token provides access to. + */ + Set listTenants(); + + /** + * Retrieve information about a tenant, by tenant ID + * + * @return the information about the tenant + */ + Tenant getTenant(String tenantId); + + /** + * Retrieve information about a tenant, by tenant name + *

+ * NOTE: currently not working in openstack ( https://bugs.launchpad.net/keystone/+bug/956687 ) + * + * @return the information about the tenant + */ + Tenant getTenantByName(String tenantName); + + /** + * Validate a token and, if it is valid, return access information regarding the tenant (though not the service catalog)/ + * + * @return the requested information + */ + Token getToken(String token); + + /** + * Validate a token and, if it is valid, return access information regarding the tenant (though not the service catalog)/ + * + * @return the requested information + */ + User getUserOfToken(String token); + + /** + * Validate a token. This is a high-performance variant of the #getToken() call that does not return any further + * information. + * + * @return true if the token is valid + */ + Boolean checkTokenIsValid(String token); + + /** + * List all endpoints for a token + *

+ * NOTE: currently not working in openstack ( https://bugs.launchpad.net/keystone/+bug/988672 ) + * + * @return the set of endpoints + */ + Set getEndpointsForToken(String token); + + /** + * Retrieve the list of users + *

+ * NOTE: this method is not in API documentation for keystone, but does work + * + * @return the list of users + */ + Set listUsers(); + + /** + * Retrieve information about a user, by user ID + * + * @return the information about the user + */ + User getUser(String userId); + + /** + * Retrieve information about a user, by user name + *

+ * NOTE: currently not working in openstack ( https://bugs.launchpad.net/keystone/+bug/956687 ) + * + * @return the information about the user + */ + User getUserByName(String userName); + + /** + * Retrieves the list of global roles associated with a specific user (excludes tenant roles). + *

+ * NOTE: Broken in openstack ( https://bugs.launchpad.net/keystone/+bug/933565 ) + * + * @return the set of Roles granted to the user + */ + Set listRolesOfUser(String userId); + + /** + * List the roles a user has been granted on a specific tenant + * + * @return the set of roles + */ + Set listRolesOfUserOnTenant(String userId, String tenantId); + +} \ No newline at end of file diff --git a/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java b/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java new file mode 100644 index 0000000000..7e038f26c6 --- /dev/null +++ b/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java @@ -0,0 +1,102 @@ +/** + * 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.keystone.v2_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.keystone.v2_0.config.KeystoneRestClientModule; +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 org.jclouds.apis.ApiMetadata} for Keystone 2.0 API + * + * @author Adrian Cole + */ +public class KeystoneApiMetadata extends BaseRestApiMetadata { + + /** The serialVersionUID */ + private static final long serialVersionUID = 6725672099385580694L; + + public static final TypeToken> CONTEXT_TOKEN = new TypeToken>() { + }; + + @Override + public Builder toBuilder() { + return new Builder().fromApiMetadata(this); + } + + public KeystoneApiMetadata() { + this(new Builder()); + } + + protected KeystoneApiMetadata(Builder builder) { + super(builder); + } + + public static Properties defaultProperties() { + Properties properties = BaseRestApiMetadata.defaultProperties(); + // auth fail can happen while cloud-init applies keypair updates + properties.setProperty("jclouds.ssh.max-retries", "7"); + properties.setProperty("jclouds.ssh.retry-auth", "true"); + // TODO: this doesn't actually do anything yet. + properties.setProperty(KeystoneProperties.VERSION, "2.0"); + properties.put(SERVICE_TYPE, ServiceType.IDENTITY); + return properties; + } + + public static class Builder extends BaseRestApiMetadata.Builder { + + protected Builder() { + super(KeystoneClient.class, KeystoneAsyncClient.class); + id("openstack-keystone") + .name("OpenStack Keystone Essex+ API") + .identityName("tenantId:user") + .credentialName("password") + .documentation(URI.create("http://api.openstack.org/")) + .version("2.0") + .defaultEndpoint("http://localhost:5000") + .defaultProperties(KeystoneApiMetadata.defaultProperties()) + .defaultModules(ImmutableSet.>of(KeystoneRestClientModule.class)); + } + + @Override + public KeystoneApiMetadata build() { + return new KeystoneApiMetadata(this); + } + + @Override + public Builder fromApiMetadata(ApiMetadata in) { + super.fromApiMetadata(in); + return this; + } + + } + +} \ No newline at end of file diff --git a/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneAsyncClient.java b/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneAsyncClient.java new file mode 100644 index 0000000000..cb88070c2f --- /dev/null +++ b/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneAsyncClient.java @@ -0,0 +1,59 @@ +/** + * 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.keystone.v2_0; + +import java.util.Set; + +import javax.ws.rs.Path; + +import org.jclouds.Constants; +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.location.Region; +import org.jclouds.location.functions.RegionToEndpoint; +import org.jclouds.openstack.keystone.v2_0.functions.RegionToAdminEndpointURI; +import org.jclouds.rest.annotations.Delegate; +import org.jclouds.rest.annotations.EndpointParam; + +import com.google.inject.Provides; + +/** + * Provides access to Openstack keystone resources via their REST API. + *

+ * + * @author Adam Lowe + * @see + * @see KeystoneClient + */ +@Path("/v{" + Constants.PROPERTY_API_VERSION + "}") +public interface KeystoneAsyncClient { + /** + * @return the Region codes configured + */ + @Provides + @Region + Set getConfiguredRegions(); + + /** Provides asynchronous access to Identity user-accessible features */ + @Delegate + ServiceAsyncClient getServiceClientForRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region); + + /** Provides asynchronous access to the KeyStone Admin API */ + @Delegate + AdminAsyncClient getAdminClientForRegion(@EndpointParam(parser = RegionToAdminEndpointURI.class) @Nullable String region); +} diff --git a/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneClient.java b/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneClient.java new file mode 100644 index 0000000000..2c63a5b074 --- /dev/null +++ b/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneClient.java @@ -0,0 +1,58 @@ +/** + * 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.keystone.v2_0; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +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.keystone.v2_0.functions.RegionToAdminEndpointURI; +import org.jclouds.rest.annotations.Delegate; +import org.jclouds.rest.annotations.EndpointParam; + +import com.google.inject.Provides; + +/** + * Provides access to Openstack keystone resources via their REST API. + *

+ * + * @author Adam Lowe + * @see + */ +@Timeout(duration = 10, timeUnit = TimeUnit.SECONDS) +public interface KeystoneClient { + /** + * @return the Region codes configured + */ + @Provides + @Region + Set getConfiguredRegions(); + + /** Provides synchronous access to Identity user-accessible features */ + @Delegate + ServiceClient getServiceClientForRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region); + + /** Provides synchronous access to the KeyStone Admin API */ + @Delegate + AdminClient getAdminClientForRegion(@EndpointParam(parser = RegionToAdminEndpointURI.class) @Nullable String region); + +} \ No newline at end of file diff --git a/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/ServiceAsyncClient.java b/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/ServiceAsyncClient.java new file mode 100644 index 0000000000..9cc665fd91 --- /dev/null +++ b/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/ServiceAsyncClient.java @@ -0,0 +1,71 @@ +/** + * 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.keystone.v2_0; + +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.core.MediaType; + +import org.jclouds.openstack.filters.AuthenticateRequest; +import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata; +import org.jclouds.openstack.keystone.v2_0.domain.Tenant; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SelectJson; +import org.jclouds.rest.annotations.SkipEncoding; +import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides asynchronous access to Service via their REST API. + *

+ * + * @see ServiceClient + * @see + * @author Adam Lowe + */ +@SkipEncoding({ '/', '=' }) +public interface ServiceAsyncClient { + /** + * @see ServiceClient#getApiMetadata() + */ + @GET + @SelectJson("version") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/") + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getApiMetadata(); + + /** + * @see ServiceClient#listTenants() + */ + @GET + @SelectJson("tenants") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/tenants") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listTenants(); +} diff --git a/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/ServiceClient.java b/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/ServiceClient.java new file mode 100644 index 0000000000..a09a78e3eb --- /dev/null +++ b/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/ServiceClient.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.keystone.v2_0; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata; +import org.jclouds.openstack.keystone.v2_0.domain.Tenant; + +/** + * Provides synchronous access to the KeyStone Service API. + *

+ * + * @author Adam Lowe + * @see ServiceAsyncClient + * @see + */ +@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) +public interface ServiceClient { + + /** + * Discover API version information, links to documentation (PDF, HTML, WADL), and supported media types + * + * @return the requested information + */ + ApiMetadata getApiMetadata(); + + /** + * The operation returns a list of tenants which the current token provides access to. + */ + Set listTenants(); +} \ No newline at end of file diff --git a/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneParserModule.java b/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneParserModule.java new file mode 100644 index 0000000000..c808961900 --- /dev/null +++ b/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneParserModule.java @@ -0,0 +1,36 @@ +/** + * 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.keystone.v2_0.config; + +import org.jclouds.json.config.GsonModule; +import org.jclouds.json.config.GsonModule.DateAdapter; + +import com.google.inject.AbstractModule; + +/** + * @author Adam Lowe + */ +public class KeystoneParserModule extends AbstractModule { + + + @Override + protected void configure() { + bind(DateAdapter.class).to(GsonModule.Iso8601DateAdapter.class); + } +} diff --git a/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneRestClientModule.java b/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneRestClientModule.java new file mode 100644 index 0000000000..70b672c5cf --- /dev/null +++ b/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneRestClientModule.java @@ -0,0 +1,76 @@ +/** + * 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.keystone.v2_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.openstack.keystone.v2_0.AdminAsyncClient; +import org.jclouds.openstack.keystone.v2_0.AdminClient; +import org.jclouds.openstack.keystone.v2_0.KeystoneAsyncClient; +import org.jclouds.openstack.keystone.v2_0.KeystoneClient; +import org.jclouds.openstack.keystone.v2_0.ServiceAsyncClient; +import org.jclouds.openstack.keystone.v2_0.ServiceClient; +import org.jclouds.openstack.keystone.v2_0.handlers.KeystoneErrorHandler; +import org.jclouds.rest.ConfiguresRestClient; +import org.jclouds.rest.config.RestClientModule; + +import com.google.common.collect.ImmutableMap; + +/** + * Configures the Keystone connection. + * + * @author Adam Lowe + */ +@ConfiguresRestClient +public class KeystoneRestClientModule extends RestClientModule { + + public static final Map, Class> DELEGATE_MAP = ImmutableMap., Class> builder() + .put(ServiceClient.class, ServiceAsyncClient.class).put(AdminClient.class, AdminAsyncClient.class) + .build(); + + public KeystoneRestClientModule() { + super(DELEGATE_MAP); + } + + @Override + protected void configure() { + install(new KeystoneParserModule()); + 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(KeystoneErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(KeystoneErrorHandler.class); + bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(KeystoneErrorHandler.class); + } +} diff --git a/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/handlers/KeystoneErrorHandler.java b/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/handlers/KeystoneErrorHandler.java new file mode 100644 index 0000000000..007270f21a --- /dev/null +++ b/labs/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/handlers/KeystoneErrorHandler.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.keystone.v2_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 KeystoneErrorHandler 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-keystone/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata b/labs/openstack-keystone/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata new file mode 100644 index 0000000000..72609ba3b7 --- /dev/null +++ b/labs/openstack-keystone/src/main/resources/META-INF/services/org.jclouds.apis.ApiMetadata @@ -0,0 +1 @@ +org.jclouds.openstack.keystone.v2_0.KeystoneApiMetadata diff --git a/labs/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/AdminClientExpectTest.java b/labs/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/AdminClientExpectTest.java new file mode 100644 index 0000000000..87cd71cd47 --- /dev/null +++ b/labs/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/AdminClientExpectTest.java @@ -0,0 +1,379 @@ +/** + * 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.keystone.v2_0; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; + +import java.net.URI; +import java.util.Set; + +import org.jclouds.date.DateService; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.http.HttpResponseException; +import org.jclouds.openstack.domain.Link; +import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata; +import org.jclouds.openstack.keystone.v2_0.domain.Endpoint; +import org.jclouds.openstack.keystone.v2_0.domain.MediaType; +import org.jclouds.openstack.keystone.v2_0.domain.Role; +import org.jclouds.openstack.keystone.v2_0.domain.Tenant; +import org.jclouds.openstack.keystone.v2_0.domain.Token; +import org.jclouds.openstack.keystone.v2_0.domain.User; +import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneRestClientExpectTest; +import org.jclouds.rest.AuthorizationException; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; + +/** + * Tests parsing and Guice wiring of UserClient + * + * @author Adam Lowe + */ +public class AdminClientExpectTest extends BaseKeystoneRestClientExpectTest { + private DateService dateService = new SimpleDateFormatDateService(); + + public AdminClientExpectTest() { + endpoint = "https://csnode.jclouds.org:35357"; + } + + public void testGetApiMetaData() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/"). + headers(ImmutableMultimap.of("Accept", APPLICATION_JSON)).build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/api_metadata.json", APPLICATION_JSON)).build()) + .getAdminClientForRegion("region-a.geo-1"); + ApiMetadata metadata = client.getApiMetadata(); + assertNotNull(metadata); + assertEquals(metadata.getId(), "v2.0"); + + ApiMetadata expected = ApiMetadata.builder().id("v2.0") + .links(ImmutableSet.of(Link.builder().relation(Link.Relation.SELF).href(URI.create("http://172.16.89.140:5000/v2.0/")).build(), + Link.builder().relation(Link.Relation.DESCRIBEDBY).type("text/html").href(URI.create("http://docs.openstack.org/api/openstack-identity-service/2.0/content/")).build(), + Link.builder().relation(Link.Relation.DESCRIBEDBY).type("application/pdf").href(URI.create("http://docs.openstack.org/api/openstack-identity-service/2.0/identity-dev-guide-2.0.pdf")).build() + )) + .status("beta") + .updated(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-11-19T00:00:00Z")) + .mediaTypes(ImmutableSet.of( + MediaType.builder().base("application/json").type("application/vnd.openstack.identity-v2.0+json").build(), + MediaType.builder().base("application/xml").type("application/vnd.openstack.identity-v2.0+xml").build() + )) + .build(); + + assertEquals(metadata, expected); + } + + public void testGetApiMetaDataFailNotFound() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/").headers(ImmutableMultimap.of("Accept", APPLICATION_JSON)).build(), + standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1"); + assertNull(client.getApiMetadata()); + } + + public void testListTenants() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tenants").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/tenant_list.json", APPLICATION_JSON)).build()) + .getAdminClientForRegion("region-a.geo-1"); + Set tenants = client.listTenants(); + assertNotNull(tenants); + assertFalse(tenants.isEmpty()); + + Set expected = ImmutableSet.of( + Tenant.builder().name("demo").id("05d1dc7af71646deba64cfc17b81bec0").build(), + Tenant.builder().name("admin").id("7aa2e17ec29f44d193c48feaba0852cc").build() + ); + + assertEquals(tenants, expected); + } + + public void testListTenantsFailNotFound() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tenants").build(), + standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1"); + assertTrue(client.listTenants().isEmpty()); + } + + public void testGetTenant() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tenants/013ba41150a14830bec85ffe93353bcc").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/tenant_details.json", APPLICATION_JSON)).build()) + .getAdminClientForRegion("region-a.geo-1"); + Tenant tenant = client.getTenant("013ba41150a14830bec85ffe93353bcc"); + assertNotNull(tenant); + assertEquals(tenant, Tenant.builder().id("013ba41150a14830bec85ffe93353bcc").name("admin").build()); + } + + @Test(expectedExceptions = AuthorizationException.class) + public void testListTenantsFailNotAuthorized() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tenants/013ba41150a14830bec85ffe93353bcc").build(), + standardResponseBuilder(401).build()).getAdminClientForRegion("region-a.geo-1"); + client.getTenant("013ba41150a14830bec85ffe93353bcc"); + } + + public void testGetTenantByName() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tenants?name=admin").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/tenant_details.json", APPLICATION_JSON)).build()) + .getAdminClientForRegion("region-a.geo-1"); + Tenant tenant = client.getTenantByName("admin"); + assertNotNull(tenant); + assertEquals(tenant, Tenant.builder().id("013ba41150a14830bec85ffe93353bcc").name("admin").build()); + } + + public void testGetTenantByNameFailNotFound() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tenants?name=admin").build(), + standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1"); + assertNull(client.getTenantByName("admin")); + } + + public void testGetToken() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/token_details.json", APPLICATION_JSON)).build()) + .getAdminClientForRegion("region-a.geo-1"); + Token token = client.getToken("sometokenorother"); + assertNotNull(token); + assertEquals(token, + Token.builder().id("167eccdc790946969ced473732e8109b").expires(dateService.iso8601SecondsDateParse("2012-04-28T12:42:50Z")) + .tenant(Tenant.builder().id("4cea93f5464b4f1c921fb3e0461d72b5").name("demo").build()).build()); + } + + public void testGetTokenFailNotFound() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").build(), + standardResponseBuilder(404).build()) + .getAdminClientForRegion("region-a.geo-1"); + assertNull(client.getToken("sometokenorother")); + } + + @Test(expectedExceptions = HttpResponseException.class) + public void testGetTokenFail500() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").build(), + standardResponseBuilder(500).build()).getAdminClientForRegion("region-a.geo-1"); + client.getToken("sometokenorother"); + } + + public void testGetUserOfToken() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/token_details.json", APPLICATION_JSON)).build()) + .getAdminClientForRegion("region-a.geo-1"); + User user = client.getUserOfToken("sometokenorother"); + assertNotNull(user); + assertEquals(user, User.builder().id("2b9b606181634ae9ac86fd95a8bc2cde").name("admin") + .roles(ImmutableSet.of(Role.builder().id("79cada5c02814b57a52e0eed4dd388cb").name("admin").build())) + .build()); + } + + public void testGetUserOfTokenFailNotFound() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").build(), + standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1"); + assertNull(client.getUserOfToken("sometokenorother")); + } + + public void testCheckTokenIsValid() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").method("HEAD") + .headers(ImmutableMultimap.of("X-Auth-Token", authToken)).build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/token_details.json", APPLICATION_JSON)).build()) + .getAdminClientForRegion("region-a.geo-1"); + assertTrue(client.checkTokenIsValid("sometokenorother")); + } + + public void testCheckTokenIsValidFailNotValid() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").method("HEAD") + .headers(ImmutableMultimap.of("X-Auth-Token", authToken)).build(), + standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1"); + assertFalse(client.checkTokenIsValid("sometokenorother")); + } + + @Test + public void testGetEndpointsForToken() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tokens/XXXXXX/endpoints").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_endpoints.json", APPLICATION_JSON)).build()) + .getAdminClientForRegion("region-a.geo-1"); + Set endpoints = client.getEndpointsForToken("XXXXXX"); + + assertEquals(endpoints, ImmutableSet.of( + Endpoint.builder().publicURL(URI.create("https://csnode.jclouds.org/v2.0/")) + .adminURL(URI.create("https://csnode.jclouds.org:35357/v2.0/")) + .region("region-a.geo-1").versionId("2.0").build() + )); + } + + @Test + public void testGetEndpointsForTokenFailNotFound() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tokens/XXXXXX/endpoints").build(), + standardResponseBuilder(404).build()) + .getAdminClientForRegion("region-a.geo-1"); + assertTrue(client.getEndpointsForToken("XXXXXX").isEmpty()); + } + + public void testListUsers() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/users").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_list.json", APPLICATION_JSON)).build()) + .getAdminClientForRegion("region-a.geo-1"); + Set users = client.listUsers(); + assertNotNull(users); + assertFalse(users.isEmpty()); + + Set expected = ImmutableSet.of( + User.builder().name("nova").id("e021dfd758eb44a89f1c57c8ef3be8e2").build(), + User.builder().name("glance").id("3f6c1c9ba993495ead7d2eb2192e284f").build(), + User.builder().name("demo").id("667b2e1420604df8b67cd8ea57d4ee64").build(), + User.builder().name("admin").id("2b9b606181634ae9ac86fd95a8bc2cde").build() + ); + + assertEquals(users, expected); + } + + @Test(expectedExceptions = AuthorizationException.class) + public void testListUsersFailNotAuth() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/users").build(), + standardResponseBuilder(401).build()).getAdminClientForRegion("region-a.geo-1"); + client.listUsers(); + } + + public void testGetUser() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/users/e021dfd758eb44a89f1c57c8ef3be8e2").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_details.json", APPLICATION_JSON)).build()) + .getAdminClientForRegion("region-a.geo-1"); + User user = client.getUser("e021dfd758eb44a89f1c57c8ef3be8e2"); + assertNotNull(user); + assertEquals(user, User.builder().name("nova").id("e021dfd758eb44a89f1c57c8ef3be8e2").build()); + } + + public void testGetUserFailNotFound() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/users/f021dfd758eb44a89f1c57c8ef3be8e2").build(), + standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1"); + assertNull(client.getUser("f021dfd758eb44a89f1c57c8ef3be8e2")); + } + + public void testGetUserByName() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/users?name=nova").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_details.json", APPLICATION_JSON)).build()) + .getAdminClientForRegion("region-a.geo-1"); + User user = client.getUserByName("nova"); + assertNotNull(user); + assertEquals(user, User.builder().name("nova").id("e021dfd758eb44a89f1c57c8ef3be8e2").build()); + } + + public void testGetUserByNameFailNotFound() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/users?name=fred").build(), + standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1"); + assertNull(client.getUserByName("fred")); + } + + public void testListRolesOfUser() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/users/3f6c1c9ba993495ead7d2eb2192e284f/roles").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_role_list.json", APPLICATION_JSON)).build()) + .getAdminClientForRegion("region-a.geo-1"); + Set roles = client.listRolesOfUser("3f6c1c9ba993495ead7d2eb2192e284f"); + assertNotNull(roles); + assertFalse(roles.isEmpty()); + assertEquals(roles, ImmutableSet.of( + Role.builder().id("79cada5c02814b57a52e0eed4dd388cb").name("admin").build() + )); + } + + public void testListRolesOfUserFailNotFound() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/users/4f6c1c9ba993495ead7d2eb2192e284f/roles").build(), + standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1"); + assertTrue(client.listRolesOfUser("4f6c1c9ba993495ead7d2eb2192e284f").isEmpty()); + } + + @Test(expectedExceptions = HttpResponseException.class) + public void testListRolesOfUserFailNotImplemented() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/users/5f6c1c9ba993495ead7d2eb2192e284f/roles").build(), + standardResponseBuilder(501).build()).getAdminClientForRegion("region-a.geo-1"); + assertTrue(client.listRolesOfUser("5f6c1c9ba993495ead7d2eb2192e284f").isEmpty()); + } + + public void testListRolesOfUserInTenant() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/users/3f6c1c9ba993495ead7d2eb2192e284f/roles").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_tenant_role_list.json", APPLICATION_JSON)).build()) + .getAdminClientForRegion("region-a.geo-1"); + Set roles = client.listRolesOfUser("3f6c1c9ba993495ead7d2eb2192e284f"); + assertNotNull(roles); + assertFalse(roles.isEmpty()); + assertEquals(roles, ImmutableSet.of( + Role.builder().id("31c451195aac49b386039341e2c92a16").name("KeystoneServiceAdmin").build(), + Role.builder().id("79cada5c02814b57a52e0eed4dd388cb").name("admin").build(), + Role.builder().id("6ea17ddd37a6447794cb0e164d4db894").name("KeystoneAdmin").build())); + } + + public void testListRolesOfUserInTenantFailNotFound() { + AdminClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/users/3f6c1c9ba993495ead7d2eb2192e284f/roles").build(), + standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1"); + assertTrue(client.listRolesOfUser("3f6c1c9ba993495ead7d2eb2192e284f").isEmpty()); + } + +} diff --git a/labs/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/AdminClientLiveTest.java b/labs/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/AdminClientLiveTest.java new file mode 100644 index 0000000000..82ab9fc504 --- /dev/null +++ b/labs/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/AdminClientLiveTest.java @@ -0,0 +1,193 @@ +/** + * 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.keystone.v2_0; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; +import static org.testng.AssertJUnit.assertTrue; + +import java.net.URI; +import java.util.Set; + +import org.jclouds.http.HttpRequest; +import org.jclouds.openstack.filters.AuthenticateRequest; +import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata; +import org.jclouds.openstack.keystone.v2_0.domain.Endpoint; +import org.jclouds.openstack.keystone.v2_0.domain.Role; +import org.jclouds.openstack.keystone.v2_0.domain.Tenant; +import org.jclouds.openstack.keystone.v2_0.domain.Token; +import org.jclouds.openstack.keystone.v2_0.domain.User; +import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneClientLiveTest; +import org.jclouds.openstack.reference.AuthHeaders; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.common.collect.Iterables; + +/** + * Tests AdminClient + * + * @author Adam Lowe + */ +@Test(groups = "live", testName = "AdminClientLiveTest", singleThreaded = true) +public class AdminClientLiveTest extends BaseKeystoneClientLiveTest { + + protected String token; + + // Get the token currently in use (there's currently no listTokens()) + @BeforeMethod + public void grabToken() { + AuthenticateRequest ar = keystoneContext.getUtils().getInjector().getInstance(AuthenticateRequest.class); + HttpRequest test = ar.filter(HttpRequest.builder().method("GET").endpoint(URI.create(endpoint)).build()); + token = Iterables.getOnlyElement(test.getHeaders().get(AuthHeaders.AUTH_TOKEN)); + } + + public void testGetApiMetaData() { + for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { + ApiMetadata result = keystoneContext.getApi().getAdminClientForRegion(regionId).getApiMetadata(); + assertNotNull(result); + assertNotNull(result.getId()); + assertNotNull(result.getStatus()); + assertNotNull(result.getUpdated()); + } + } + + public void testTenants() { + for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { + AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId); + Set result = client.listTenants(); + assertNotNull(result); + assertFalse(result.isEmpty()); + + for (Tenant tenant : result) { + assertNotNull(tenant.getId()); + + Tenant aTenant = client.getTenant(tenant.getId()); + assertEquals(aTenant, tenant); + } + } + } + + public void testToken() { + for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { + AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId); + assertTrue(client.checkTokenIsValid(token)); + Token result = client.getToken(token); + assertNotNull(result); + assertEquals(result.getId(), token); + assertNotNull(result.getTenant()); + + User user = client.getUserOfToken(token); + assertNotNull(user); + assertNotNull(user.getId()); + assertNotNull(user.getName()); + } + } + + public void testInvalidToken() { + for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { + AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId); + assertFalse(client.checkTokenIsValid("thisisnotarealtoken!")); + assertNull(client.getToken("thisisnotarealtoken!")); + } + } + + // TODO this threw 501 not implemented + @Test(enabled = false) + public void testTokenEndpoints() { + for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { + AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId); + Set endpoints = client.getEndpointsForToken(token); + assertNotNull(endpoints); + assertFalse(endpoints.isEmpty()); + } + } + + // TODO this threw 501 not implemented + @Test(enabled = false) + public void testInvalidTokenEndpoints() { + for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { + AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId); + assertTrue(client.getEndpointsForToken("thisisnotarealtoken!").isEmpty()); + } + } + + public void testUsers() { + for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { + AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId); + Set users = client.listUsers(); + assertNotNull(users); + assertFalse(users.isEmpty()); + for (User user : users) { + User aUser = client.getUser(user.getId()); + assertEquals(aUser, user); + } + } + } + + @Test(dependsOnMethods = {"testUsers", "testTenants"}) + public void testUserRolesOnTenant() { + for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { + AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId); + Set users = client.listUsers(); + Set tenants = client.listTenants(); + + for (User user : users) { + for (Tenant tenant : tenants) { + Set roles = client.listRolesOfUserOnTenant(user.getId(), tenant.getId()); + for (Role role : roles) { + assertNotNull(role.getId()); + } + } + } + } + } + + // TODO this functionality is currently broken in openstack + @Test(enabled = false, dependsOnMethods = "testUsers") + public void testListRolesOfUser() { + for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { + AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId); + for (User user : client.listUsers()) { + Set roles = client.listRolesOfUser(user.getId()); + for (Role role : roles) { + assertNotNull(role.getId()); + } + } + } + } + + // TODO this functionality is currently broken in openstack (possibly deprecated?) + @Test(enabled=false, dependsOnMethods = {"testUsers", "testTenants"}) + public void testUsersAndTenantsByName() { + for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { + AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId); + for (User user : client.listUsers()) { + User aUser = client.getUserByName(user.getName()); + assertEquals(aUser, user); + } + for (Tenant tenant : client.listTenants()) { + Tenant aTenant = client.getTenantByName(tenant.getName()); + assertEquals(aTenant, tenant); + } + } + } +} \ No newline at end of file diff --git a/labs/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/UserClientExpectTest.java b/labs/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/UserClientExpectTest.java new file mode 100644 index 0000000000..58697da9e3 --- /dev/null +++ b/labs/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/UserClientExpectTest.java @@ -0,0 +1,95 @@ +/** + * 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.keystone.v2_0; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertNotNull; + +import java.net.URI; +import java.util.Set; + +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.openstack.domain.Link; +import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata; +import org.jclouds.openstack.keystone.v2_0.domain.MediaType; +import org.jclouds.openstack.keystone.v2_0.domain.Tenant; +import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneRestClientExpectTest; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; + +/** + * Tests parsing and Guice wiring of UserClient + * + * @author Adam Lowe + */ +public class UserClientExpectTest extends BaseKeystoneRestClientExpectTest { + + public void testGetApiMetaData() { + ServiceClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + HttpRequest.builder().method("GET").endpoint(URI.create(endpoint + "/v2.0/")). + headers(ImmutableMultimap.of("Accept", APPLICATION_JSON)).build(), + HttpResponse.builder().statusCode(200). + payload(payloadFromResourceWithContentType("/api_metadata.json", APPLICATION_JSON)).build()) + .getServiceClientForRegion("region-a.geo-1"); + ApiMetadata metadata = client.getApiMetadata(); + assertNotNull(metadata); + assertEquals(metadata.getId(), "v2.0"); + + ApiMetadata expected = ApiMetadata.builder().id("v2.0") + .links(ImmutableSet.of(Link.builder().relation(Link.Relation.SELF).href(URI.create("http://172.16.89.140:5000/v2.0/")).build(), + Link.builder().relation(Link.Relation.DESCRIBEDBY).type("text/html").href(URI.create("http://docs.openstack.org/api/openstack-identity-service/2.0/content/")).build(), + Link.builder().relation(Link.Relation.DESCRIBEDBY).type("application/pdf").href(URI.create("http://docs.openstack.org/api/openstack-identity-service/2.0/identity-dev-guide-2.0.pdf")).build() + )) + .status("beta") + .updated(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-11-19T00:00:00Z")) + .mediaTypes(ImmutableSet.of( + MediaType.builder().base("application/json").type("application/vnd.openstack.identity-v2.0+json").build(), + MediaType.builder().base("application/xml").type("application/vnd.openstack.identity-v2.0+xml").build() + )) + .build(); + + assertEquals(metadata, expected); + } + + public void testListTenants() { + ServiceClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + HttpRequest.builder().method("GET").endpoint(URI.create(endpoint + "/v2.0/tenants")). + headers(ImmutableMultimap.of("Accept", APPLICATION_JSON, "X-Auth-Token", authToken)).build(), + HttpResponse.builder().statusCode(200). + payload(payloadFromResourceWithContentType("/tenant_list.json", APPLICATION_JSON)).build()) + .getServiceClientForRegion("region-a.geo-1"); + Set tenants = client.listTenants(); + assertNotNull(tenants); + assertFalse(tenants.isEmpty()); + + Set expected = ImmutableSet.of( + Tenant.builder().name("demo").id("05d1dc7af71646deba64cfc17b81bec0").build(), + Tenant.builder().name("admin").id("7aa2e17ec29f44d193c48feaba0852cc").build() + ); + + assertEquals(tenants, expected); + } +} diff --git a/labs/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/UserClientLiveTest.java b/labs/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/UserClientLiveTest.java new file mode 100644 index 0000000000..9399e9c190 --- /dev/null +++ b/labs/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/UserClientLiveTest.java @@ -0,0 +1,61 @@ +/** + * 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.keystone.v2_0; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertNotNull; + +import java.util.Set; + +import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata; +import org.jclouds.openstack.keystone.v2_0.domain.Tenant; +import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneClientLiveTest; +import org.testng.annotations.Test; + +/** + * Tests UserClient + * + * @author Adam Lowe + */ +@Test(groups = "live", testName = "UserClientLiveTest") +public class UserClientLiveTest extends BaseKeystoneClientLiveTest { + + public void testGetApiMetaData() { + for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { + ApiMetadata result = keystoneContext.getApi().getServiceClientForRegion(regionId).getApiMetadata(); + assertNotNull(result); + assertNotNull(result.getId()); + assertNotNull(result.getStatus()); + assertNotNull(result.getUpdated()); + } + } + + public void testListTenants() { + for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { + Set result = keystoneContext.getApi().getServiceClientForRegion(regionId).listTenants(); + assertNotNull(result); + assertFalse(result.isEmpty()); + + for (Tenant tenant : result) { + assertNotNull(tenant.getId()); + } + } + } +} diff --git a/labs/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/internal/BaseKeystoneClientLiveTest.java b/labs/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/internal/BaseKeystoneClientLiveTest.java new file mode 100644 index 0000000000..ef64a89a4b --- /dev/null +++ b/labs/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/internal/BaseKeystoneClientLiveTest.java @@ -0,0 +1,77 @@ +/** + * 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.keystone.v2_0.internal; + +import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE; + +import java.util.Properties; + +import org.jclouds.apis.BaseContextLiveTest; +import org.jclouds.openstack.keystone.v2_0.KeystoneApiMetadata; +import org.jclouds.openstack.keystone.v2_0.KeystoneAsyncClient; +import org.jclouds.openstack.keystone.v2_0.KeystoneClient; +import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties; +import org.jclouds.openstack.services.ServiceType; +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 KeystoneClient} + * + * @author Adam Lowe + */ +@Test(groups = "live") +public class BaseKeystoneClientLiveTest extends BaseContextLiveTest> { + + public BaseKeystoneClientLiveTest() { + provider = "openstack-keystone"; + } + + protected RestContext keystoneContext; + + @BeforeGroups(groups = { "integration", "live" }) + @Override + public void setupContext() { + super.setupContext(); + keystoneContext = context; + } + + @Override + protected Properties setupProperties() { + Properties props = super.setupProperties(); + setIfTestSystemPropertyPresent(props, KeystoneProperties.CREDENTIAL_TYPE); + return props; + } + + @AfterGroups(groups = "live") + protected void tearDown() { + if (keystoneContext != null) + keystoneContext.close(); + } + + @Override + protected TypeToken> contextType() { + return KeystoneApiMetadata.CONTEXT_TOKEN; + } + +} diff --git a/labs/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/internal/BaseKeystoneRestClientExpectTest.java b/labs/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/internal/BaseKeystoneRestClientExpectTest.java new file mode 100644 index 0000000000..8d8afcffc0 --- /dev/null +++ b/labs/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/internal/BaseKeystoneRestClientExpectTest.java @@ -0,0 +1,86 @@ +/** + * 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.keystone.v2_0.internal; + +import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE; + +import java.net.URI; +import java.util.Properties; + +import javax.ws.rs.core.MediaType; + +import org.jclouds.Constants; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.openstack.keystone.v1_1.config.AuthenticationServiceModule; +import org.jclouds.openstack.services.ServiceType; +import org.jclouds.rest.internal.BaseRestClientExpectTest; + +import com.google.common.base.Objects; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.net.HttpHeaders; + +/** + * Base class for writing KeyStone 2.0 Rest Client Expect tests + * + * @author Adam Lowe + */ +public class BaseKeystoneRestClientExpectTest extends BaseRestClientExpectTest { + protected HttpRequest keystoneAuthWithUsernameAndPassword; + protected HttpRequest keystoneAuthWithAccessKeyAndSecretKey; + protected String authToken; + protected HttpResponse responseWithKeystoneAccess; + protected String endpoint = "https://csnode.jclouds.org"; + + public BaseKeystoneRestClientExpectTest() { + provider = "openstack-keystone"; + 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; + } + + 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); + } + + @Override + protected Properties setupProperties() { + Properties props = super.setupProperties(); + props.put(SERVICE_TYPE, ServiceType.IDENTITY); + return props; + } + + @Override + protected HttpRequestComparisonType compareHttpRequestAsType(HttpRequest input) { + return Objects.equal("HEAD", input.getMethod()) ? HttpRequestComparisonType.DEFAULT : HttpRequestComparisonType.JSON; + } + +} diff --git a/labs/openstack-keystone/src/test/resources/api_metadata.json b/labs/openstack-keystone/src/test/resources/api_metadata.json new file mode 100644 index 0000000000..09934299c9 --- /dev/null +++ b/labs/openstack-keystone/src/test/resources/api_metadata.json @@ -0,0 +1 @@ +{"version": {"status": "beta", "updated": "2011-11-19T00:00:00Z", "media-types": [{"base": "application/json", "type": "application/vnd.openstack.identity-v2.0+json"}, {"base": "application/xml", "type": "application/vnd.openstack.identity-v2.0+xml"}], "id": "v2.0", "links": [{"href": "http://172.16.89.140:5000/v2.0/", "rel": "self"}, {"href": "http://docs.openstack.org/api/openstack-identity-service/2.0/content/", "type": "text/html", "rel": "describedby"}, {"href": "http://docs.openstack.org/api/openstack-identity-service/2.0/identity-dev-guide-2.0.pdf", "type": "application/pdf", "rel": "describedby"}]}} \ No newline at end of file diff --git a/labs/openstack-keystone/src/test/resources/logback.xml b/labs/openstack-keystone/src/test/resources/logback.xml new file mode 100644 index 0000000000..a4f81d3fa6 --- /dev/null +++ b/labs/openstack-keystone/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-keystone/src/test/resources/tenant_details.json b/labs/openstack-keystone/src/test/resources/tenant_details.json new file mode 100644 index 0000000000..12cdc272e9 --- /dev/null +++ b/labs/openstack-keystone/src/test/resources/tenant_details.json @@ -0,0 +1 @@ +{"tenant": {"enabled": true, "description": null, "name": "admin", "id": "013ba41150a14830bec85ffe93353bcc"}} \ No newline at end of file diff --git a/labs/openstack-keystone/src/test/resources/tenant_list.json b/labs/openstack-keystone/src/test/resources/tenant_list.json new file mode 100644 index 0000000000..aadcd703c0 --- /dev/null +++ b/labs/openstack-keystone/src/test/resources/tenant_list.json @@ -0,0 +1 @@ +{"tenants_links": [], "tenants": [{"enabled": true, "description": null, "name": "demo", "id": "05d1dc7af71646deba64cfc17b81bec0"}, {"enabled": true, "description": null, "name": "admin", "id": "7aa2e17ec29f44d193c48feaba0852cc"}]} \ No newline at end of file diff --git a/labs/openstack-keystone/src/test/resources/token_details.json b/labs/openstack-keystone/src/test/resources/token_details.json new file mode 100644 index 0000000000..530fb5932b --- /dev/null +++ b/labs/openstack-keystone/src/test/resources/token_details.json @@ -0,0 +1 @@ +{"access": {"token": {"expires": "2012-04-28T12:42:50Z", "id": "167eccdc790946969ced473732e8109b", "tenant": {"id": "4cea93f5464b4f1c921fb3e0461d72b5", "enabled": true, "description": null, "name": "demo"}}, "user": {"username": "admin", "roles_links": [], "id": "2b9b606181634ae9ac86fd95a8bc2cde", "roles": [{"id": "79cada5c02814b57a52e0eed4dd388cb", "name": "admin"}], "name": "admin"}}} diff --git a/labs/openstack-keystone/src/test/resources/user_details.json b/labs/openstack-keystone/src/test/resources/user_details.json new file mode 100644 index 0000000000..17f1ae666e --- /dev/null +++ b/labs/openstack-keystone/src/test/resources/user_details.json @@ -0,0 +1 @@ +{"user": {"name": "nova", "enabled": true, "email": "nova@example.com", "id": "e021dfd758eb44a89f1c57c8ef3be8e2", "tenantId": "ab1da202f5774cceb5da2aeff1f0aa87"}} \ No newline at end of file diff --git a/labs/openstack-keystone/src/test/resources/user_endpoints.json b/labs/openstack-keystone/src/test/resources/user_endpoints.json new file mode 100644 index 0000000000..1e73bda239 --- /dev/null +++ b/labs/openstack-keystone/src/test/resources/user_endpoints.json @@ -0,0 +1,10 @@ +{"endpoints": [ + { + "adminURL": "https://csnode.jclouds.org:35357/v2.0/", + "publicURL": "https://csnode.jclouds.org/v2.0/", + "region": "region-a.geo-1", + "id": "2.0", + "versionId":"2.0", + "list": "https://csnode.jclouds.org/extension" + } + ]} \ No newline at end of file diff --git a/labs/openstack-keystone/src/test/resources/user_list.json b/labs/openstack-keystone/src/test/resources/user_list.json new file mode 100644 index 0000000000..641a557b8a --- /dev/null +++ b/labs/openstack-keystone/src/test/resources/user_list.json @@ -0,0 +1 @@ +{"users": [{"name": "admin", "enabled": true, "email": "admin@example.com", "id": "2b9b606181634ae9ac86fd95a8bc2cde", "tenantId": null}, {"name": "demo", "enabled": true, "email": "demo@example.com", "id": "667b2e1420604df8b67cd8ea57d4ee64", "tenantId": null}, {"name": "nova", "enabled": true, "email": "nova@example.com", "id": "e021dfd758eb44a89f1c57c8ef3be8e2", "tenantId": "ab1da202f5774cceb5da2aeff1f0aa87"}, {"name": "glance", "enabled": true, "email": "glance@example.com", "id": "3f6c1c9ba993495ead7d2eb2192e284f", "tenantId": "ab1da202f5774cceb5da2aeff1f0aa87"}]} \ No newline at end of file diff --git a/labs/openstack-keystone/src/test/resources/user_role_list.json b/labs/openstack-keystone/src/test/resources/user_role_list.json new file mode 100644 index 0000000000..ee90ff90ea --- /dev/null +++ b/labs/openstack-keystone/src/test/resources/user_role_list.json @@ -0,0 +1 @@ +{"roles": [{"id": "79cada5c02814b57a52e0eed4dd388cb", "name": "admin"}]} \ No newline at end of file diff --git a/labs/openstack-keystone/src/test/resources/user_tenant_role_list.json b/labs/openstack-keystone/src/test/resources/user_tenant_role_list.json new file mode 100644 index 0000000000..0a25228c84 --- /dev/null +++ b/labs/openstack-keystone/src/test/resources/user_tenant_role_list.json @@ -0,0 +1 @@ +{"roles": [{"id": "31c451195aac49b386039341e2c92a16", "name": "KeystoneServiceAdmin"}, {"id": "79cada5c02814b57a52e0eed4dd388cb", "name": "admin"}, {"id": "6ea17ddd37a6447794cb0e164d4db894", "name": "KeystoneAdmin"}]} \ No newline at end of file diff --git a/labs/pom.xml b/labs/pom.xml index a6d3e22750..521a07e677 100644 --- a/labs/pom.xml +++ b/labs/pom.xml @@ -43,5 +43,9 @@ carrenza-vcloud-director openstack-swift jenkins + cdmi + openstack-glance + joyent-sdc + openstack-keystone diff --git a/labs/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/features/VMClientLiveTest.java b/labs/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/features/VMClientLiveTest.java index 0afcd54aeb..e25953ed34 100644 --- a/labs/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/features/VMClientLiveTest.java +++ b/labs/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/features/VMClientLiveTest.java @@ -28,7 +28,6 @@ import org.jclouds.cim.OSType; import org.jclouds.compute.domain.CIMOperatingSystem; import org.jclouds.compute.domain.ExecResponse; import org.jclouds.domain.LoginCredentials; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.InetSocketAddressConnect; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.savvis.vpdc.domain.Network; @@ -48,13 +47,14 @@ import com.google.common.base.Predicate; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet.Builder; import com.google.common.collect.Iterables; +import com.google.common.net.HostAndPort; @Test(groups = "live") public class VMClientLiveTest extends BaseVPDCClientLiveTest { private VMClient client; private VM vm; - private RetryablePredicate socketTester; + private RetryablePredicate socketTester; private String username = checkNotNull(System.getProperty("test." + provider + ".loginUser"), "test." + provider + ".loginUser"); @@ -66,7 +66,7 @@ public class VMClientLiveTest extends BaseVPDCClientLiveTest { public void setupContext() { super.setupContext(); client = restContext.getApi().getVMClient(); - socketTester = new RetryablePredicate(new InetSocketAddressConnect(), 130, 10, TimeUnit.SECONDS);// make + socketTester = new RetryablePredicate(new InetSocketAddressConnect(), 130, 10, TimeUnit.SECONDS);// make } private String billingSiteId; @@ -277,7 +277,7 @@ public class VMClientLiveTest extends BaseVPDCClientLiveTest { assert clonedVM.getHref() != null : clonedVM; } - protected void checkSSH(IPSocket socket) { + protected void checkSSH(HostAndPort socket) { socketTester.apply(socket); SshClient client = view.utils().sshFactory() .create(socket, LoginCredentials.builder().user(username).password(password).build()); diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/FindLocationForResource.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/FindLocationForResource.java new file mode 100644 index 0000000000..b123469a01 --- /dev/null +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/FindLocationForResource.java @@ -0,0 +1,71 @@ +/** + * 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.vcloud.director.v1_5.compute.functions; + +import java.net.URI; +import java.util.NoSuchElementException; +import java.util.Set; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.collect.Memoized; +import org.jclouds.domain.Location; +import org.jclouds.logging.Logger; +import org.jclouds.vcloud.director.v1_5.domain.Reference; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; + +/** + * @author danikov + */ +@Singleton +public class FindLocationForResource implements Function { + + @Resource + protected Logger logger = Logger.NULL; + + final Supplier> locations; + + @Inject + public FindLocationForResource(@Memoized Supplier> locations) { + this.locations = locations; + } + + /** + * searches for a location associated with this resource. + * + * @throws NoSuchElementException + * if not found + */ + public Location apply(Reference resource) { + for (Location input : locations.get()) { + do { + // The "name" isn't always present, ex inside a vApp we have a rel + // link that only includes href and type. + if (URI.create(input.getId()).equals(resource.getHref())) + return input; + } while ((input = input.getParent()) != null); + } + throw new NoSuchElementException(String.format("resource: %s not found in locations: %s", resource, + locations.get())); + } +} \ No newline at end of file diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/HardwareForVAppTemplate.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/HardwareForVAppTemplate.java new file mode 100644 index 0000000000..d1bef8b89c --- /dev/null +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/HardwareForVAppTemplate.java @@ -0,0 +1,90 @@ +/** + * 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.vcloud.director.v1_5.compute.functions; + +import static com.google.common.base.Preconditions.checkNotNull; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.predicates.ImagePredicates; +import org.jclouds.dmtf.ovf.VirtualHardwareSection; +import org.jclouds.logging.Logger; +import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType; +import org.jclouds.vcloud.director.v1_5.domain.Link; +import org.jclouds.vcloud.director.v1_5.domain.VAppTemplate; +import org.jclouds.vcloud.director.v1_5.domain.dmtf.Envelope; +import org.jclouds.vcloud.director.v1_5.predicates.LinkPredicates; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; + +/** + * @author Adrian Cole + */ +@Singleton +public class HardwareForVAppTemplate implements Function { + + @Resource + protected Logger logger = Logger.NULL; + + private final Function templateToEnvelope; + private final FindLocationForResource findLocationForResource; + private final VCloudHardwareBuilderFromResourceAllocations rasdToHardwareBuilder; + + @Inject + protected HardwareForVAppTemplate(Function templateToEnvelope, + FindLocationForResource findLocationForResource, + VCloudHardwareBuilderFromResourceAllocations rasdToHardwareBuilder) { + this.templateToEnvelope = checkNotNull(templateToEnvelope, "templateToEnvelope"); + this.findLocationForResource = checkNotNull(findLocationForResource, "findLocationForResource"); + this.rasdToHardwareBuilder = checkNotNull(rasdToHardwareBuilder, "rasdToHardwareBuilder"); + } + + @Override + public Hardware apply(VAppTemplate from) { + checkNotNull(from, "VAppTemplate"); + + Envelope ovf = templateToEnvelope.apply(from); + + if (ovf.getVirtualSystem().getVirtualHardwareSections().size() > 1) { + logger.warn("multiple hardware choices found. using first", ovf); + } + VirtualHardwareSection hardware = Iterables.get(ovf.getVirtualSystem().getVirtualHardwareSections(), 0); + HardwareBuilder builder = rasdToHardwareBuilder.apply(hardware.getItems()); + Link vdc = Iterables.find(checkNotNull(from, "from").getLinks(), LinkPredicates.typeEquals(VCloudDirectorMediaType.VDC)); + if (vdc != null) { + builder.location(findLocationForResource.apply(vdc)); + } else { + // otherwise, it could be in a public catalog, which is not assigned to a VDC + } + builder.ids(from.getHref().toASCIIString()).name(from.getName()).supportsImage( + ImagePredicates.idEquals(from.getHref().toASCIIString())); + builder.hypervisor("VMware"); + return builder.build(); + + } + + protected String getName(String name) { + return name; + } +} \ No newline at end of file diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/HardwareForVm.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/HardwareForVm.java new file mode 100644 index 0000000000..4af222a544 --- /dev/null +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/HardwareForVm.java @@ -0,0 +1,78 @@ +/** + * 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.vcloud.director.v1_5.compute.functions; + +import static com.google.common.base.Preconditions.checkNotNull; + +import javax.annotation.Resource; +import javax.inject.Inject; + +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.HardwareBuilder; +import org.jclouds.compute.predicates.ImagePredicates; +import org.jclouds.domain.Location; +import org.jclouds.logging.Logger; +import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType; +import org.jclouds.vcloud.director.v1_5.domain.Reference; +import org.jclouds.vcloud.director.v1_5.domain.Vm; +import org.jclouds.vcloud.director.v1_5.domain.section.VirtualHardwareSection; +import org.jclouds.vcloud.director.v1_5.functions.SectionForVApp; +import org.jclouds.vcloud.director.v1_5.predicates.LinkPredicates; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; + +/** + * @author Adrian Cole + */ +public class HardwareForVm implements Function { + + @Resource + protected Logger logger = Logger.NULL; + + private final Function findLocationForResource; + private final VCloudHardwareBuilderFromResourceAllocations rasdToHardwareBuilder; + private final SectionForVApp findVirtualHardwareSectionForVm; + + @Inject + protected HardwareForVm(Function findLocationForResource, + VCloudHardwareBuilderFromResourceAllocations rasdToHardwareBuilder, + SectionForVApp findVirtualHardwareSectionForVm) { + this.findLocationForResource = checkNotNull(findLocationForResource, "findLocationForResource"); + this.rasdToHardwareBuilder = checkNotNull(rasdToHardwareBuilder, "rasdToHardwareBuilder"); + this.findVirtualHardwareSectionForVm = checkNotNull(findVirtualHardwareSectionForVm, "findVirtualHardwareSectionForVm"); + } + + @Override + public Hardware apply(Vm from) { + checkNotNull(from, "VApp"); + // TODO make this work with composite vApps + if (from == null) + return null; + + VirtualHardwareSection hardware = findVirtualHardwareSectionForVm.apply(from); + HardwareBuilder builder = rasdToHardwareBuilder.apply(hardware.getItems()); + builder.location(findLocationForResource.apply(Iterables.find(checkNotNull(from, "from").getLinks(), + LinkPredicates.typeEquals(VCloudDirectorMediaType.VDC)))); + builder.ids(from.getHref().toASCIIString()).name(from.getName()).supportsImage( + ImagePredicates.idEquals(from.getHref().toASCIIString())); + builder.hypervisor("VMware"); + return builder.build(); + } +} \ No newline at end of file diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/ImageForVAppTemplate.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/ImageForVAppTemplate.java new file mode 100644 index 0000000000..18c934ebc1 --- /dev/null +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/ImageForVAppTemplate.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.vcloud.director.v1_5.compute.functions; + +import static com.google.common.base.Preconditions.checkNotNull; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.compute.domain.CIMOperatingSystem; +import org.jclouds.compute.domain.Image; +import org.jclouds.compute.domain.ImageBuilder; +import org.jclouds.compute.reference.ComputeServiceConstants; +import org.jclouds.logging.Logger; +import org.jclouds.ovf.Envelope; +import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType; +import org.jclouds.vcloud.director.v1_5.domain.Link; +import org.jclouds.vcloud.director.v1_5.domain.VAppTemplate; +import org.jclouds.vcloud.director.v1_5.predicates.LinkPredicates; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; + +/** + * @author Adrian Cole + */ +@Singleton +public class ImageForVAppTemplate implements Function { + + @Resource + @Named(ComputeServiceConstants.COMPUTE_LOGGER) + public Logger logger = Logger.NULL; + + private final Function templateToEnvelope; + private final FindLocationForResource findLocationForResource; + + @Inject + protected ImageForVAppTemplate(Function templateToEnvelope, + FindLocationForResource findLocationForResource) { + this.templateToEnvelope = checkNotNull(templateToEnvelope, "templateToEnvelope"); + this.findLocationForResource = checkNotNull(findLocationForResource, "findLocationForResource"); + } + + @Override + public Image apply(VAppTemplate from) { + checkNotNull(from, "VAppTemplate"); + Envelope ovf = templateToEnvelope.apply(from); + + ImageBuilder builder = new ImageBuilder(); + builder.ids(from.getHref().toASCIIString()); + builder.uri(from.getHref()); + builder.name(from.getName()); + Link vdc = Iterables.find(checkNotNull(from, "from").getLinks(), LinkPredicates.typeEquals(VCloudDirectorMediaType.VDC)); + if (vdc != null) { + builder.location(findLocationForResource.apply(vdc)); + } else { + // otherwise, it could be in a public catalog, which is not assigned to a VDC + } + builder.description(from.getDescription() != null ? from.getDescription() : from.getName()); + builder.operatingSystem(CIMOperatingSystem.toComputeOs(ovf)); + return builder.build(); + } + +} \ No newline at end of file diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/VCloudHardwareBuilderFromResourceAllocations.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/VCloudHardwareBuilderFromResourceAllocations.java new file mode 100644 index 0000000000..133af532e2 --- /dev/null +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/VCloudHardwareBuilderFromResourceAllocations.java @@ -0,0 +1,43 @@ +/** + * 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.vcloud.director.v1_5.compute.functions; + +import javax.inject.Singleton; + +import org.jclouds.compute.domain.Volume; +import org.jclouds.dmtf.cim.ResourceAllocationSettingData; +import org.jclouds.dmtf.cim.functions.HardwareBuilderFromResourceAllocations; + +/** + * @author Adrian Cole + */ +@Singleton +public class VCloudHardwareBuilderFromResourceAllocations extends HardwareBuilderFromResourceAllocations { + @Override + public Volume apply(ResourceAllocationSettingData from) { + // FIXME: not yet implemented +// if (from instanceof VCloudHardDisk) { +// VCloudHardDisk vDisk = VCloudHardDisk.class.cast(from); +// return new VolumeImpl(from.getAddressOnParent() + "", Volume.Type.LOCAL, vDisk.getCapacity() / 1024f, null, +// "0".equals(from.getAddressOnParent()), true); +// } else { + return super.apply(from); +// } + } +} \ No newline at end of file diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/ValidateVAppTemplateAndReturnEnvelopeOrThrowIllegalArgumentException.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/ValidateVAppTemplateAndReturnEnvelopeOrThrowIllegalArgumentException.java new file mode 100644 index 0000000000..7e36aefa33 --- /dev/null +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/ValidateVAppTemplateAndReturnEnvelopeOrThrowIllegalArgumentException.java @@ -0,0 +1,84 @@ +/** + * 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.vcloud.director.v1_5.compute.functions; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import java.net.URI; +import java.util.concurrent.ExecutionException; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.dmtf.ovf.NetworkSection; +import org.jclouds.logging.Logger; +import org.jclouds.ovf.Envelope; +import org.jclouds.vcloud.director.v1_5.domain.VAppTemplate; +import org.jclouds.vcloud.director.v1_5.functions.SectionForVAppTemplate; + +import com.google.common.base.Function; +import com.google.common.cache.LoadingCache; + +/** + * @author Adrian Cole + */ +@Singleton +public class ValidateVAppTemplateAndReturnEnvelopeOrThrowIllegalArgumentException implements + Function { + + @Resource + protected Logger logger = Logger.NULL; + + private final LoadingCache envelopes; + private final SectionForVAppTemplate findNetworkSectionForVAppTemplate; + + @Inject + protected ValidateVAppTemplateAndReturnEnvelopeOrThrowIllegalArgumentException(LoadingCache envelopes, + SectionForVAppTemplate findNetworkSectionForVAppTemplate) { + this.envelopes = checkNotNull(envelopes, "envelopes"); + this.findNetworkSectionForVAppTemplate = checkNotNull(findNetworkSectionForVAppTemplate, "findNetworkSectionForVAppTemplate"); + } + + @Override + public Envelope apply(VAppTemplate from) { + checkArgument(from.getChildren().size() == 1, "multiple vms are not supported: %s", from); + + checkArgument(findNetworkSectionForVAppTemplate.apply(from).getNetworks().size() == 1, + "multiple network connections are not supported: %s", from); + + checkArgument(from.isOvfDescriptorUploaded(), "ovf descriptor is not uploaded: %s", from); + Envelope ovf = getOVFForVAppTemplateAndValidate(from); + return ovf; + } + + private Envelope getOVFForVAppTemplateAndValidate(VAppTemplate from) throws IllegalArgumentException { + Envelope ovf; + try { + ovf = envelopes.get(from.getHref()); + checkArgument(ovf.getVirtualSystem().getVirtualHardwareSections().size() > 0, + "no hardware sections exist in ovf %s", ovf); + } catch (ExecutionException e) { + throw new IllegalArgumentException("no ovf envelope found for: " + from, e); + } + return ovf; + } +} + diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/VmToNodeMetadata.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/VmToNodeMetadata.java new file mode 100644 index 0000000000..9f18522498 --- /dev/null +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/functions/VmToNodeMetadata.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.vcloud.director.v1_5.compute.functions; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Predicates.not; +import static com.google.common.collect.Iterables.filter; +import static org.jclouds.vcloud.director.v1_5.compute.util.VCloudDirectorComputeUtils.getCredentialsFrom; +import static org.jclouds.vcloud.director.v1_5.compute.util.VCloudDirectorComputeUtils.getIpsFromVm; +import static org.jclouds.vcloud.director.v1_5.compute.util.VCloudDirectorComputeUtils.toComputeOs; + +import java.util.Map; +import java.util.Set; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.compute.domain.Hardware; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.NodeMetadataBuilder; +import org.jclouds.compute.domain.NodeState; +import org.jclouds.compute.functions.GroupNamingConvention; +import org.jclouds.domain.Credentials; +import org.jclouds.logging.Logger; +import org.jclouds.util.InetAddresses2.IsPrivateIPAddress; +import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType; +import org.jclouds.vcloud.director.v1_5.domain.ResourceEntity.Status; +import org.jclouds.vcloud.director.v1_5.domain.Vm; +import org.jclouds.vcloud.director.v1_5.predicates.LinkPredicates; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; + +/** + * @author Adrian Cole + */ +@Singleton +public class VmToNodeMetadata implements Function { + @Resource + protected static Logger logger = Logger.NULL; + + protected final FindLocationForResource findLocationForResourceInVDC; + protected final Function hardwareForVm; + protected final Map vAppStatusToNodeState; + protected final Map credentialStore; + protected final GroupNamingConvention nodeNamingConvention; + + @Inject + protected VmToNodeMetadata(Map vAppStatusToNodeState, Map credentialStore, + FindLocationForResource findLocationForResourceInVDC, Function hardwareForVm, + GroupNamingConvention.Factory namingConvention) { + this.nodeNamingConvention = checkNotNull(namingConvention, "namingConvention").createWithoutPrefix(); + this.hardwareForVm = checkNotNull(hardwareForVm, "hardwareForVm"); + this.findLocationForResourceInVDC = checkNotNull(findLocationForResourceInVDC, "findLocationForResourceInVDC"); + this.credentialStore = checkNotNull(credentialStore, "credentialStore"); + this.vAppStatusToNodeState = checkNotNull(vAppStatusToNodeState, "vAppStatusToNodeState"); + } + + public NodeMetadata apply(Vm from) { + NodeMetadataBuilder builder = new NodeMetadataBuilder(); + builder.ids(from.getHref().toASCIIString()); + builder.uri(from.getHref()); + builder.name(from.getName()); + builder.hostname(from.getName()); + builder.location(findLocationForResourceInVDC.apply( + Iterables.find(from.getLinks(), LinkPredicates.typeEquals(VCloudDirectorMediaType.VDC)))); + builder.group(nodeNamingConvention.groupInUniqueNameOrNull(from.getName())); + builder.operatingSystem(toComputeOs(from)); + builder.hardware(hardwareForVm.apply(from)); + builder.state(vAppStatusToNodeState.get(from.getStatus())); + Set addresses = getIpsFromVm(from); + builder.publicAddresses(filter(addresses, not(IsPrivateIPAddress.INSTANCE))); + builder.privateAddresses(filter(addresses, IsPrivateIPAddress.INSTANCE)); + + // normally, we don't affect the credential store when reading vApps. + // However, login user, etc, is actually in the metadata, so lets see + Credentials fromApi = getCredentialsFrom(from); + if (fromApi != null && !credentialStore.containsKey("node#" + from.getHref().toASCIIString())) + credentialStore.put("node#" + from.getHref().toASCIIString(), fromApi); + return builder.build(); + } +} \ No newline at end of file diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/util/VCloudDirectorComputeUtils.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/util/VCloudDirectorComputeUtils.java new file mode 100644 index 0000000000..c70942bf38 --- /dev/null +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/compute/util/VCloudDirectorComputeUtils.java @@ -0,0 +1,150 @@ +/** + * 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.vcloud.director.v1_5.compute.util; + +import static com.google.common.collect.Iterables.filter; + +import java.util.Set; + +import org.jclouds.cim.OSType; +import org.jclouds.compute.domain.CIMOperatingSystem; +import org.jclouds.compute.domain.OperatingSystem; +import org.jclouds.dmtf.CIMPredicates; +import org.jclouds.dmtf.cim.ResourceAllocationSettingData; +import org.jclouds.dmtf.cim.ResourceAllocationSettingData.ResourceType; +import org.jclouds.domain.LoginCredentials; +import org.jclouds.vcloud.director.v1_5.domain.VApp; +import org.jclouds.vcloud.director.v1_5.domain.VAppTemplate; +import org.jclouds.vcloud.director.v1_5.domain.Vm; +import org.jclouds.vcloud.director.v1_5.domain.network.NetworkConnection; +import org.jclouds.vcloud.director.v1_5.domain.section.GuestCustomizationSection; +import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConnectionSection; +import org.jclouds.vcloud.director.v1_5.domain.section.OperatingSystemSection; +import org.jclouds.vcloud.director.v1_5.domain.section.VirtualHardwareSection; +import org.jclouds.vcloud.director.v1_5.functions.SectionForVApp; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSet.Builder; +import com.google.common.collect.Iterables; +import com.google.inject.Inject; + +/** + * + * @author danikov + */ +public class VCloudDirectorComputeUtils { + + public static OperatingSystem toComputeOs(VApp vApp, OperatingSystem defaultOs) { + CIMOperatingSystem cimOs = toComputeOs(vApp); + return cimOs != null ? cimOs : defaultOs; + } + + public static CIMOperatingSystem toComputeOs(VApp vApp) { + // TODO we need to change the design so that it doesn't assume single-vms + return vApp.getChildren().getVms().size() > 0 ? toComputeOs(Iterables.get(vApp.getChildren().getVms(), 0)) : null; + } + + private static SectionForVApp findOperatingSystemSectionForVApp = + new SectionForVApp(OperatingSystemSection.class); + + public static CIMOperatingSystem toComputeOs(Vm vm) { + return toComputeOs(findOperatingSystemSectionForVApp.apply(vm)); + } + + public static CIMOperatingSystem toComputeOs(OperatingSystemSection os) { + return new CIMOperatingSystem(OSType.fromValue(os.getId()), "", null, os.getDescription()); + } + + public static String getVirtualSystemIdentifierOfFirstVMIn(VApp vApp) { + return vApp.getChildren().getVms().size() > 0 ? + getVirtualSystemIdentifierOf(Iterables.get(vApp.getChildren().getVms(), 0)) : null; + } + + @Inject private static SectionForVApp findVirtualHardwareSectionForVApp = + new SectionForVApp(VirtualHardwareSection.class); + + public static String getVirtualSystemIdentifierOf(Vm vm) { + VirtualHardwareSection virtualHardwareSection = findVirtualHardwareSectionForVApp.apply(vm); + if (virtualHardwareSection != null && virtualHardwareSection != null) + return virtualHardwareSection.getSystem().getVirtualSystemIdentifier(); + return null; + } + + public static LoginCredentials getCredentialsFrom(VApp vApp) { + return vApp.getChildren().getVms().size() > 0 ? + getCredentialsFrom(Iterables.get(vApp.getChildren().getVms(), 0)) : null; + } + + public static LoginCredentials getCredentialsFrom(VAppTemplate vApp) { + return vApp.getChildren().size() > 0 ? getCredentialsFrom(Iterables.get(vApp.getChildren(), 0)) : null; + } + + @Inject private static SectionForVApp findGuestCustomizationSectionForVApp = + new SectionForVApp(GuestCustomizationSection.class); + + public static LoginCredentials getCredentialsFrom(Vm vm) { + LoginCredentials.Builder builder = LoginCredentials.builder(); + GuestCustomizationSection guestCustomizationSection = findGuestCustomizationSectionForVApp.apply(vm); + if (guestCustomizationSection != null) + builder.password(guestCustomizationSection.getAdminPassword()); + return builder.build(); + } + + @Inject private static SectionForVApp findNetworkConnectionSectionForVApp = + new SectionForVApp(NetworkConnectionSection.class); + + public static Set getIpsFromVApp(VApp vApp) { + // TODO make this work with composite vApps + if (vApp.getChildren().getVms().size() == 0) + return ImmutableSet.of(); + return getIpsFromVm(Iterables.get(vApp.getChildren().getVms(), 0)); + } + + public static Set getIpsFromVm(Vm vm) { + Builder ips = ImmutableSet.builder(); + // TODO: figure out how to differentiate public from private ip addresses + // assumption is that we'll do this from the network object, which may + // have + // enough data to tell whether or not it is a public network without + // string + // parsing. At worst, we could have properties set per cloud provider to + // declare the networks which are public, then check against these in + // networkconnection.getNetwork + NetworkConnectionSection networkConnectionSection = findNetworkConnectionSectionForVApp.apply(vm); + if (networkConnectionSection != null) { + for (NetworkConnection connection : networkConnectionSection.getNetworkConnections()) { + if (connection.getIpAddress() != null) + ips.add(connection.getIpAddress()); + if (connection.getExternalIpAddress() != null) + ips.add(connection.getExternalIpAddress()); + } + } else { + for (ResourceAllocationSettingData net : filter(findVirtualHardwareSectionForVApp.apply(vm).getItems(), + CIMPredicates.resourceTypeIn(ResourceType.ETHERNET_ADAPTER))) { + // FIXME: not yet implemented +// if (net instanceof VCloudNetworkAdapter) { +// VCloudNetworkAdapter vNet = VCloudNetworkAdapter.class.cast(net); +// if (vNet.getIpAddress() != null) +// ips.add(vNet.getIpAddress()); +// } + } + } + return ips.build(); + } +} diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/config/VCloudDirectorRestClientModule.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/config/VCloudDirectorRestClientModule.java index c6c4df7485..2f560e50a1 100644 --- a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/config/VCloudDirectorRestClientModule.java +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/config/VCloudDirectorRestClientModule.java @@ -43,6 +43,7 @@ import org.jclouds.rest.internal.RestContextImpl; import org.jclouds.vcloud.director.v1_5.admin.VCloudDirectorAdminAsyncClient; import org.jclouds.vcloud.director.v1_5.admin.VCloudDirectorAdminClient; import org.jclouds.vcloud.director.v1_5.annotations.Login; +import org.jclouds.vcloud.director.v1_5.compute.util.VCloudDirectorComputeUtils; import org.jclouds.vcloud.director.v1_5.domain.Session; import org.jclouds.vcloud.director.v1_5.domain.SessionWithToken; import org.jclouds.vcloud.director.v1_5.features.CatalogAsyncClient; @@ -67,6 +68,8 @@ import org.jclouds.vcloud.director.v1_5.features.VAppTemplateAsyncClient; import org.jclouds.vcloud.director.v1_5.features.VAppTemplateClient; import org.jclouds.vcloud.director.v1_5.features.VdcAsyncClient; import org.jclouds.vcloud.director.v1_5.features.VdcClient; +import org.jclouds.vcloud.director.v1_5.features.VmAsyncClient; +import org.jclouds.vcloud.director.v1_5.features.VmClient; import org.jclouds.vcloud.director.v1_5.features.admin.AdminCatalogAsyncClient; import org.jclouds.vcloud.director.v1_5.features.admin.AdminCatalogClient; import org.jclouds.vcloud.director.v1_5.features.admin.AdminNetworkAsyncClient; @@ -122,6 +125,7 @@ public class VCloudDirectorRestClientModule extends RestClientModule, Class> ADMIN_DELEGATE_MAP = ImmutableMap., Class>builder() @@ -166,6 +170,7 @@ public class VCloudDirectorRestClientModule extends RestClientModule + * Represents removable media, such as a CD-ROM, DVD or Floppy disk. + * *

  * <complexType name="Media" />
  * 
@@ -53,7 +53,7 @@ public class Media extends ResourceEntity { public static enum ImageType { @XmlEnumValue("iso") ISO("iso"), @XmlEnumValue("floppy") FLOPPY("floppy"), - UNRECOGNIZED("unrecognized"); + @XmlEnumValue("") UNRECOGNIZED("unrecognized"); public static final List ALL = ImmutableList.of(ISO, FLOPPY); diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/domain/Vm.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/domain/Vm.java index d961091764..ce7c33eeeb 100644 --- a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/domain/Vm.java +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/domain/Vm.java @@ -22,6 +22,7 @@ import static com.google.common.base.Objects.equal; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import org.jclouds.dmtf.ovf.environment.EnvironmentType; @@ -30,15 +31,16 @@ import com.google.common.base.Objects; import com.google.common.base.Objects.ToStringHelper; /** - * Represents a VM. + * Represents a virtual machine. * *
- * <complexType name="Vm" />
+ * <complexType name="VmType" />
  * 
* * @author grkvlt@apache.org */ -@XmlType(name = "Vm") +@XmlRootElement(name = "Vm") +@XmlType(name = "VmType") public class Vm extends AbstractVAppType { public static Builder builder() { diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/VAppAsyncClient.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/VAppAsyncClient.java index 3da8d44b23..ad8c0b9119 100644 --- a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/VAppAsyncClient.java +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/VAppAsyncClient.java @@ -122,15 +122,6 @@ public interface VAppAsyncClient { @JAXBResponseParser ListenableFuture deleteVApp(@EndpointParam URI vAppURI); - /** - * @see VAppClient#consolidateVm(URI) - */ - @POST - @Path("/action/consolidate") - @Consumes(TASK) - @JAXBResponseParser - ListenableFuture consolidateVm(@EndpointParam URI vAppURI); - /** * @see VAppClient#modifyControlAccess(URI, ControlAccessParams) */ @@ -180,15 +171,6 @@ public interface VAppAsyncClient { @JAXBResponseParser ListenableFuture exitMaintenanceMode(@EndpointParam URI vAppURI); - /** - * @see VAppClient#installVMwareTools(URI) - */ - @POST - @Path("/action/installVMwareTools") - @Consumes(TASK) - @JAXBResponseParser - ListenableFuture installVMwareTools(@EndpointParam URI vAppURI); - /** * @see VAppClient#recompose(URI, RecomposeVAppParams) */ @@ -200,17 +182,6 @@ public interface VAppAsyncClient { ListenableFuture recompose(@EndpointParam URI vAppURI, @BinderParam(BindToXMLPayload.class) RecomposeVAppParams params); - /** - * @see VAppClient#relocateVm(URI, RelocateParams) - */ - @POST - @Path("/action/relocate") - @Produces(RELOCATE_VM_PARAMS) - @Consumes(TASK) - @JAXBResponseParser - ListenableFuture relocateVm(@EndpointParam URI vAppURI, - @BinderParam(BindToXMLPayload.class) RelocateParams params); - /** * @see VAppClient#undeploy(URI, UndeployVAppParams) */ @@ -222,15 +193,6 @@ public interface VAppAsyncClient { ListenableFuture undeploy(@EndpointParam URI vAppURI, @BinderParam(BindToXMLPayload.class) UndeployVAppParams params); - /** - * @see VAppClient#upgradeHardwareVersion(URI) - */ - @POST - @Path("/action/upgradeHardwareVersion") - @Consumes(TASK) - @JAXBResponseParser - ListenableFuture upgradeHardwareVersion(@EndpointParam URI vAppURI); - /** * @see VAppClient#getControlAccess(URI) */ @@ -295,27 +257,6 @@ public interface VAppAsyncClient { @JAXBResponseParser ListenableFuture suspend(@EndpointParam URI vAppURI); - /** - * @see VAppClient#getGuestCustomizationSection(URI) - */ - @GET - @Path("/guestCustomizationSection") - @Consumes - @JAXBResponseParser - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getGuestCustomizationSection(@EndpointParam URI vmURI); - - /** - * @see VAppClient#modifyGuestCustomizationSection(URI, GuestCustomizationSection) - */ - @PUT - @Path("/guestCustomizationSection") - @Produces(GUEST_CUSTOMIZATION_SECTION) - @Consumes(TASK) - @JAXBResponseParser - ListenableFuture modifyGuestCustomizationSection(@EndpointParam URI vmURI, - @BinderParam(BindToXMLPayload.class) GuestCustomizationSection section); - /** * @see VAppClient#getLeaseSettingsSection(URI) */ @@ -337,28 +278,6 @@ public interface VAppAsyncClient { ListenableFuture modifyLeaseSettingsSection(@EndpointParam URI vAppURI, @BinderParam(BindToXMLPayload.class) LeaseSettingsSection section); - /** - * @see VAppClient#ejectMedia(URI, MediaInsertOrEjectParams) - */ - @POST - @Path("/media/action/ejectMedia") - @Produces(MEDIA_PARAMS) - @Consumes(TASK) - @JAXBResponseParser - ListenableFuture ejectMedia(@EndpointParam URI vmURI, - @BinderParam(BindToXMLPayload.class) MediaInsertOrEjectParams mediaParams); - - /** - * @see VAppClient#insertMedia(URI, MediaInsertOrEjectParams) - */ - @POST - @Path("/media/action/insertMedia") - @Produces(MEDIA_PARAMS) - @Consumes(TASK) - @JAXBResponseParser - ListenableFuture insertMedia(@EndpointParam URI vmURI, - @BinderParam(BindToXMLPayload.class) MediaInsertOrEjectParams mediaParams); - /** * @see VAppClient#getNetworkConfigSection(URI) */ @@ -380,27 +299,6 @@ public interface VAppAsyncClient { ListenableFuture modifyNetworkConfigSection(@EndpointParam URI vAppURI, @BinderParam(BindToXMLPayload.class) NetworkConfigSection section); - /** - * @see VAppClient#getNetworkConnectionSection(URI) - */ - @GET - @Path("/networkConnectionSection") - @Consumes - @JAXBResponseParser - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getNetworkConnectionSection(@EndpointParam URI vmURI); - - /** - * @see VAppClient#modifyNetworkConnectionSection(URI, NetworkConnectionSection) - */ - @PUT - @Path("/networkConnectionSection") - @Produces(NETWORK_CONNECTION_SECTION) - @Consumes(TASK) - @JAXBResponseParser - ListenableFuture modifyNetworkConnectionSection(@EndpointParam URI vmURI, - @BinderParam(BindToXMLPayload.class) NetworkConnectionSection section); - /** * @see VAppClient#getNetworkSection(URI) */ @@ -411,27 +309,6 @@ public interface VAppAsyncClient { @ExceptionParser(ReturnNullOnNotFoundOr404.class) ListenableFuture getNetworkSection(@EndpointParam URI vAppURI); - /** - * @see VAppClient#getOperatingSystemSection(URI) - */ - @GET - @Path("/operatingSystemSection") - @Consumes - @JAXBResponseParser - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getOperatingSystemSection(@EndpointParam URI vmURI); - - /** - * @see VAppClient#modifyOperatingSystemSection(URI, OperatingSystemSection) - */ - @PUT - @Path("/operatingSystemSection") - @Produces(OPERATING_SYSTEM_SECTION) - @Consumes(TASK) - @JAXBResponseParser - ListenableFuture modifyOperatingSystemSection(@EndpointParam URI vmURI, - @BinderParam(BindToXMLPayload.class) OperatingSystemSection section); - /** * @see VAppClient#getOwner(URI) */ @@ -474,56 +351,6 @@ public interface VAppAsyncClient { ListenableFuture modifyProductSections(@EndpointParam URI vAppURI, @BinderParam(BindToXMLPayload.class) ProductSectionList sectionList); - /** - * @see VAppClient#getPendingQuestion(URI) - */ - @GET - @Path("/question") - @Consumes - @JAXBResponseParser - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getPendingQuestion(@EndpointParam URI vAppURI); - - /** - * @see VAppClient#answerQuestion(URI, VmQuestionAnswer) - */ - @POST - @Path("/question/action/answer") - @Produces(VM_PENDING_ANSWER) - @Consumes - @JAXBResponseParser - ListenableFuture answerQuestion(@EndpointParam URI vAppURI, - @BinderParam(BindToXMLPayload.class) VmQuestionAnswer answer); - - /** - * @see VAppClient#getRuntimeInfoSection(URI) - */ - @GET - @Path("/runtimeInfoSection") - @Consumes - @JAXBResponseParser - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getRuntimeInfoSection(@EndpointParam URI vmURI); - - /** - * @see VAppClient#getScreenImage(URI) - */ - @GET - @Path("/screen") - @Consumes(ANY_IMAGE) - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - @ResponseParser(ReturnPayloadBytes.class) - ListenableFuture getScreenImage(@EndpointParam URI vAppURI); - - /** - * @see VAppClient#getScreenTicket(URI) - */ - @POST - @Path("/screen/action/acquireTicket") - @Consumes - @JAXBResponseParser - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getScreenTicket(@EndpointParam URI vAppURI); /** * @see VAppClient#getStartupSection(URI) @@ -547,145 +374,8 @@ public interface VAppAsyncClient { @BinderParam(BindToXMLPayload.class) StartupSection section); /** - * @see VAppClient#getVirtualHardwareSection(URI) - */ - @GET - @Path("/virtualHardwareSection") - @Consumes - @JAXBResponseParser - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getVirtualHardwareSection(@EndpointParam URI vmURI); - - /** - * @see VAppClient#modifyVirtualHardwareSection(URI, VirtualHardwareSection) - */ - @PUT - @Path("/virtualHardwareSection") - @Produces(VIRTUAL_HARDWARE_SECTION) - @Consumes(TASK) - @JAXBResponseParser - ListenableFuture modifyVirtualHardwareSection(@EndpointParam URI vmURI, - @BinderParam(BindToXMLPayload.class) VirtualHardwareSection section); - - /** - * @see VAppClient#getVirtualHardwareSectionCpu(URI) - */ - @GET - @Path("/virtualHardwareSection/cpu") - @Consumes - @JAXBResponseParser - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getVirtualHardwareSectionCpu(@EndpointParam URI vmURI); - - /** - * @see VAppClient#modifyVirtualHardwareSectionCpu(URI, ResourceAllocationSettingData) - */ - @PUT - @Path("/virtualHardwareSection/cpu") - @Produces(OVF_RASD_ITEM) - @Consumes(TASK) - @JAXBResponseParser - ListenableFuture modifyVirtualHardwareSectionCpu(@EndpointParam URI vmURI, - @BinderParam(BindToXMLPayload.class) RasdItem rasd); - - /** - * @see VAppClient#getVirtualHardwareSectionDisks(URI) - */ - @GET - @Path("/virtualHardwareSection/disks") - @Consumes - @JAXBResponseParser - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getVirtualHardwareSectionDisks(@EndpointParam URI vmURI); - - /** - * @see VAppClient#modifyVirtualHardwareSectionDisks(URI, RasdItemsList) - */ - @PUT - @Path("/virtualHardwareSection/disks") - @Produces(OVF_RASD_ITEMS_LIST) - @Consumes(TASK) - @JAXBResponseParser - ListenableFuture modifyVirtualHardwareSectionDisks(@EndpointParam URI vmURI, - @BinderParam(BindToXMLPayload.class) RasdItemsList rasdItemsList); - - /** - * @see VAppClient#getVirtualHardwareSectionMedia(URI) - */ - @GET - @Path("/virtualHardwareSection/media") - @Consumes - @JAXBResponseParser - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getVirtualHardwareSectionMedia(@EndpointParam URI vmURI); - - /** - * @see VAppClient#getVirtualHardwareSectionMemory(URI) - */ - @GET - @Path("/virtualHardwareSection/memory") - @Consumes - @JAXBResponseParser - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getVirtualHardwareSectionMemory(@EndpointParam URI vmURI); - - /** - * @see VAppClient#modifyVirtualHardwareSectionMemory(URI, ResourceAllocationSettingData) - */ - @PUT - @Path("/virtualHardwareSection/memory") - @Produces(OVF_RASD_ITEM) - @Consumes(TASK) - @JAXBResponseParser - ListenableFuture modifyVirtualHardwareSectionMemory(@EndpointParam URI vmURI, - @BinderParam(BindToXMLPayload.class) RasdItem rasd); - - /** - * @see VAppClient#getVirtualHardwareSectionNetworkCards(URI) - */ - @GET - @Path("/virtualHardwareSection/networkCards") - @Consumes - @JAXBResponseParser - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getVirtualHardwareSectionNetworkCards(@EndpointParam URI vmURI); - - /** - * @see VAppClient#modifyVirtualHardwareSectionNetworkCards(URI, RasdItemsList) - */ - @PUT - @Path("/virtualHardwareSection/networkCards") - @Produces(OVF_RASD_ITEMS_LIST) - @Consumes(TASK) - @JAXBResponseParser - ListenableFuture modifyVirtualHardwareSectionNetworkCards(@EndpointParam URI vmURI, - @BinderParam(BindToXMLPayload.class) RasdItemsList rasdItemsList); - - /** - * @see VAppClient#getVirtualHardwareSectionSerialPorts(URI) - */ - @GET - @Path("/virtualHardwareSection/serialPorts") - @Consumes - @JAXBResponseParser - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getVirtualHardwareSectionSerialPorts(@EndpointParam URI vmURI); - - /** - * @see VAppClient#modifyVirtualHardwareSectionSerialPorts(URI, RasdItemsList) - */ - @PUT - @Path("/virtualHardwareSection/serialPorts") - @Produces(OVF_RASD_ITEMS_LIST) - @Consumes(TASK) - @JAXBResponseParser - ListenableFuture modifyVirtualHardwareSectionSerialPorts(@EndpointParam URI vmURI, - @BinderParam(BindToXMLPayload.class) RasdItemsList rasdItemsList); - - /** - * @return asynchronous access to {@link Metadata} features + * Asynchronous access to {@link VApp} {@link Metadata} features */ @Delegate MetadataAsyncClient.Writeable getMetadataClient(); - } diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/VAppClient.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/VAppClient.java index f8dc431db4..431eb5583c 100644 --- a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/VAppClient.java +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/VAppClient.java @@ -27,26 +27,14 @@ import org.jclouds.dmtf.ovf.StartupSection; import org.jclouds.rest.annotations.Delegate; import org.jclouds.vcloud.director.v1_5.domain.Owner; import org.jclouds.vcloud.director.v1_5.domain.ProductSectionList; -import org.jclouds.vcloud.director.v1_5.domain.RasdItemsList; -import org.jclouds.vcloud.director.v1_5.domain.ScreenTicket; import org.jclouds.vcloud.director.v1_5.domain.Task; import org.jclouds.vcloud.director.v1_5.domain.VApp; -import org.jclouds.vcloud.director.v1_5.domain.VmPendingQuestion; -import org.jclouds.vcloud.director.v1_5.domain.VmQuestionAnswer; -import org.jclouds.vcloud.director.v1_5.domain.dmtf.RasdItem; import org.jclouds.vcloud.director.v1_5.domain.params.ControlAccessParams; import org.jclouds.vcloud.director.v1_5.domain.params.DeployVAppParams; -import org.jclouds.vcloud.director.v1_5.domain.params.MediaInsertOrEjectParams; import org.jclouds.vcloud.director.v1_5.domain.params.RecomposeVAppParams; -import org.jclouds.vcloud.director.v1_5.domain.params.RelocateParams; import org.jclouds.vcloud.director.v1_5.domain.params.UndeployVAppParams; -import org.jclouds.vcloud.director.v1_5.domain.section.GuestCustomizationSection; import org.jclouds.vcloud.director.v1_5.domain.section.LeaseSettingsSection; import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConfigSection; -import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConnectionSection; -import org.jclouds.vcloud.director.v1_5.domain.section.OperatingSystemSection; -import org.jclouds.vcloud.director.v1_5.domain.section.RuntimeInfoSection; -import org.jclouds.vcloud.director.v1_5.domain.section.VirtualHardwareSection; /** * Provides synchronous access to {@link VApp} objects. @@ -59,9 +47,9 @@ import org.jclouds.vcloud.director.v1_5.domain.section.VirtualHardwareSection; public interface VAppClient { /** - * Retrieves a vApp/VM. + * Retrieves a {@link VApp}. * - * The vApp/VM could be in one of these statuses: + * The {@link VApp} could be in one of these statuses: *
    *
  • {@link org.jclouds.vcloud.director.v1_5.domain.ResourceEntityType.Status#FAILED_CREATION FAILED_CREATION(-1)} - * Transient entity state, e.g., model object is created but the corresponding VC backing does not @@ -101,7 +89,7 @@ public interface VAppClient { VApp getVApp(URI vAppURI); /** - * Modifies the name/description of a vApp/VM. + * Modifies the name/description of a {@link VApp}. * *
         * PUT /vApp/{id}
    @@ -112,7 +100,7 @@ public interface VAppClient {
        Task modifyVApp(URI vAppURI, VApp vApp);
     
        /**
    -    * Deletes a vApp/VM.
    +    * Deletes a {@link VApp}.
         *
         * 
         * DELETE /vApp/{id}
    @@ -123,18 +111,7 @@ public interface VAppClient {
        Task deleteVApp(URI vAppURI);
     
        /**
    -    * Consolidates a vm.
    -    *
    -    * 
    -    * POST /vApp/{id}/action/consolidate
    -    * 
    - * - * @since 1.5 - */ - Task consolidateVm(URI vAppURI); - - /** - * Modifies the control access of a vApp. + * Modifies the control access of a {@link VApp}. * *
         * POST /vApp/{id}/action/controlAccess
    @@ -145,7 +122,7 @@ public interface VAppClient {
        ControlAccessParams modifyControlAccess(URI vAppURI, ControlAccessParams params);
     
        /**
    -    * Deploys a vApp/VM.
    +    * Deploys a {@link VApp}.
         *
         * Deployment means allocation of all resource for a vApp/VM like CPU and memory
         * from a vDC resource pool. Deploying a vApp automatically deploys all of the
    @@ -162,7 +139,7 @@ public interface VAppClient {
        Task deploy(URI vAppURI, DeployVAppParams params);
     
        /**
    -    * Discard suspended state of a vApp/VM.
    +    * Discard suspended state of a {@link VApp}.
         *
         * Discarding suspended state of a vApp automatically discarded suspended
         * states of all of the virtual machines it contains.
    @@ -176,7 +153,7 @@ public interface VAppClient {
        Task discardSuspendedState(URI vAppURI);
     
        /**
    -    * Place the vApp into maintenance mode.
    +    * Place the {@link VApp} into maintenance mode.
         *
         * While in maintenance mode, a system admin can operate on the vApp as
         * usual, but end users are restricted to read-only operations. Any
    @@ -192,7 +169,7 @@ public interface VAppClient {
        void enterMaintenanceMode(URI vAppURI);
     
        /**
    -    * Take the vApp out of maintenance mode.
    +    * Take the {@link VApp} out of maintenance mode.
         *
         * 
         * POST /vApp/{id}/action/exitMaintenanceMode
    @@ -203,20 +180,7 @@ public interface VAppClient {
        void exitMaintenanceMode(URI vAppURI);
     
        /**
    -    * Installs VMware tools to the virtual machine.
    -    *
    -    * It should be running in order for them to be installed.
    -    *
    -    * 
    -    * POST /vApp/{id}/action/installVMwareTools
    -    * 
    - * - * @since 1.5 - */ - Task installVMwareTools(URI vAppURI); - - /** - * Recompose a vApp by removing its own VMs and/or adding new ones from other + * Recompose a {@link VApp} by removing its own VMs and/or adding new ones from other * vApps or vApp templates. * * To remove VMs you should put their references in elements. The way you add @@ -234,18 +198,7 @@ public interface VAppClient { Task recompose(URI vAppURI, RecomposeVAppParams params); /** - * Relocates a vm. - * - *
    -    * POST /vApp/{id}/action/relocate
    -    * 
    - * - * @since 1.5 - */ - Task relocateVm(URI vAppURI, RelocateParams params); - - /** - * Undeploy a vApp/VM. + * Undeploy a {@link VApp}. * * Undeployment means deallocation of all resources for a vApp/VM like CPU * and memory from a vDC resource pool. Undeploying a vApp automatically @@ -260,19 +213,7 @@ public interface VAppClient { Task undeploy(URI vAppURI, UndeployVAppParams params); /** - * Upgrade virtual hardware version of a VM to the highest supported virtual - * hardware version of provider vDC where the VM locates. - * - *
    -    * POST /vApp/{id}/action/upgradeHardwareVersion
    -    * 
    - * - * @since 1.5 - */ - Task upgradeHardwareVersion(URI vAppURI); - - /** - * Retrieves the control access information for a vApp. + * Retrieves the control access information for a {@link VApp}. * * The vApp could be shared to everyone or could be shared to specific user, * by modifying the control access values. @@ -286,7 +227,7 @@ public interface VAppClient { ControlAccessParams getControlAccess(URI vAppURI); /** - * Powers off a vApp/VM. + * Powers off a {@link VApp}. * * If the operation is used over a vApp then all VMs are powered off. This operation is allowed only when the vApp/VM is powered on. * @@ -299,7 +240,7 @@ public interface VAppClient { Task powerOff(URI vAppURI); /** - * Powers on a vApp/VM. + * Powers on a {@link VApp}. * * If the operation is used over a vApp then all VMs are powered on. This * operation is allowed only when the vApp/VM is powered off. @@ -313,7 +254,7 @@ public interface VAppClient { Task powerOn(URI vAppURI); /** - * Reboots a vApp/VM. + * Reboots a {@link VApp}. * * The vApp/VM should be started in order to reboot it. * @@ -326,7 +267,7 @@ public interface VAppClient { Task reboot(URI vAppURI); /** - * Resets a vApp/VM. + * Resets a {@link VApp}. * * If the operation is used over a vApp then all VMs are reset. This * operation is allowed only when the vApp/VM is powered on. @@ -340,7 +281,7 @@ public interface VAppClient { Task reset(URI vAppURI); /** - * Shutdowns a vApp/VM. + * Shuts down a {@link VApp}. * * If the operation is used over a vApp then all VMs are shutdown. This * operation is allowed only when the vApp/VM is powered on. @@ -354,7 +295,7 @@ public interface VAppClient { Task shutdown(URI vAppURI); /** - * Suspends a vApp/VM. + * Suspends a {@link VApp}. * * If the operation is used over a vApp then all VMs are suspended. This * operation is allowed only when the vApp/VM is powered on. @@ -368,29 +309,7 @@ public interface VAppClient { Task suspend(URI vAppURI); /** - * Retrieves the guest customization section of a VM. - * - *
    -    * GET /vApp/{id}/guestCustomizationSection
    -    * 
    - * - * @since 1.0 - */ - GuestCustomizationSection getGuestCustomizationSection(URI vmURI); - - /** - * Modifies the guest customization section of a VM. - * - *
    -    * PUT /vApp/{id}/guestCustomizationSection
    -    * 
    - * - * @since 1.0 - */ - Task modifyGuestCustomizationSection(URI vmURI, GuestCustomizationSection section); - - /** - * Retrieves the lease settings section of a vApp or vApp template. + * Retrieves the lease settings section of a {@link VApp}. * *
         * GET /vApp/{id}/leaseSettingsSection
    @@ -401,7 +320,7 @@ public interface VAppClient {
        LeaseSettingsSection getLeaseSettingsSection(URI vAppURI);
     
        /**
    -    * Modifies the lease settings section of a vApp or vApp template.
    +    * Modifies the lease settings section of a {@link VApp}.
         *
         * 
         * PUT /vApp/{id}/leaseSettingsSection
    @@ -412,29 +331,7 @@ public interface VAppClient {
        Task modifyLeaseSettingsSection(URI vAppURI, LeaseSettingsSection section);
     
        /**
    -    * Ejects a media from a VM.
    -    *
    -    * 
    -    * PUT /vApp/{id}/media/action/ejectMedia
    -    * 
    - * - * @since 0.9 - */ - Task ejectMedia(URI vmURI, MediaInsertOrEjectParams mediaParams); - - /** - * Inserts a media into a VM. - * - *
    -    * PUT /vApp/{id}/media/action/insertMedia
    -    * 
    - * - * @since 0.9 - */ - Task insertMedia(URI vmURI, MediaInsertOrEjectParams mediaParams); - - /** - * Retrieves the network config section of a vApp or vApp template. + * Retrieves the network config section of a {@link VApp}. * *
         * GET /vApp/{id}/networkConfigSection
    @@ -442,10 +339,10 @@ public interface VAppClient {
         *
         * @since 0.9
         */
    -   NetworkConfigSection getNetworkConfigSection(URI vmURI);
    +   NetworkConfigSection getNetworkConfigSection(URI vAppURI);
     
        /**
    -    * Modifies the network config section of a vApp.
    +    * Modifies the network config section of a {@link VApp}.
         *
         * 
         * PUT /vApp/{id}/networkConfigSection
    @@ -453,32 +350,10 @@ public interface VAppClient {
         *
         * @since 0.9
         */
    -   Task modifyNetworkConfigSection(URI vmURI, NetworkConfigSection section);
    +   Task modifyNetworkConfigSection(URI vAppURI, NetworkConfigSection section);
     
        /**
    -    * Retrieves the network connection section of a VM.
    -    *
    -    * 
    -    * GET /vApp/{id}/networkConnectionSection
    -    * 
    - * - * @since 0.9 - */ - NetworkConnectionSection getNetworkConnectionSection(URI vmURI); - - /** - * Modifies the network connection section of a VM. - * - *
    -    * PUT /vApp/{id}/networkConnectionSection
    -    * 
    - * - * @since 0.9 - */ - Task modifyNetworkConnectionSection(URI vmURI, NetworkConnectionSection section); - - /** - * Retrieves the network section of a vApp or vApp template. + * Retrieves the network section of a {@link VApp}. * *
         * GET /vApp/{id}/networkSection
    @@ -489,29 +364,7 @@ public interface VAppClient {
        NetworkSection getNetworkSection(URI vAppURI);
     
        /**
    -    * Retrieves the operating system section of a VM.
    -    *
    -    * 
    -    * GET /vApp/{id}/operatingSystemSection
    -    * 
    - * - * @since 0.9 - */ - OperatingSystemSection getOperatingSystemSection(URI vmURI); - - /** - * Modifies the operating system section of a VM. - * - *
    -    * PUT /vApp/{id}/operatingSystemSection
    -    * 
    - * - * @since 0.9 - */ - Task modifyOperatingSystemSection(URI vmURI, OperatingSystemSection section); - - /** - * Retrieves the owner of a vApp. + * Retrieves the owner of a {@link VApp}. * *
         * GET /vApp/{id}/owner
    @@ -522,7 +375,7 @@ public interface VAppClient {
        Owner getOwner(URI vAppURI);
     
        /**
    -    * Changes VApp owner.
    +    * Changes {@link VApp} owner.
         *
         * 
         * PUT /vApp/{id}/owner
    @@ -533,7 +386,7 @@ public interface VAppClient {
        void modifyOwner(URI vAppURI, Owner owner);
     
        /**
    -    * Retrieves VAppTemplate/VM product sections.
    +    * Retrieves {@link VApp} product sections.
         *
         * 
         * GET /vApp/{id}/productSections
    @@ -544,7 +397,7 @@ public interface VAppClient {
        ProductSectionList getProductSections(URI vAppURI);
     
        /**
    -    * Modifies the product section information of a vApp/VM.
    +    * Modifies the product section information of a {@link VApp}.
         *
         * 
         * PUT /vApp/{id}/productSections
    @@ -555,74 +408,7 @@ public interface VAppClient {
        Task modifyProductSections(URI vAppURI, ProductSectionList sectionList);
     
        /**
    -    * Retrieves a pending question for a VM.
    -    *
    -    * The user should answer to the question by operation {@link #answerQuestion(URI, VmQuestionAnswer)}.
    -    * Usually questions will be asked when the VM is powering on.
    -    *
    -    * 
    -    * GET /vApp/{id}/question
    -    * 
    - * - * @since 0.9 - */ - VmPendingQuestion getPendingQuestion(URI vAppURI); - - /** - * Answer on a pending question. - * - * The answer IDs of choice and question should match the ones returned from operation {@link #getPendingQuestion(URI)}. - * - *
    -    * POST /vApp/{id}/question/action/answer
    -    * 
    - * - * @since 0.9 - */ - void answerQuestion(URI vAppURI, VmQuestionAnswer answer); - - /** - * Retrieves the runtime info section of a VM. - * - *
    -    * GET /vApp/{id}/runtimeInfoSection
    -    * 
    - * - * @since 1.5 - */ - RuntimeInfoSection getRuntimeInfoSection(URI vmURI); - - /** - * Retrieves the thumbnail of the screen of a VM. - * - * The content type of the response may vary (e.g. {@code image/png}, {@code image/gif}). - * - *
    -    * GET /vApp/{id}/screen
    -    * 
    - * - * @since 0.9 - */ - byte[] getScreenImage(URI vAppURI); - - /** - * Retrieve a screen ticket for remote console connection to a VM. - * - * A screen ticket is a string that includes the virtual machine's IP address, its managed object reference, and a string - * that has been encoded as described in RFC 2396. Each VM element in a vApp includes a link where rel="screen:acquireTicket". - * You can use that link to request a screen ticket that you can use with the vmware-vmrc utility to open a VMware Remote - * Console for the virtual machine represented by that VM element. The vApp should be running to get a valid screen ticket. - * - *
    -    * GET /vApp/{id}/screen/action/acquireTicket
    -    * 
    - * - * @since 0.9 - */ - ScreenTicket getScreenTicket(URI vAppURI); - - /** - * Retrieves the startup section of a VApp. + * Retrieves the startup section of a {@link VApp}. * *
         * GET /vApp/{id}/startupSection
    @@ -633,7 +419,7 @@ public interface VAppClient {
        StartupSection getStartupSection(URI vAppURI);
     
        /**
    -    * Modifies the startup section of a VApp.
    +    * Modifies the startup section of a {@link VApp}.
         *
         * 
         * PUT /vApp/{id}/startupSection
    @@ -644,150 +430,7 @@ public interface VAppClient {
        Task modifyStartupSection(URI vAppURI, StartupSection section);
     
        /**
    -    * Retrieves the virtual hardware section of a VM.
    -    *
    -    * 
    -    * GET /vApp/{id}/virtualHardwareSection
    -    * 
    - * - * @since 0.9 - */ - VirtualHardwareSection getVirtualHardwareSection(URI vmURI); - - /** - * Modifies the virtual hardware section of a VM. - * - *
    -    * PUT /vApp/{id}/virtualHardwareSection
    -    * 
    - * - * @since 0.9 - */ - Task modifyVirtualHardwareSection(URI vmURI, VirtualHardwareSection section); - - /** - * Retrieves the CPU properties in virtual hardware section of a VM. - * - *
    -    * GET /vApp/{id}/virtualHardwareSection/cpu
    -    * 
    - * - * @since 0.9 - */ - RasdItem getVirtualHardwareSectionCpu(URI vmURI); - - /** - * Modifies the CPU properties in virtual hardware section of a VM. - * - *
    -    * PUT /vApp/{id}/virtualHardwareSection/cpu
    -    * 
    - * - * @since 0.9 - */ - Task modifyVirtualHardwareSectionCpu(URI vmURI, RasdItem rasd); - - /** - * Retrieves a list of ResourceAllocationSettingData items for disks from virtual hardware section of a VM. - * - *
    -    * GET /vApp/{id}/virtualHardwareSection/disks
    -    * 
    - * - * @since 0.9 - */ - RasdItemsList getVirtualHardwareSectionDisks(URI vmURI); - - /** - * Modifies the disks list in virtual hardware section of a VM. - * - *
    -    * PUT /vApp/{id}/virtualHardwareSection/disks
    -    * 
    - * - * @since 0.9 - */ - Task modifyVirtualHardwareSectionDisks(URI vmURI, RasdItemsList rasdItemsList); - - /** - * Retrieves the list of ResourceAllocationSettingData items that represents the floppies and CD/DVD drives in a VM. - * - *
    -    * GET /vApp/{id}/virtualHardwareSection/media
    -    * 
    - * - * @since 0.9 - */ - RasdItemsList getVirtualHardwareSectionMedia(URI vmURI); - - /** - * Retrieves the ResourceAllocationSettingData item that contains memory information from virtual hardware section of a VM. - * - *
    -    * GET /vApp/{id}/virtualHardwareSection/memory
    -    * 
    - * - * @since 0.9 - */ - RasdItem getVirtualHardwareSectionMemory(URI vmURI); - - /** - * Modifies the memory properties in virtual hardware section of a VM. - * - *
    -    * PUT /vApp/{id}/virtualHardwareSection/memory
    -    * 
    - * - * @since 0.9 - */ - Task modifyVirtualHardwareSectionMemory(URI vmURI, RasdItem rasd); - - /** - * Retrieves a list of ResourceAllocationSettingData items for network cards from virtual hardware section of a VM. - * - *
    -    * GET /vApp/{id}/virtualHardwareSection/networkCards
    -    * 
    - * - * @since 0.9 - */ - RasdItemsList getVirtualHardwareSectionNetworkCards(URI vmURI); - - /** - * Modifies the network cards list in virtual hardware section of a VM. - * - *
    -    * PUT /vApp/{id}/virtualHardwareSection/networkCards
    -    * 
    - * - * @since 0.9 - */ - Task modifyVirtualHardwareSectionNetworkCards(URI vmURI, RasdItemsList rasdItemsList); - - /** - * Retrieves a list of ResourceAllocationSettingData items for serial ports from virtual hardware section of a VM. - * - *
    -    * GET /vApp/{id}/virtualHardwareSection/serialPorts
    -    * 
    - * - * @since 1.5 - */ - RasdItemsList getVirtualHardwareSectionSerialPorts(URI vmURI); - - /** - * Modifies the serial ports list in virtual hardware section of a VM. - * - *
    -    * PUT /vApp/{id}/virtualHardwareSection/serialPorts
    -    * 
    - * - * @since 1.5 - */ - Task modifyVirtualHardwareSectionSerialPorts(URI vmURI, RasdItemsList rasdItemsList); - - /** - * @return synchronous access to {@link Metadata} features + * Synchronous access to {@link VApp} {@link Metadata} features. */ @Delegate MetadataClient.Writeable getMetadataClient(); diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/VmAsyncClient.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/VmAsyncClient.java new file mode 100644 index 0000000000..f5169f262f --- /dev/null +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/VmAsyncClient.java @@ -0,0 +1,533 @@ +/* + * 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.vcloud.director.v1_5.features; + +import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.ANY_IMAGE; +import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.DEPLOY_VAPP_PARAMS; +import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.GUEST_CUSTOMIZATION_SECTION; +import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.MEDIA_PARAMS; +import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.NETWORK_CONNECTION_SECTION; +import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.OPERATING_SYSTEM_SECTION; +import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.OVF_RASD_ITEM; +import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.OVF_RASD_ITEMS_LIST; +import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.PRODUCT_SECTION_LIST; +import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.RELOCATE_VM_PARAMS; +import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.TASK; +import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.UNDEPLOY_VAPP_PARAMS; +import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.VIRTUAL_HARDWARE_SECTION; +import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.VM; +import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.VM_PENDING_ANSWER; + +import java.net.URI; + +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.Produces; + +import org.jclouds.rest.annotations.BinderParam; +import org.jclouds.rest.annotations.Delegate; +import org.jclouds.rest.annotations.EndpointParam; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.JAXBResponseParser; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.ResponseParser; +import org.jclouds.rest.binders.BindToXMLPayload; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; +import org.jclouds.vcloud.director.v1_5.domain.ProductSectionList; +import org.jclouds.vcloud.director.v1_5.domain.RasdItemsList; +import org.jclouds.vcloud.director.v1_5.domain.ScreenTicket; +import org.jclouds.vcloud.director.v1_5.domain.Task; +import org.jclouds.vcloud.director.v1_5.domain.Vm; +import org.jclouds.vcloud.director.v1_5.domain.VmPendingQuestion; +import org.jclouds.vcloud.director.v1_5.domain.VmQuestionAnswer; +import org.jclouds.vcloud.director.v1_5.domain.dmtf.RasdItem; +import org.jclouds.vcloud.director.v1_5.domain.params.DeployVAppParams; +import org.jclouds.vcloud.director.v1_5.domain.params.MediaInsertOrEjectParams; +import org.jclouds.vcloud.director.v1_5.domain.params.RelocateParams; +import org.jclouds.vcloud.director.v1_5.domain.params.UndeployVAppParams; +import org.jclouds.vcloud.director.v1_5.domain.section.GuestCustomizationSection; +import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConnectionSection; +import org.jclouds.vcloud.director.v1_5.domain.section.OperatingSystemSection; +import org.jclouds.vcloud.director.v1_5.domain.section.RuntimeInfoSection; +import org.jclouds.vcloud.director.v1_5.domain.section.VirtualHardwareSection; +import org.jclouds.vcloud.director.v1_5.filters.AddVCloudAuthorizationToRequest; +import org.jclouds.vcloud.director.v1_5.functions.ReturnPayloadBytes; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * @author grkvlt@apache.org + * @see VmClient + */ +@RequestFilters(AddVCloudAuthorizationToRequest.class) +public interface VmAsyncClient { + + /** + * @see VmClient#getVm(URI) + */ + @GET + @Consumes(VM) + @JAXBResponseParser + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getVm(@EndpointParam URI vmURI); + + /** + * @see VmClient#modifyVm(URI, Vm) + */ + @PUT + @Produces(VM) + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture modifyVm(@EndpointParam URI vmURI, + @BinderParam(BindToXMLPayload.class) Vm vApp); + + /** + * @see VmClient#deleteVm(URI) + */ + @DELETE + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture deleteVm(@EndpointParam URI vmURI); + + /** + * @see VmClient#consolidateVm(URI) + */ + @POST + @Path("/action/consolidate") + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture consolidateVm(@EndpointParam URI vmURI); + + /** + * @see VmClient#deploy(URI, DeployVAppParams) + */ + @POST + @Path("/action/deploy") + @Produces(DEPLOY_VAPP_PARAMS) + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture deploy(@EndpointParam URI vmURI, + @BinderParam(BindToXMLPayload.class) DeployVAppParams params); + + /** + * @see VmClient#discardSuspendedState(URI) + */ + @POST + @Path("/action/discardSuspendedState") + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture discardSuspendedState(@EndpointParam URI vmURI); + + /** + * @see VmClient#installVMwareTools(URI) + */ + @POST + @Path("/action/installVMwareTools") + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture installVMwareTools(@EndpointParam URI vmURI); + + /** + * @see VmClient#relocateVm(URI, RelocateParams) + */ + @POST + @Path("/action/relocate") + @Produces(RELOCATE_VM_PARAMS) + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture relocateVm(@EndpointParam URI vmURI, + @BinderParam(BindToXMLPayload.class) RelocateParams params); + + /** + * @see VmClient#undeploy(URI, UndeployVAppParams) + */ + @POST + @Path("/action/undeploy") + @Produces(UNDEPLOY_VAPP_PARAMS) + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture undeploy(@EndpointParam URI vmURI, + @BinderParam(BindToXMLPayload.class) UndeployVAppParams params); + + /** + * @see VmClient#upgradeHardwareVersion(URI) + */ + @POST + @Path("/action/upgradeHardwareVersion") + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture upgradeHardwareVersion(@EndpointParam URI vmURI); + + /** + * @see VmClient#powerOff(URI) + */ + @POST + @Path("/power/action/powerOff") + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture powerOff(@EndpointParam URI vmURI); + + /** + * @see VmClient#powerOn(URI) + */ + @POST + @Path("/power/action/powerOn") + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture powerOn(@EndpointParam URI vmURI); + + /** + * @see VmClient#reboot(URI) + */ + @POST + @Path("/power/action/powerOff") + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture reboot(@EndpointParam URI vmURI); + + /** + * @see VmClient#reset(URI) + */ + @POST + @Path("/power/action/reset") + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture reset(@EndpointParam URI vmURI); + + /** + * @see VmClient#shutdown(URI) + */ + @POST + @Path("/power/action/shutdown") + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture shutdown(@EndpointParam URI vmURI); + + /** + * @see VmClient#suspend(URI) + */ + @POST + @Path("/power/action/suspend") + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture suspend(@EndpointParam URI vmURI); + + /** + * @see VmClient#getGuestCustomizationSection(URI) + */ + @GET + @Path("/guestCustomizationSection") + @Consumes + @JAXBResponseParser + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getGuestCustomizationSection(@EndpointParam URI vmURI); + + /** + * @see VmClient#modifyGuestCustomizationSection(URI, GuestCustomizationSection) + */ + @PUT + @Path("/guestCustomizationSection") + @Produces(GUEST_CUSTOMIZATION_SECTION) + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture modifyGuestCustomizationSection(@EndpointParam URI vmURI, + @BinderParam(BindToXMLPayload.class) GuestCustomizationSection section); + + /** + * @see VmClient#ejectMedia(URI, MediaInsertOrEjectParams) + */ + @POST + @Path("/media/action/ejectMedia") + @Produces(MEDIA_PARAMS) + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture ejectMedia(@EndpointParam URI vmURI, + @BinderParam(BindToXMLPayload.class) MediaInsertOrEjectParams mediaParams); + + /** + * @see VmClient#insertMedia(URI, MediaInsertOrEjectParams) + */ + @POST + @Path("/media/action/insertMedia") + @Produces(MEDIA_PARAMS) + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture insertMedia(@EndpointParam URI vmURI, + @BinderParam(BindToXMLPayload.class) MediaInsertOrEjectParams mediaParams); + + /** + * @see VmClient#getNetworkConnectionSection(URI) + */ + @GET + @Path("/networkConnectionSection") + @Consumes + @JAXBResponseParser + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getNetworkConnectionSection(@EndpointParam URI vmURI); + + /** + * @see VmClient#modifyNetworkConnectionSection(URI, NetworkConnectionSection) + */ + @PUT + @Path("/networkConnectionSection") + @Produces(NETWORK_CONNECTION_SECTION) + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture modifyNetworkConnectionSection(@EndpointParam URI vmURI, + @BinderParam(BindToXMLPayload.class) NetworkConnectionSection section); + + /** + * @see VmClient#getOperatingSystemSection(URI) + */ + @GET + @Path("/operatingSystemSection") + @Consumes + @JAXBResponseParser + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getOperatingSystemSection(@EndpointParam URI vmURI); + + /** + * @see VmClient#modifyOperatingSystemSection(URI, OperatingSystemSection) + */ + @PUT + @Path("/operatingSystemSection") + @Produces(OPERATING_SYSTEM_SECTION) + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture modifyOperatingSystemSection(@EndpointParam URI vmURI, + @BinderParam(BindToXMLPayload.class) OperatingSystemSection section); + + /** + * @see VmClient#getProductSections(URI) + */ + @GET + @Path("/productSections") + @Consumes + @JAXBResponseParser + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getProductSections(@EndpointParam URI vmURI); + + /** + * @see VmClient#modifyProductSections(URI, ProductSectionList) + */ + @PUT + @Path("/productSections") + @Produces(PRODUCT_SECTION_LIST) + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture modifyProductSections(@EndpointParam URI vmURI, + @BinderParam(BindToXMLPayload.class) ProductSectionList sectionList); + + /** + * @see VmClient#getPendingQuestion(URI) + */ + @GET + @Path("/question") + @Consumes + @JAXBResponseParser + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getPendingQuestion(@EndpointParam URI vmURI); + + /** + * @see VmClient#answerQuestion(URI, VmQuestionAnswer) + */ + @POST + @Path("/question/action/answer") + @Produces(VM_PENDING_ANSWER) + @Consumes + @JAXBResponseParser + ListenableFuture answerQuestion(@EndpointParam URI vmURI, + @BinderParam(BindToXMLPayload.class) VmQuestionAnswer answer); + + /** + * @see VmClient#getRuntimeInfoSection(URI) + */ + @GET + @Path("/runtimeInfoSection") + @Consumes + @JAXBResponseParser + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getRuntimeInfoSection(@EndpointParam URI vmURI); + + /** + * @see VmClient#getScreenImage(URI) + */ + @GET + @Path("/screen") + @Consumes(ANY_IMAGE) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + @ResponseParser(ReturnPayloadBytes.class) + ListenableFuture getScreenImage(@EndpointParam URI vmURI); + + /** + * @see VmClient#getScreenTicket(URI) + */ + @POST + @Path("/screen/action/acquireTicket") + @Consumes + @JAXBResponseParser + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getScreenTicket(@EndpointParam URI vmURI); + + /** + * @see VmClient#getVirtualHardwareSection(URI) + */ + @GET + @Path("/virtualHardwareSection") + @Consumes + @JAXBResponseParser + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getVirtualHardwareSection(@EndpointParam URI vmURI); + + /** + * @see VmClient#modifyVirtualHardwareSection(URI, VirtualHardwareSection) + */ + @PUT + @Path("/virtualHardwareSection") + @Produces(VIRTUAL_HARDWARE_SECTION) + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture modifyVirtualHardwareSection(@EndpointParam URI vmURI, + @BinderParam(BindToXMLPayload.class) VirtualHardwareSection section); + + /** + * @see VmClient#getVirtualHardwareSectionCpu(URI) + */ + @GET + @Path("/virtualHardwareSection/cpu") + @Consumes + @JAXBResponseParser + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getVirtualHardwareSectionCpu(@EndpointParam URI vmURI); + + /** + * @see VmClient#modifyVirtualHardwareSectionCpu(URI, ResourceAllocationSettingData) + */ + @PUT + @Path("/virtualHardwareSection/cpu") + @Produces(OVF_RASD_ITEM) + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture modifyVirtualHardwareSectionCpu(@EndpointParam URI vmURI, + @BinderParam(BindToXMLPayload.class) RasdItem rasd); + + /** + * @see VmClient#getVirtualHardwareSectionDisks(URI) + */ + @GET + @Path("/virtualHardwareSection/disks") + @Consumes + @JAXBResponseParser + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getVirtualHardwareSectionDisks(@EndpointParam URI vmURI); + + /** + * @see VmClient#modifyVirtualHardwareSectionDisks(URI, RasdItemsList) + */ + @PUT + @Path("/virtualHardwareSection/disks") + @Produces(OVF_RASD_ITEMS_LIST) + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture modifyVirtualHardwareSectionDisks(@EndpointParam URI vmURI, + @BinderParam(BindToXMLPayload.class) RasdItemsList rasdItemsList); + + /** + * @see VmClient#getVirtualHardwareSectionMedia(URI) + */ + @GET + @Path("/virtualHardwareSection/media") + @Consumes + @JAXBResponseParser + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getVirtualHardwareSectionMedia(@EndpointParam URI vmURI); + + /** + * @see VmClient#getVirtualHardwareSectionMemory(URI) + */ + @GET + @Path("/virtualHardwareSection/memory") + @Consumes + @JAXBResponseParser + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getVirtualHardwareSectionMemory(@EndpointParam URI vmURI); + + /** + * @see VmClient#modifyVirtualHardwareSectionMemory(URI, ResourceAllocationSettingData) + */ + @PUT + @Path("/virtualHardwareSection/memory") + @Produces(OVF_RASD_ITEM) + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture modifyVirtualHardwareSectionMemory(@EndpointParam URI vmURI, + @BinderParam(BindToXMLPayload.class) RasdItem rasd); + + /** + * @see VmClient#getVirtualHardwareSectionNetworkCards(URI) + */ + @GET + @Path("/virtualHardwareSection/networkCards") + @Consumes + @JAXBResponseParser + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getVirtualHardwareSectionNetworkCards(@EndpointParam URI vmURI); + + /** + * @see VmClient#modifyVirtualHardwareSectionNetworkCards(URI, RasdItemsList) + */ + @PUT + @Path("/virtualHardwareSection/networkCards") + @Produces(OVF_RASD_ITEMS_LIST) + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture modifyVirtualHardwareSectionNetworkCards(@EndpointParam URI vmURI, + @BinderParam(BindToXMLPayload.class) RasdItemsList rasdItemsList); + + /** + * @see VmClient#getVirtualHardwareSectionSerialPorts(URI) + */ + @GET + @Path("/virtualHardwareSection/serialPorts") + @Consumes + @JAXBResponseParser + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getVirtualHardwareSectionSerialPorts(@EndpointParam URI vmURI); + + /** + * @see VmClient#modifyVirtualHardwareSectionSerialPorts(URI, RasdItemsList) + */ + @PUT + @Path("/virtualHardwareSection/serialPorts") + @Produces(OVF_RASD_ITEMS_LIST) + @Consumes(TASK) + @JAXBResponseParser + ListenableFuture modifyVirtualHardwareSectionSerialPorts(@EndpointParam URI vmURI, + @BinderParam(BindToXMLPayload.class) RasdItemsList rasdItemsList); + + /** + * Asynchronous access to {@Vm} {@link Metadata} features. + */ + @Delegate + MetadataAsyncClient.Writeable getMetadataClient(); +} diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/VmClient.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/VmClient.java new file mode 100644 index 0000000000..e2c9de904a --- /dev/null +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/features/VmClient.java @@ -0,0 +1,517 @@ +/* + * 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.vcloud.director.v1_5.features; + +import java.net.URI; +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.rest.annotations.Delegate; +import org.jclouds.vcloud.director.v1_5.domain.ProductSectionList; +import org.jclouds.vcloud.director.v1_5.domain.RasdItemsList; +import org.jclouds.vcloud.director.v1_5.domain.ScreenTicket; +import org.jclouds.vcloud.director.v1_5.domain.Task; +import org.jclouds.vcloud.director.v1_5.domain.Vm; +import org.jclouds.vcloud.director.v1_5.domain.VmPendingQuestion; +import org.jclouds.vcloud.director.v1_5.domain.VmQuestionAnswer; +import org.jclouds.vcloud.director.v1_5.domain.dmtf.RasdItem; +import org.jclouds.vcloud.director.v1_5.domain.params.DeployVAppParams; +import org.jclouds.vcloud.director.v1_5.domain.params.MediaInsertOrEjectParams; +import org.jclouds.vcloud.director.v1_5.domain.params.RelocateParams; +import org.jclouds.vcloud.director.v1_5.domain.params.UndeployVAppParams; +import org.jclouds.vcloud.director.v1_5.domain.section.GuestCustomizationSection; +import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConnectionSection; +import org.jclouds.vcloud.director.v1_5.domain.section.OperatingSystemSection; +import org.jclouds.vcloud.director.v1_5.domain.section.RuntimeInfoSection; +import org.jclouds.vcloud.director.v1_5.domain.section.VirtualHardwareSection; + +/** + * Provides synchronous access to {@link Vm} objects. + * + * @author grkvlt@apache.org + * @see VmAsyncClient + * @version 1.5 + */ +@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS) +public interface VmClient { + + /** + * Retrieves a {@link Vm}. + * + * @since 0.9 + * @see VAppClient#getVApp(URI) + */ + Vm getVm(URI vmURI); + + /** + * Modifies the name/description of a {@link Vm}. + * + * @since 0.9 + * @see VAppClient#modifyVApp(URI, VApp) + */ + Task modifyVm(URI vmURI, Vm vm); + + /** + * Deletes a {@link Vm}. + * + * @since 0.9 + * @see VAppClient#deleteVApp(URI) + */ + Task deleteVm(URI vmURI); + + /** + * Consolidates a {@link Vm}. + * + *
    +    * POST /vApp/{id}/action/consolidate
    +    * 
    + * + * @since 1.5 + */ + Task consolidateVm(URI vmURI); + + /** + * Deploys a {@link Vm}. + * + * @since 0.9 + * @see VAppClient#deploy(URI, DeployVAppParams) + */ + Task deploy(URI vmURI, DeployVAppParams params); + + /** + * Discard suspended state of a {@link Vm}. + * + * @since 0.9 + * @see VAppClient#discardSuspendedState(URI) + */ + Task discardSuspendedState(URI vmURI); + + /** + * Installs VMware tools to the virtual machine. + * + * It should be running in order for them to be installed. + * + *
    +    * POST /vApp/{id}/action/installVMwareTools
    +    * 
    + * + * @since 1.5 + */ + Task installVMwareTools(URI vmURI); + + /** + * Relocates a {@link Vm}. + * + *
    +    * POST /vApp/{id}/action/relocate
    +    * 
    + * + * @since 1.5 + */ + Task relocateVm(URI vmURI, RelocateParams params); + + /** + * Undeploy a {@link Vm}. + * + * @since 0.9 + * @see VAppClient#undeploy(URI, UndeployVAppParams) + */ + Task undeploy(URI vmURI, UndeployVAppParams params); + + /** + * Upgrade virtual hardware version of a VM to the highest supported virtual + * hardware version of provider vDC where the VM locates. + * + *
    +    * POST /vApp/{id}/action/upgradeHardwareVersion
    +    * 
    + * + * @since 1.5 + */ + Task upgradeHardwareVersion(URI vmURI); + + /** + * Powers off a {@link Vm}. + * + * @since 0.9 + * @see VAppClient#powerOff(URI) + */ + Task powerOff(URI vmURI); + + /** + * Powers on a {@link Vm}. + * + * @since 0.9 + * @see VAppClient#powerOn(URI) + */ + Task powerOn(URI vmURI); + + /** + * Reboots a {@link Vm}. + * + * @since 0.9 + * @see VAppClient#reboot(URI) + */ + Task reboot(URI vmURI); + + /** + * Resets a {@link Vm}. + * + * @since 0.9 + * @see VAppClient#reset(URI) + */ + Task reset(URI vmURI); + + /** + * Shuts down a {@link Vm}. + * + * @since 0.9 + * @see VAppClient#shutdown(URI) + */ + Task shutdown(URI vmURI); + + /** + * Suspends a {@link Vm}. + * + * @since 0.9 + * @see VAppClient#suspend(URI) + */ + Task suspend(URI vmURI); + + /** + * Retrieves the guest customization section of a {@link Vm}. + * + *
    +    * GET /vApp/{id}/guestCustomizationSection
    +    * 
    + * + * @since 1.0 + * @see VAppClient# + */ + GuestCustomizationSection getGuestCustomizationSection(URI vmURI); + + /** + * Modifies the guest customization section of a {@link Vm}. + * + *
    +    * PUT /vApp/{id}/guestCustomizationSection
    +    * 
    + * + * @since 1.0 + */ + Task modifyGuestCustomizationSection(URI vmURI, GuestCustomizationSection section); + + /** + * Ejects media from a {@link Vm}. + * + *
    +    * PUT /vApp/{id}/media/action/ejectMedia
    +    * 
    + * + * @since 0.9 + */ + Task ejectMedia(URI vmURI, MediaInsertOrEjectParams mediaParams); + + /** + * Insert media into a {@link Vm}. + * + *
    +    * PUT /vApp/{id}/media/action/insertMedia
    +    * 
    + * + * @since 0.9 + */ + Task insertMedia(URI vmURI, MediaInsertOrEjectParams mediaParams); + + /** + * Retrieves the network connection section of a {@link Vm}. + * + *
    +    * GET /vApp/{id}/networkConnectionSection
    +    * 
    + * + * @since 0.9 + */ + NetworkConnectionSection getNetworkConnectionSection(URI vmURI); + + /** + * Modifies the network connection section of a {@link Vm}. + * + *
    +    * PUT /vApp/{id}/networkConnectionSection
    +    * 
    + * + * @since 0.9 + */ + Task modifyNetworkConnectionSection(URI vmURI, NetworkConnectionSection section); + + /** + * Retrieves the operating system section of a {@link Vm}. + * + *
    +    * GET /vApp/{id}/operatingSystemSection
    +    * 
    + * + * @since 0.9 + */ + OperatingSystemSection getOperatingSystemSection(URI vmURI); + + /** + * Modifies the operating system section of a {@link Vm}. + * + *
    +    * PUT /vApp/{id}/operatingSystemSection
    +    * 
    + * + * @since 0.9 + */ + Task modifyOperatingSystemSection(URI vmURI, OperatingSystemSection section); + + /** + * Retrieves {@link Vm} product sections. + * + * @since 1.5 + * @see VAppClient#getProductSections(URI) + */ + ProductSectionList getProductSections(URI vmURI); + + /** + * Modifies the product section information of a {@link Vm}. + * + * @since 1.5 + * @see VAppClient#modifyProductSections(URI, ProductSectionList) + */ + Task modifyProductSections(URI vmURI, ProductSectionList sectionList); + + /** + * Retrieves a pending question for a {@link Vm}. + * + * The user should answer to the question by operation {@link #answerQuestion(URI, VmQuestionAnswer)}. + * Usually questions will be asked when the VM is powering on. + * + *
    +    * GET /vApp/{id}/question
    +    * 
    + * + * @since 0.9 + */ + VmPendingQuestion getPendingQuestion(URI vmURI); + + /** + * Answer a pending question on a {@link Vm}. + * + * The answer IDs of choice and question should match the ones returned from operation {@link #getPendingQuestion(URI)}. + * + *
    +    * POST /vApp/{id}/question/action/answer
    +    * 
    + * + * @since 0.9 + */ + void answerQuestion(URI vmURI, VmQuestionAnswer answer); + + /** + * Retrieves the runtime info section of a {@link Vm}. + * + *
    +    * GET /vApp/{id}/runtimeInfoSection
    +    * 
    + * + * @since 1.5 + */ + RuntimeInfoSection getRuntimeInfoSection(URI vmURI); + + /** + * Retrieves the thumbnail of the screen of a {@link Vm}. + * + * The content type of the response may vary (e.g. {@code image/png}, {@code image/gif}). + * + *
    +    * GET /vApp/{id}/screen
    +    * 
    + * + * @since 0.9 + */ + byte[] getScreenImage(URI vmURI); + + /** + * Retrieve a screen ticket for remote console connection to a {@link Vm}. + * + * A screen ticket is a string that includes the virtual machine's IP address, its managed object reference, and a string + * that has been encoded as described in RFC 2396. Each VM element in a vApp includes a link where rel="screen:acquireTicket". + * You can use that link to request a screen ticket that you can use with the vmware-vmrc utility to open a VMware Remote + * Console for the virtual machine represented by that VM element. The vApp should be running to get a valid screen ticket. + * + *
    +    * GET /vApp/{id}/screen/action/acquireTicket
    +    * 
    + * + * @since 0.9 + */ + ScreenTicket getScreenTicket(URI vmURI); + + /** + * Retrieves the virtual hardware section of a {@link Vm}. + * + *
    +    * GET /vApp/{id}/virtualHardwareSection
    +    * 
    + * + * @since 0.9 + */ + VirtualHardwareSection getVirtualHardwareSection(URI vmURI); + + /** + * Modifies the virtual hardware section of a {@link Vm}. + * + *
    +    * PUT /vApp/{id}/virtualHardwareSection
    +    * 
    + * + * @since 0.9 + */ + Task modifyVirtualHardwareSection(URI vmURI, VirtualHardwareSection section); + + /** + * Retrieves the CPU properties in virtual hardware section of a {@link Vm}. + * + *
    +    * GET /vApp/{id}/virtualHardwareSection/cpu
    +    * 
    + * + * @since 0.9 + */ + RasdItem getVirtualHardwareSectionCpu(URI vmURI); + + /** + * Modifies the CPU properties in virtual hardware section of a {@link Vm}. + * + *
    +    * PUT /vApp/{id}/virtualHardwareSection/cpu
    +    * 
    + * + * @since 0.9 + */ + Task modifyVirtualHardwareSectionCpu(URI vmURI, RasdItem rasd); + + /** + * Retrieves a list of items for disks from virtual hardware section of a {@link Vm}. + * + *
    +    * GET /vApp/{id}/virtualHardwareSection/disks
    +    * 
    + * + * @since 0.9 + */ + RasdItemsList getVirtualHardwareSectionDisks(URI vmURI); + + /** + * Modifies the disks list in virtual hardware section of a {@link Vm}. + * + *
    +    * PUT /vApp/{id}/virtualHardwareSection/disks
    +    * 
    + * + * @since 0.9 + */ + Task modifyVirtualHardwareSectionDisks(URI vmURI, RasdItemsList rasdItemsList); + + /** + * Retrieves the list of items that represents the floppies and CD/DVD drives in a {@link Vm}. + * + *
    +    * GET /vApp/{id}/virtualHardwareSection/media
    +    * 
    + * + * @since 0.9 + */ + RasdItemsList getVirtualHardwareSectionMedia(URI vmURI); + + /** + * Retrieves the item that contains memory information from virtual hardware section of a {@link Vm}. + * + *
    +    * GET /vApp/{id}/virtualHardwareSection/memory
    +    * 
    + * + * @since 0.9 + */ + RasdItem getVirtualHardwareSectionMemory(URI vmURI); + + /** + * Modifies the memory properties in virtual hardware section of a {@link Vm}. + * + *
    +    * PUT /vApp/{id}/virtualHardwareSection/memory
    +    * 
    + * + * @since 0.9 + */ + Task modifyVirtualHardwareSectionMemory(URI vmURI, RasdItem rasd); + + /** + * Retrieves a list of items for network cards from virtual hardware section of a {@link Vm}. + * + *
    +    * GET /vApp/{id}/virtualHardwareSection/networkCards
    +    * 
    + * + * @since 0.9 + */ + RasdItemsList getVirtualHardwareSectionNetworkCards(URI vmURI); + + /** + * Modifies the network cards list in virtual hardware section of a {@link Vm}. + * + *
    +    * PUT /vApp/{id}/virtualHardwareSection/networkCards
    +    * 
    + * + * @since 0.9 + */ + Task modifyVirtualHardwareSectionNetworkCards(URI vmURI, RasdItemsList rasdItemsList); + + /** + * Retrieves a list of items for serial ports from virtual hardware section of a {@link Vm}. + * + *
    +    * GET /vApp/{id}/virtualHardwareSection/serialPorts
    +    * 
    + * + * @since 1.5 + */ + RasdItemsList getVirtualHardwareSectionSerialPorts(URI vmURI); + + /** + * Modifies the serial ports list in virtual hardware section of a {@link Vm}. + * + *
    +    * PUT /vApp/{id}/virtualHardwareSection/serialPorts
    +    * 
    + * + * @since 1.5 + */ + Task modifyVirtualHardwareSectionSerialPorts(URI vmURI, RasdItemsList rasdItemsList); + + /** + * Synchronous access to {@link Vm} {@link Metadata} features. + */ + @Delegate + MetadataClient.Writeable getMetadataClient(); +} diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/functions/SectionForVApp.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/functions/SectionForVApp.java new file mode 100644 index 0000000000..bed3ccb55c --- /dev/null +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/functions/SectionForVApp.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.vcloud.director.v1_5.functions; + +import org.jclouds.dmtf.ovf.SectionType; +import org.jclouds.vcloud.director.v1_5.domain.AbstractVAppType; + +import com.google.common.base.Function; + +/** + * @author danikov + */ +public class SectionForVApp implements Function { + + private final Class sectionType; + + public SectionForVApp(Class sectionType) { + this.sectionType = sectionType; + } + + @SuppressWarnings("unchecked") + @Override + public S apply(AbstractVAppType from) { + for (SectionType section : from.getSections()) { + if (sectionType.isAssignableFrom(section.getClass())) { + return (S)section; + } + } + return null; + } +} \ No newline at end of file diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/functions/SectionForVAppTemplate.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/functions/SectionForVAppTemplate.java index 2efcd27ee4..e33051b65f 100644 --- a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/functions/SectionForVAppTemplate.java +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/functions/SectionForVAppTemplate.java @@ -18,8 +18,6 @@ */ package org.jclouds.vcloud.director.v1_5.functions; -import java.util.Set; - import javax.inject.Inject; import javax.inject.Singleton; @@ -27,7 +25,6 @@ import org.jclouds.dmtf.ovf.SectionType; import org.jclouds.vcloud.director.v1_5.domain.VAppTemplate; import com.google.common.base.Function; -import com.google.common.collect.Sets; /** * @author danikov @@ -45,7 +42,6 @@ public class SectionForVAppTemplate implements Function sections = Sets.newLinkedHashSet(); for (SectionType section : from.getSections()) { if (sectionType.isAssignableFrom(section.getClass())) { return (S)section; diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/predicates/LinkPredicates.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/predicates/LinkPredicates.java index 7cfe5119e9..91187b49ca 100644 --- a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/predicates/LinkPredicates.java +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/predicates/LinkPredicates.java @@ -20,9 +20,13 @@ package org.jclouds.vcloud.director.v1_5.predicates; import static com.google.common.base.Preconditions.checkNotNull; +import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType; import org.jclouds.vcloud.director.v1_5.domain.Link; import com.google.common.base.Predicate; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; /** * Predicates handy when working with Links @@ -31,7 +35,7 @@ import com.google.common.base.Predicate; */ public class LinkPredicates { - + /** * matches links of the given relation * @@ -46,32 +50,57 @@ public class LinkPredicates { /** @see #relEquals(String) */ public static Predicate relEquals(final Link.Rel rel) { - checkNotNull(rel, "rel must be defined"); - - return new Predicate() { - @Override - public boolean apply(Link link) { - return rel == link.getRel(); - } - - @Override - public String toString() { - return "relEquals(" + rel.value() + ")"; - } - }; + return LINK_REL_SELECTORS.apply(checkNotNull(rel, "rel must be defined")); } + + private static final LoadingCache> LINK_REL_SELECTORS = CacheBuilder.newBuilder() + .maximumSize(Link.Rel.ALL.size()) + .build( + new CacheLoader>() { + public Predicate load(final Link.Rel rel) { + return new Predicate() { + @Override + public boolean apply(Link link) { + return rel == link.getRel(); + } + + @Override + public String toString() { + return "relEquals(" + rel.value() + ")"; + } + }; + } + }); /** * @see ReferenceTypePredicates#nameEquals */ public static Predicate nameEquals(String name) { - return ReferencePredicates.nameEquals(name); + return MEDIA_NAME_SELECTORS.apply(name); } + + private static final LoadingCache> MEDIA_NAME_SELECTORS = CacheBuilder.newBuilder() + .maximumSize(VCloudDirectorMediaType.ALL.size()) + .build( + new CacheLoader>() { + public Predicate load(String key) { + return ReferencePredicates.nameEquals(key); + } + }); /** * @see ReferenceTypePredicates#typeEquals */ public static Predicate typeEquals(String type) { - return ReferencePredicates.typeEquals(type); + return MEDIA_TYPE_SELECTORS.apply(type); } + + private static final LoadingCache> MEDIA_TYPE_SELECTORS = CacheBuilder.newBuilder() + .maximumSize(VCloudDirectorMediaType.ALL.size()) + .build( + new CacheLoader>() { + public Predicate load(String key) { + return ReferencePredicates.typeEquals(key); + } + }); } diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/user/VCloudDirectorAsyncClient.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/user/VCloudDirectorAsyncClient.java index 90b848b5e9..60cd65bfde 100644 --- a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/user/VCloudDirectorAsyncClient.java +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/user/VCloudDirectorAsyncClient.java @@ -29,6 +29,7 @@ import org.jclouds.vcloud.director.v1_5.features.UploadAsyncClient; import org.jclouds.vcloud.director.v1_5.features.VAppAsyncClient; import org.jclouds.vcloud.director.v1_5.features.VAppTemplateAsyncClient; import org.jclouds.vcloud.director.v1_5.features.VdcAsyncClient; +import org.jclouds.vcloud.director.v1_5.features.VmAsyncClient; import com.google.inject.Provides; @@ -105,4 +106,10 @@ public interface VCloudDirectorAsyncClient { */ @Delegate VAppTemplateAsyncClient getVAppTemplateClient(); + + /** + * @return asynchronous access to {@link Vm} features + */ + @Delegate + VmAsyncClient getVmClient(); } diff --git a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/user/VCloudDirectorClient.java b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/user/VCloudDirectorClient.java index fda7a3686e..cf0c5803bc 100644 --- a/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/user/VCloudDirectorClient.java +++ b/labs/vcloud-director/src/main/java/org/jclouds/vcloud/director/v1_5/user/VCloudDirectorClient.java @@ -33,6 +33,7 @@ import org.jclouds.vcloud.director.v1_5.features.UploadClient; import org.jclouds.vcloud.director.v1_5.features.VAppClient; import org.jclouds.vcloud.director.v1_5.features.VAppTemplateClient; import org.jclouds.vcloud.director.v1_5.features.VdcClient; +import org.jclouds.vcloud.director.v1_5.features.VmClient; import com.google.inject.Provides; @@ -109,4 +110,10 @@ public interface VCloudDirectorClient { */ @Delegate VAppTemplateClient getVAppTemplateClient(); + + /** + * @return synchronous access to {@link Vm} features + */ + @Delegate + VmClient getVmClient(); } diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/AbstractVAppClientLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/AbstractVAppClientLiveTest.java index a0d47cb00c..6dc1020a79 100644 --- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/AbstractVAppClientLiveTest.java +++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/AbstractVAppClientLiveTest.java @@ -37,23 +37,25 @@ import org.jclouds.dmtf.cim.CimBoolean; import org.jclouds.dmtf.cim.CimString; import org.jclouds.dmtf.cim.CimUnsignedInt; import org.jclouds.dmtf.cim.CimUnsignedLong; +import org.jclouds.vcloud.director.v1_5.domain.AbstractVAppType; import org.jclouds.vcloud.director.v1_5.domain.RasdItemsList; import org.jclouds.vcloud.director.v1_5.domain.Reference; import org.jclouds.vcloud.director.v1_5.domain.ResourceEntity.Status; -import org.jclouds.vcloud.director.v1_5.domain.dmtf.RasdItem; -import org.jclouds.vcloud.director.v1_5.domain.section.GuestCustomizationSection; -import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConnectionSection; import org.jclouds.vcloud.director.v1_5.domain.Task; import org.jclouds.vcloud.director.v1_5.domain.VApp; import org.jclouds.vcloud.director.v1_5.domain.VAppTemplate; import org.jclouds.vcloud.director.v1_5.domain.Vdc; import org.jclouds.vcloud.director.v1_5.domain.Vm; +import org.jclouds.vcloud.director.v1_5.domain.dmtf.RasdItem; +import org.jclouds.vcloud.director.v1_5.domain.section.GuestCustomizationSection; +import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConnectionSection; import org.jclouds.vcloud.director.v1_5.features.CatalogClient; import org.jclouds.vcloud.director.v1_5.features.MetadataClient; import org.jclouds.vcloud.director.v1_5.features.QueryClient; import org.jclouds.vcloud.director.v1_5.features.VAppClient; import org.jclouds.vcloud.director.v1_5.features.VAppTemplateClient; import org.jclouds.vcloud.director.v1_5.features.VdcClient; +import org.jclouds.vcloud.director.v1_5.features.VmClient; import org.jclouds.vcloud.director.v1_5.internal.BaseVCloudDirectorClientLiveTest; import org.jclouds.vcloud.director.v1_5.predicates.ReferencePredicates; import org.jclouds.xml.internal.JAXBParser; @@ -76,9 +78,10 @@ import com.google.common.collect.Iterables; */ public abstract class AbstractVAppClientLiveTest extends BaseVCloudDirectorClientLiveTest { - public static final String VAPP = "vApp"; - public static final String VAPP_TEMPLATE = "vAppTemplate"; - public static final String VDC = "vdc"; + public static final String VAPP = "VApp"; + public static final String VAPP_TEMPLATE = "VAppTemplate"; + public static final String VDC = "Vdc"; + public static final String VM = "Vm"; /* * Convenience reference to API clients. @@ -89,6 +92,7 @@ public abstract class AbstractVAppClientLiveTest extends BaseVCloudDirectorClien protected VAppClient vAppClient; protected VAppTemplateClient vAppTemplateClient; protected VdcClient vdcClient; + protected VmClient vmClient; protected MetadataClient.Writeable metadataClient; /* @@ -97,9 +101,10 @@ public abstract class AbstractVAppClientLiveTest extends BaseVCloudDirectorClien protected Vdc vdc; protected Vm vm; - protected URI vAppURI; protected VApp vApp; protected VAppTemplate vAppTemplate; + protected URI vmURI; + protected URI vAppURI; /** * Retrieves the required clients from the REST API context @@ -116,6 +121,7 @@ public abstract class AbstractVAppClientLiveTest extends BaseVCloudDirectorClien vAppClient = context.getApi().getVAppClient(); vAppTemplateClient = context.getApi().getVAppTemplateClient(); vdcClient = context.getApi().getVdcClient(); + vmClient = context.getApi().getVmClient(); setupEnvironment(); } @@ -148,6 +154,7 @@ public abstract class AbstractVAppClientLiveTest extends BaseVCloudDirectorClien // Get the Vm List vms = vApp.getChildren().getVms(); vm = Iterables.getOnlyElement(vms); + vmURI = vm.getHref(); assertFalse(vms.isEmpty(), "The VApp must have a Vm"); } @@ -182,8 +189,9 @@ public abstract class AbstractVAppClientLiveTest extends BaseVCloudDirectorClien } @AfterClass(alwaysRun = true, description = "Cleans up the environment by deleting created VApps") - protected void cleanUp() { + protected void cleanUpEnvironment() { vdc = vdcClient.getVdc(vdcURI); // Refresh + // Find references in the Vdc with the VApp type and in the list of instantiated VApp names Iterable vApps = Iterables.filter(vdc.getResourceEntities(), Predicates.and(ReferencePredicates. typeEquals(VCloudDirectorMediaType.VAPP), ReferencePredicates. nameIn(vAppNames))); @@ -237,84 +245,116 @@ public abstract class AbstractVAppClientLiveTest extends BaseVCloudDirectorClien } /** - * Power on a {@link VApp}s {@link Vm}s. - * - * @see #powerOn(URI) + * Power on a {@link VApp}. */ - protected VApp powerOn(final VApp testVApp) { - return powerOn(testVApp.getHref()); - } - - /** - * Power on a {@link VApp}s {@link Vm}s. - */ - protected VApp powerOn(final URI testVAppURI) { - VApp testVApp = vAppClient.getVApp(testVAppURI); - Vm vm = Iterables.getOnlyElement(testVApp.getChildren().getVms()); - Status status = vm.getStatus(); + protected VApp powerOnVApp(final URI testVAppURI) { + VApp test = vAppClient.getVApp(testVAppURI); + Status status = test.getStatus(); if (status != Status.POWERED_ON) { Task powerOn = vAppClient.powerOn(vm.getHref()); assertTaskSucceedsLong(powerOn); } - assertVAppStatus(testVAppURI, Status.POWERED_ON); - return testVApp; + test = vAppClient.getVApp(testVAppURI); + assertStatus(VAPP, test, Status.POWERED_ON); + return test; } /** - * Power off a {@link VApp}s {@link Vm}s. - * - * @see #powerOff(URI) + * Power on a {@link Vm}. */ - protected VApp powerOff(final VApp testVApp) { - return powerOff(testVApp.getHref()); + protected Vm powerOnVm(final URI testVmURI) { + Vm test = vmClient.getVm(testVmURI); + Status status = test.getStatus(); + if (status != Status.POWERED_ON) { + Task powerOn = vmClient.powerOn(vm.getHref()); + assertTaskSucceedsLong(powerOn); + } + test = vmClient.getVm(testVmURI); + assertStatus(VM, test, Status.POWERED_ON); + return test; } /** - * Power off a {@link VApp}s {@link Vm}s. + * Power off a {@link VApp}. */ - protected VApp powerOff(final URI testVAppURI) { - VApp testVApp = vAppClient.getVApp(testVAppURI); - Vm vm = Iterables.getOnlyElement(testVApp.getChildren().getVms()); - Status status = vm.getStatus(); + protected VApp powerOffVApp(final URI testVAppURI) { + VApp test = vAppClient.getVApp(testVAppURI); + Status status = test.getStatus(); if (status != Status.POWERED_OFF) { Task powerOff = vAppClient.powerOff(vm.getHref()); assertTaskSucceedsLong(powerOff); } - assertVAppStatus(testVAppURI, Status.POWERED_OFF); - return testVApp; + test = vAppClient.getVApp(testVAppURI); + assertStatus(VAPP, test, Status.POWERED_OFF); + return test; } /** - * Suspend a {@link VApp}s {@link Vm}s. - * - * @see #suspend(URI) + * Power off a {@link Vm}. */ - protected VApp suspend(final VApp testVApp) { - return powerOff(testVApp.getHref()); + protected Vm powerOffVm(final URI testVmURI) { + Vm test = vmClient.getVm(testVmURI); + Status status = test.getStatus(); + if (status != Status.POWERED_OFF) { + Task powerOff = vmClient.powerOff(vm.getHref()); + assertTaskSucceedsLong(powerOff); + } + test = vmClient.getVm(testVmURI); + assertStatus(VM, test, Status.POWERED_OFF); + return test; } /** - * Suspend a {@link VApp}s {@link Vm}s. + * Suspend a {@link VApp}. */ - protected VApp suspend(final URI testVAppURI) { - VApp testVApp = vAppClient.getVApp(testVAppURI); - Vm vm = Iterables.getOnlyElement(testVApp.getChildren().getVms()); - Status status = vm.getStatus(); + protected VApp suspendVApp(final URI testVAppURI) { + VApp test = vAppClient.getVApp(testVAppURI); + Status status = test.getStatus(); if (status != Status.SUSPENDED) { Task suspend = vAppClient.suspend(vm.getHref()); assertTaskSucceedsLong(suspend); } - assertVAppStatus(testVAppURI, Status.SUSPENDED); - return testVApp; + test = vAppClient.getVApp(testVAppURI); + assertStatus(VAPP, test, Status.SUSPENDED); + return test; } /** - * Check the {@link VApp}s {@link Vm}s current status. + * Suspend a {@link Vm}. + */ + protected Vm suspendVm(final URI testVmURI) { + Vm test = vmClient.getVm(testVmURI); + Status status = test.getStatus(); + if (status != Status.SUSPENDED) { + Task suspend = vmClient.suspend(vm.getHref()); + assertTaskSucceedsLong(suspend); + } + test = vmClient.getVm(testVmURI); + assertStatus(VM, test, Status.SUSPENDED); + return test; + } + + /** + * Check the {@link VApp}s current status. */ protected void assertVAppStatus(final URI testVAppURI, final Status status) { VApp testVApp = vAppClient.getVApp(testVAppURI); - Vm vm = Iterables.getOnlyElement(testVApp.getChildren().getVms()); - assertEquals(vm.getStatus(), status, String.format(OBJ_FIELD_EQ, VAPP, "status", status.toString(), vm.getStatus().toString())); + assertStatus(VAPP, testVApp, status); + } + + /** + * Check the {@link Vm}s current status. + */ + protected void assertVmStatus(final URI testVmURI, final Status status) { + Vm testVm = vmClient.getVm(testVmURI); + assertStatus(VM, testVm, status); + } + + /** + * Check a {@link VApp} or {@link Vm}s status. + */ + protected static void assertStatus(final String type, final AbstractVAppType testVApp, final Status status) { + assertEquals(testVApp.getStatus(), status, String.format(OBJ_FIELD_EQ, type, "status", status.toString(), testVApp.getStatus().toString())); } /** diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppClientExpectTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppClientExpectTest.java index 700fd453ca..6d9cbeb777 100644 --- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppClientExpectTest.java +++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppClientExpectTest.java @@ -39,9 +39,7 @@ import org.jclouds.vcloud.director.v1_5.domain.VmQuestionAnswer; import org.jclouds.vcloud.director.v1_5.domain.dmtf.RasdItem; import org.jclouds.vcloud.director.v1_5.domain.params.ControlAccessParams; import org.jclouds.vcloud.director.v1_5.domain.params.DeployVAppParams; -import org.jclouds.vcloud.director.v1_5.domain.params.MediaInsertOrEjectParams; import org.jclouds.vcloud.director.v1_5.domain.params.RecomposeVAppParams; -import org.jclouds.vcloud.director.v1_5.domain.params.RelocateParams; import org.jclouds.vcloud.director.v1_5.domain.params.UndeployVAppParams; import org.jclouds.vcloud.director.v1_5.domain.section.GuestCustomizationSection; import org.jclouds.vcloud.director.v1_5.domain.section.LeaseSettingsSection; @@ -56,9 +54,6 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.testng.internal.annotations.Sets; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Multimaps; - /** * Allows us to test the {@link VAppClient} via its side effects. * @@ -127,22 +122,6 @@ public class VAppClientExpectTest extends VCloudDirectorAdminClientExpectTest { assertEquals(client.getVAppClient().deleteVApp(vAppURI), expected); } - @Test(enabled = false) - public void testConsolidateVApp() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("POST", vAppId + "/action/consolidate") - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/consolidateVAppTask.xml", VCloudDirectorMediaType.TASK) - .httpResponseBuilder().build()); - - Task expected = consolidateVAppTask(); - - assertEquals(client.getVAppClient().consolidateVm(vAppURI), expected); - } - @Test(enabled = false) public void testControlAccess() { VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, @@ -226,22 +205,6 @@ public class VAppClientExpectTest extends VCloudDirectorAdminClientExpectTest { client.getVAppClient().exitMaintenanceMode(vAppURI); } - @Test(enabled = false) - public void testInstallVMwareTools() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("POST", vAppId + "/action/installVMwareTools") - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/installVMwareToolsTask.xml", VCloudDirectorMediaType.TASK) - .httpResponseBuilder().build()); - - Task expected = installVMwareToolsTask(); - - assertEquals(client.getVAppClient().installVMwareTools(vAppURI), expected); - } - @Test(enabled = false) public void testRecomposeVApp() { VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, @@ -262,26 +225,6 @@ public class VAppClientExpectTest extends VCloudDirectorAdminClientExpectTest { assertEquals(client.getVAppClient().recompose(vAppURI, params), expected); } - @Test(enabled = false) - public void testRelocate() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("POST", vAppId + "/action/relocate") - .xmlFilePayload("/vApp/relocateParams.xml", VCloudDirectorMediaType.RELOCATE_VM_PARAMS) - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/relocateTask.xml", VCloudDirectorMediaType.TASK) - .httpResponseBuilder().build()); - - RelocateParams params = RelocateParams.builder() - .build(); - - Task expected = relocateTask(); - - assertEquals(client.getVAppClient().relocateVm(vAppURI, params), expected); - } - @Test(enabled = false) public void testUndeploy() { VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, @@ -302,22 +245,6 @@ public class VAppClientExpectTest extends VCloudDirectorAdminClientExpectTest { assertEquals(client.getVAppClient().undeploy(vAppURI, params), expected); } - @Test(enabled = false) - public void testUpgradeHardwareVersion() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("POST", vAppId + "/action/upgradeHardwareVersion") - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/upgradeHardwareVersionTask.xml", VCloudDirectorMediaType.TASK) - .httpResponseBuilder().build()); - - Task expected = upgradeHardwareVersionTask(); - - assertEquals(client.getVAppClient().upgradeHardwareVersion(vAppURI), expected); - } - @Test(enabled = false) public void testPowerOff() { VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, @@ -430,42 +357,6 @@ public class VAppClientExpectTest extends VCloudDirectorAdminClientExpectTest { assertEquals(client.getVAppClient().getControlAccess(vAppURI), expected); } - @Test(enabled = false) - public void testGetGuestCustomizationSection() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("GET", vAppId + "/guestCustomizationSection") - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/getGuestCustomizationSection.xml", VCloudDirectorMediaType.GUEST_CUSTOMIZATION_SECTION) - .httpResponseBuilder().build()); - - GuestCustomizationSection expected = getGuestCustomizationSection(); - - assertEquals(client.getVAppClient().getGuestCustomizationSection(vAppURI), expected); - } - - @Test(enabled = false) - public void testModifyGuestCustomizationSection() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("PUT", vAppId + "/guestCustomizationSection") - .xmlFilePayload("/vApp/modifyGuestCustomizationSection.xml", VCloudDirectorMediaType.GUEST_CUSTOMIZATION_SECTION) - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/modifyGuestCustomizationSectionTask.xml", VCloudDirectorMediaType.TASK) - .httpResponseBuilder().build()); - - GuestCustomizationSection section = getGuestCustomizationSection().toBuilder() - .build(); - - Task expected = modifyGuestCustomizationSectionTask(); - - assertEquals(client.getVAppClient().modifyGuestCustomizationSection(vAppURI, section), expected); - } - @Test(enabled = false) public void testGetLeaseSettingsSection() { VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, @@ -502,46 +393,6 @@ public class VAppClientExpectTest extends VCloudDirectorAdminClientExpectTest { assertEquals(client.getVAppClient().modifyLeaseSettingsSection(vAppURI, section), expected); } - @Test(enabled = false) - public void testEjectMedia() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("PUT", vAppId + "/media/action/ejectMedia") - .xmlFilePayload("/vApp/ejectMediaParams.xml", VCloudDirectorMediaType.MEDIA_PARAMS) - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/ejectMediaTask.xml", VCloudDirectorMediaType.TASK) - .httpResponseBuilder().build()); - - MediaInsertOrEjectParams params = MediaInsertOrEjectParams.builder() - .build(); - - Task expected = ejectMediaTask(); - - assertEquals(client.getVAppClient().ejectMedia(vAppURI, params), expected); - } - - @Test(enabled = false) - public void testInsertMedia() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("PUT", vAppId + "/media/action/insertMedia") - .xmlFilePayload("/vApp/insertMediaParams.xml", VCloudDirectorMediaType.MEDIA_PARAMS) - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/insertMediaTask.xml", VCloudDirectorMediaType.VAPP) - .httpResponseBuilder().build()); - - MediaInsertOrEjectParams params = MediaInsertOrEjectParams.builder() - .build(); - - Task expected = insertMediaTask(); - - assertEquals(client.getVAppClient().insertMedia(vAppURI, params), expected); - } - @Test(enabled = false) public void testGetNetworkConfigSection() { VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, @@ -578,42 +429,6 @@ public class VAppClientExpectTest extends VCloudDirectorAdminClientExpectTest { assertEquals(client.getVAppClient().modifyNetworkConfigSection(vAppURI, section), expected); } - @Test(enabled = false) - public void testGetNetworkConnectionSection() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("GET", vAppId + "/networkConnectionSection") - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/getNetworkConnectionSection.xml", VCloudDirectorMediaType.NETWORK_CONNECTION_SECTION) - .httpResponseBuilder().build()); - - NetworkConnectionSection expected = getNetworkConnectionSection(); - - assertEquals(client.getVAppClient().getNetworkConnectionSection(vAppURI), expected); - } - - @Test(enabled = false) - public void testModifyNetworkConnectionSection() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("PUT", vAppId + "/networkConnectionSection") - .xmlFilePayload("/vApp/modifyNetworkConnectionSection.xml", VCloudDirectorMediaType.NETWORK_CONNECTION_SECTION) - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/modifyNetworkConnectionSectionTask.xml", VCloudDirectorMediaType.TASK) - .httpResponseBuilder().build()); - - NetworkConnectionSection section = getNetworkConnectionSection().toBuilder() - .build(); - - Task expected = modifyNetworkConnectionSectionTask(); - - assertEquals(client.getVAppClient().modifyNetworkConnectionSection(vAppURI, section), expected); - } - @Test(enabled = false) public void testGetNetworkSection() { VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, @@ -630,42 +445,6 @@ public class VAppClientExpectTest extends VCloudDirectorAdminClientExpectTest { assertEquals(client.getVAppClient().getNetworkSection(vAppURI), expected); } - @Test(enabled = false) - public void testGetOperatingSystemSection() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("GET", vAppId + "/operatingSystemSection") - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/getOperatingSystemSection.xml", VCloudDirectorMediaType.OPERATING_SYSTEM_SECTION) - .httpResponseBuilder().build()); - - OperatingSystemSection expected = getOperatingSystemSection(); - - assertEquals(client.getVAppClient().getOperatingSystemSection(vAppURI), expected); - } - - @Test(enabled = false) - public void testModifyOperatingSystemSection() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("PUT", vAppId + "/operatingSystemSection") - .xmlFilePayload("/vApp/modifyOperatingSystemSection.xml", VCloudDirectorMediaType.OPERATING_SYSTEM_SECTION) - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/modifyOperatingSystemSectionTask.xml", VCloudDirectorMediaType.TASK) - .httpResponseBuilder().build()); - - OperatingSystemSection section = getOperatingSystemSection().toBuilder() - .build(); - - Task expected = modifyOperatingSystemSectionTask(); - - assertEquals(client.getVAppClient().modifyOperatingSystemSection(vAppURI, section), expected); - } - @Test(enabled = false) public void testGetOwner() { VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, @@ -732,89 +511,6 @@ public class VAppClientExpectTest extends VCloudDirectorAdminClientExpectTest { assertEquals(client.getVAppClient().modifyProductSections(vAppURI, null), expected); } - @Test(enabled = false) - public void testGetPendingQuestion() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("GET", vAppId + "/question") - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/getPendingQuestion.xml", VCloudDirectorMediaType.VM_PENDING_QUESTION) - .httpResponseBuilder().build()); - - VmPendingQuestion expected = getPendingQuestion(); - - assertEquals(client.getVAppClient().getPendingQuestion(vAppURI), expected); - } - - @Test(enabled = false) - public void testAnswerQuestion() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("PUT", vAppId + "/question/action/answer") - .xmlFilePayload("/vApp/answerQuestion.xml", VCloudDirectorMediaType.VM_PENDING_ANSWER) - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .httpResponseBuilder().statusCode(204).build()); - - VmQuestionAnswer answer = null; // = VmQuestionAnswer.builder(); -// .build; - - client.getVAppClient().answerQuestion(vAppURI, answer); - } - - @Test(enabled = false) - public void testGetRuntimeInfoSection() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("GET", vAppId + "/runtimeInfoSection") - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/getRuntimeInfoSection.xml", VCloudDirectorMediaType.RUNTIME_INFO_SECTION) - .httpResponseBuilder().build()); - - RuntimeInfoSection expected = getRuntimeInfoSection(); - - assertEquals(client.getVAppClient().getRuntimeInfoSection(vAppURI), expected); - } - - @Test(enabled = false) - public void testGetScreenImage() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("GET", vAppId + "/screen") - .acceptMedia(VCloudDirectorMediaType.ANY_IMAGE) - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .httpResponseBuilder() - .headers(Multimaps.forMap(ImmutableMap.of("Content-Type", "image/png"))) - .message(new String(getScreenImage())) - .build()); - - byte[] expected = getScreenImage(); - - assertEquals(client.getVAppClient().getScreenImage(vAppURI), expected); - } - - @Test(enabled = false) - public void testGetScreenTicket() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("POST", vAppId + "/screen/action/acquireTicket") - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/getScreenTicket.xml", VCloudDirectorMediaType.SCREEN_TICKET) - .httpResponseBuilder().build()); - - ScreenTicket expected = getScreenTicket(); - - assertEquals(client.getVAppClient().getScreenTicket(vAppURI), expected); - } - @Test(enabled = false) public void testGetStartupSection() { VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, @@ -851,238 +547,6 @@ public class VAppClientExpectTest extends VCloudDirectorAdminClientExpectTest { assertEquals(client.getVAppClient().modifyStartupSection(vAppURI, section), expected); } - @Test(enabled = false) - public void testGetVirtualHardwareSection() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("GET", vAppId + "/virtualHardwareSection") - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/getVirtualHardwareSection.xml", VCloudDirectorMediaType.VIRTUAL_HARDWARE_SECTION) - .httpResponseBuilder().build()); - - VirtualHardwareSection expected = getVirtualHardwareSection(); - - assertEquals(client.getVAppClient().getVirtualHardwareSection(vAppURI), expected); - } - - @Test(enabled = false) - public void testModifyVirtualHardwareSection() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("PUT", vAppId + "/virtualHardwareSection") - .xmlFilePayload("/vApp/modifyVirtualHardwareSection.xml", VCloudDirectorMediaType.VIRTUAL_HARDWARE_SECTION) - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/modifyVirtualHardwareSectionTask.xml", VCloudDirectorMediaType.TASK) - .httpResponseBuilder().build()); - - VirtualHardwareSection section = getVirtualHardwareSection().toBuilder() - .build(); - - Task expected = modifyVirtualHardwareSectionTask(); - - assertEquals(client.getVAppClient().modifyVirtualHardwareSection(vAppURI, section), expected); - } - - @Test(enabled = false) - public void testGetVirtualHardwareSectionCpu() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("GET", vAppId + "/virtualHardwareSection/cpu") - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/getVirtualHardwareSectionCpu.xml", VCloudDirectorMediaType.OVF_RASD_ITEM) - .httpResponseBuilder().build()); - - RasdItem expected = getVirtualHardwareSectionCpu(); - - assertEquals(client.getVAppClient().getVirtualHardwareSectionCpu(vAppURI), expected); - } - - @Test(enabled = false) - public void testModifyVirtualHardwareSectionCpu() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("", vAppId + "/virtualHardwareSection/cpu") - .xmlFilePayload("/vApp/modifyVirtualHardwareSectionCpu.xml", VCloudDirectorMediaType.OVF_RASD_ITEM) - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/modifyVirtualHardwareSectionCpuTask.xml", VCloudDirectorMediaType.TASK) - .httpResponseBuilder().build()); - - RasdItem cpu = getVirtualHardwareSectionCpu(); // .toBuilder(); -// .build(); - - Task expected = modifyVirtualHardwareSectionCpuTask(); - - assertEquals(client.getVAppClient().modifyVirtualHardwareSectionCpu(vAppURI, cpu), expected); - } - - @Test(enabled = false) - public void testGetVirtualHardwareSectionDisks() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("GET", vAppId + "/virtualHardwareSection/disks") - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/getVirtualHardwareSectionDisks.xml", VCloudDirectorMediaType.OVF_RASD_ITEMS_LIST) - .httpResponseBuilder().build()); - - RasdItemsList expected = getVirtualHardwareSectionDisks(); - - assertEquals(client.getVAppClient().getVirtualHardwareSectionDisks(vAppURI), expected); - } - - @Test(enabled = false) - public void testModifyVirtualHardwareSectionDisks() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("PUT", vAppId + "/virtualHardwareSection/disks") - .xmlFilePayload("/vApp/modifyVirtualHardwareSectionDisks.xml", VCloudDirectorMediaType.OVF_RASD_ITEMS_LIST) - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/modifyVirtualHardwareSectionDisksTask.xml", VCloudDirectorMediaType.TASK) - .httpResponseBuilder().build()); - - RasdItemsList disks = getVirtualHardwareSectionDisks().toBuilder() - .build(); - - Task expected = modifyVirtualHardwareSectionDisksTask(); - - assertEquals(client.getVAppClient().modifyVirtualHardwareSectionDisks(vAppURI, disks), expected); - } - - @Test(enabled = false) - public void testGetVirtualHardwareSectionMedia() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("GET", vAppId + "/virtualHardwareSection/media") - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/getVirtualHardwareSectionMedia.xml", VCloudDirectorMediaType.OVF_RASD_ITEMS_LIST) - .httpResponseBuilder().build()); - - RasdItemsList expected = getVirtualHardwareSectionMedia(); - - assertEquals(client.getVAppClient().getVirtualHardwareSectionMedia(vAppURI), expected); - } - - @Test(enabled = false) - public void testGetVirtualHardwareSectionMemory() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("GET", vAppId + "/virtualHardwareSection/memory") - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/getVirtualHardwareSectionMemory.xml", VCloudDirectorMediaType.OVF_RASD_ITEM) - .httpResponseBuilder().build()); - - RasdItem expected = getVirtualHardwareSectionMemory(); - - assertEquals(client.getVAppClient().getVirtualHardwareSectionMemory(vAppURI), expected); - } - - @Test(enabled = false) - public void testModifyVirtualHardwareSectionMemory() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("PUT", vAppId + "/virtualHardwareSection/memory") - .xmlFilePayload("/vApp/modifyVirtualHardwareSectionMemory.xml", VCloudDirectorMediaType.VAPP) - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/modifyVirtualHardwareSectionMemoryTask.xml", VCloudDirectorMediaType.TASK) - .httpResponseBuilder().build()); - - RasdItem memory = getVirtualHardwareSectionCpu(); // .toBuilder(); -// .build(); - - Task expected = modifyVirtualHardwareSectionMemoryTask(); - - assertEquals(client.getVAppClient().modifyVirtualHardwareSectionMemory(vAppURI, memory), expected); - } - - @Test(enabled = false) - public void testGetVirtualHardwareSectionNetworkCards() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("GET", vAppId + "/virtualHardwareSection/networkCards") - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/getVirtualHardwareSectionNetworkCards.xml", VCloudDirectorMediaType.OVF_RASD_ITEMS_LIST) - .httpResponseBuilder().build()); - - RasdItemsList expected = getVirtualHardwareSectionNetworkCards(); - - assertEquals(client.getVAppClient().getVirtualHardwareSectionNetworkCards(vAppURI), expected); - } - - @Test(enabled = false) - public void testModifyVirtualHardwareSectionNetworkCards() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("PUT", vAppId + "/virtualHardwareSection/networkCards") - .xmlFilePayload("/vApp/modifyVirtualHardwareSectionNetworkCards.xml", VCloudDirectorMediaType.OVF_RASD_ITEMS_LIST) - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/modifyVirtualHardwareSectionNetworkCardsTask.xml", VCloudDirectorMediaType.TASK) - .httpResponseBuilder().build()); - - RasdItemsList networkCards = getVirtualHardwareSectionNetworkCards().toBuilder() - .build(); - - Task expected = modifyVirtualHardwareSectionNetworkCardsTask(); - - assertEquals(client.getVAppClient().modifyVirtualHardwareSectionNetworkCards(vAppURI, networkCards), expected); - } - - @Test(enabled = false) - public void testGetVirtualHardwareSectionSerialPorts() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("GET", vAppId + "/virtualHardwareSection/serialPorts") - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/getVirtualHardwareSectionSerialPorts.xml", VCloudDirectorMediaType.VAPP) - .httpResponseBuilder().build()); - - RasdItemsList expected = getVirtualHardwareSectionSerialPorts(); - - assertEquals(client.getVAppClient().getVirtualHardwareSectionSerialPorts(vAppURI), expected); - } - - @Test(enabled = false) - public void testModifyVirtualHardwareSectionSerialPorts() { - VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, - new VcloudHttpRequestPrimer() - .apiCommand("PUT", vAppId + "/virtualHardwareSection/serialPorts") - .xmlFilePayload("/vApp/modifyVirtualHardwareSectionSerialPorts.xml", VCloudDirectorMediaType.OVF_RASD_ITEMS_LIST) - .acceptAnyMedia() - .httpRequestBuilder().build(), - new VcloudHttpResponsePrimer() - .xmlFilePayload("/vApp/modifyVirtualHardwareSectionSerialPortsTask.xml", VCloudDirectorMediaType.TASK) - .httpResponseBuilder().build()); - - RasdItemsList serialPorts = getVirtualHardwareSectionSerialPorts().toBuilder() - .build(); - - Task expected = modifyVirtualHardwareSectionSerialPortsTask(); - - assertEquals(client.getVAppClient().modifyVirtualHardwareSectionSerialPorts(vAppURI, serialPorts), expected); - } - public static VApp getVApp() { // FIXME Does not match XML VApp vApp = VApp.builder() diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppClientLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppClientLiveTest.java index edb255169c..c5ec6a0b17 100644 --- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppClientLiveTest.java +++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppClientLiveTest.java @@ -30,9 +30,7 @@ import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.N import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_FIELD_EQ; import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.TASK_COMPLETE_TIMELY; import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.ADMIN_USER; -import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.MEDIA; import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkControlAccessParams; -import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkGuestCustomizationSection; import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkLeaseSettingsSection; import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadata; import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataFor; @@ -40,36 +38,23 @@ import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataKeyAbs import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataValue; import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataValueFor; import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkNetworkConfigSection; -import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkNetworkConnectionSection; import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkNetworkSection; -import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkOperatingSystemSection; import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkOwner; import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkProductSectionList; -import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkRasdItemsList; -import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkResourceAllocationSettingData; -import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkRuntimeInfoSection; -import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkScreenTicket; import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkStartupSection; import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkVApp; -import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkVirtualHardwareSection; -import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkVmPendingQuestion; import static org.jclouds.vcloud.director.v1_5.predicates.LinkPredicates.relEquals; import static org.jclouds.vcloud.director.v1_5.predicates.LinkPredicates.typeEquals; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; -import java.math.BigInteger; import java.net.URI; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; -import org.jclouds.dmtf.cim.OSType; -import org.jclouds.dmtf.cim.ResourceAllocationSettingData; import org.jclouds.dmtf.ovf.MsgType; import org.jclouds.dmtf.ovf.NetworkSection; import org.jclouds.dmtf.ovf.ProductSection; @@ -86,42 +71,23 @@ import org.jclouds.vcloud.director.v1_5.domain.MetadataEntry; import org.jclouds.vcloud.director.v1_5.domain.MetadataValue; import org.jclouds.vcloud.director.v1_5.domain.Owner; import org.jclouds.vcloud.director.v1_5.domain.ProductSectionList; -import org.jclouds.vcloud.director.v1_5.domain.RasdItemsList; import org.jclouds.vcloud.director.v1_5.domain.Reference; import org.jclouds.vcloud.director.v1_5.domain.ResourceEntity.Status; -import org.jclouds.vcloud.director.v1_5.domain.ScreenTicket; import org.jclouds.vcloud.director.v1_5.domain.Task; import org.jclouds.vcloud.director.v1_5.domain.VApp; -import org.jclouds.vcloud.director.v1_5.domain.VmPendingQuestion; -import org.jclouds.vcloud.director.v1_5.domain.VmQuestionAnswer; -import org.jclouds.vcloud.director.v1_5.domain.VmQuestionAnswerChoice; -import org.jclouds.vcloud.director.v1_5.domain.dmtf.RasdItem; -import org.jclouds.vcloud.director.v1_5.domain.network.NetworkConnection; -import org.jclouds.vcloud.director.v1_5.domain.network.NetworkConnection.IpAddressAllocationMode; import org.jclouds.vcloud.director.v1_5.domain.params.ControlAccessParams; import org.jclouds.vcloud.director.v1_5.domain.params.DeployVAppParams; -import org.jclouds.vcloud.director.v1_5.domain.params.MediaInsertOrEjectParams; import org.jclouds.vcloud.director.v1_5.domain.params.RecomposeVAppParams; -import org.jclouds.vcloud.director.v1_5.domain.params.RelocateParams; import org.jclouds.vcloud.director.v1_5.domain.params.UndeployVAppParams; -import org.jclouds.vcloud.director.v1_5.domain.query.QueryResultRecordType; -import org.jclouds.vcloud.director.v1_5.domain.query.QueryResultRecords; -import org.jclouds.vcloud.director.v1_5.domain.section.GuestCustomizationSection; import org.jclouds.vcloud.director.v1_5.domain.section.LeaseSettingsSection; import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConfigSection; -import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConnectionSection; -import org.jclouds.vcloud.director.v1_5.domain.section.OperatingSystemSection; -import org.jclouds.vcloud.director.v1_5.domain.section.RuntimeInfoSection; -import org.jclouds.vcloud.director.v1_5.domain.section.VirtualHardwareSection; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; -import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; -import com.google.common.collect.Sets; /** * Tests behavior of the {@link VAppClient}. @@ -150,10 +116,10 @@ public class VAppClientLiveTest extends AbstractVAppClientLiveTest { Media sourceMedia = Media.builder() .type(VCloudDirectorMediaType.MEDIA) - .name("Test media "+random.nextInt()) + .name(name("media")) .size(iso.length) .imageType(Media.ImageType.ISO) - .description("Test media generated by vAppClientLiveTest") + .description("Test media generated by VAppClientLiveTest") .build(); Media media = context.getApi().getMediaClient().createMedia(addMedia.getHref(), sourceMedia); @@ -183,22 +149,21 @@ public class VAppClientLiveTest extends AbstractVAppClientLiveTest { } } - @Override - @AfterClass(alwaysRun = true) + @AfterClass(alwaysRun = true, dependsOnMethods = { "cleanUpEnvironment" }) public void cleanUp() { if (adminContext != null && mediaCreated && mediaURI != null) { try { - Task delete = context.getApi().getMediaClient().deleteMedia(mediaURI); - taskDoneEventually(delete); + Task delete = context.getApi().getMediaClient().deleteMedia(mediaURI); + taskDoneEventually(delete); } catch (Exception e) { - logger.warn("Error when deleting media: %s", e.getMessage()); + logger.warn(e, "Error when deleting media"); } } if (adminContext != null && testUserCreated && testUserURI != null) { try { - adminContext.getApi().getUserClient().deleteUser(testUserURI); + adminContext.getApi().getUserClient().deleteUser(testUserURI); } catch (Exception e) { - logger.warn("Error when deleting user: %s", e.getMessage()); + logger.warn(e, "Error when deleting user"); } } } @@ -252,7 +217,7 @@ public class VAppClientLiveTest extends AbstractVAppClientLiveTest { @Test(description = "POST /vApp/{id}/action/deploy", dependsOnMethods = { "testGetVApp" }) public void testDeployVApp() { DeployVAppParams params = DeployVAppParams.builder() - .deploymentLeaseSeconds((int) TimeUnit.SECONDS.convert(1L, TimeUnit.HOURS)) + .deploymentLeaseSeconds((int)TimeUnit.SECONDS.convert(1L, TimeUnit.HOURS)) .notForceCustomization() .notPowerOn() .build(); @@ -274,7 +239,7 @@ public class VAppClientLiveTest extends AbstractVAppClientLiveTest { @Test(description = "POST /vApp/{id}/power/action/powerOn", dependsOnMethods = { "testDeployVApp" }) public void testPowerOnVApp() { // Power off VApp - vApp = powerOff(vApp); + vApp = powerOffVApp(vApp.getHref()); // The method under test Task powerOnVApp = vAppClient.powerOn(vApp.getHref()); @@ -290,7 +255,7 @@ public class VAppClientLiveTest extends AbstractVAppClientLiveTest { @Test(description = "POST /vApp/{id}/power/action/reboot", dependsOnMethods = { "testDeployVApp" }) public void testReboot() { // Power on VApp - vApp = powerOn(vApp); + vApp = powerOnVApp(vApp.getHref()); // The method under test Task reboot = vAppClient.reboot(vApp.getHref()); @@ -306,7 +271,7 @@ public class VAppClientLiveTest extends AbstractVAppClientLiveTest { @Test(description = "POST /vApp/{id}/power/action/shutdown", dependsOnMethods = { "testDeployVApp" }) public void testShutdown() { // Power on VApp - vApp = powerOn(vApp); + vApp = powerOnVApp(vApp.getHref()); // The method under test Task shutdown = vAppClient.shutdown(vAppURI); @@ -319,13 +284,13 @@ public class VAppClientLiveTest extends AbstractVAppClientLiveTest { assertVAppStatus(vAppURI, Status.POWERED_OFF); // Power on the VApp again - vApp = powerOn(vApp); + vApp = powerOnVApp(vApp.getHref()); } @Test(description = "POST /vApp/{id}/power/action/suspend", dependsOnMethods = { "testDeployVApp" }) public void testSuspend() { // Power on VApp - vApp = powerOn(vApp); + vApp = powerOnVApp(vApp.getHref()); // The method under test Task suspend = vAppClient.suspend(vAppURI); @@ -338,13 +303,13 @@ public class VAppClientLiveTest extends AbstractVAppClientLiveTest { assertVAppStatus(vAppURI, Status.SUSPENDED); // Power on the VApp again - vApp = powerOn(vApp); + vApp = powerOnVApp(vApp.getHref()); } @Test(description = "POST /vApp/{id}/power/action/reset", dependsOnMethods = { "testDeployVApp" }) public void testReset() { // Power on VApp - vApp = powerOn(vApp); + vApp = powerOnVApp(vApp.getHref()); // The method under test Task reset = vAppClient.reset(vAppURI); @@ -360,7 +325,7 @@ public class VAppClientLiveTest extends AbstractVAppClientLiveTest { @Test(description = "POST /vApp/{id}/action/undeploy", dependsOnMethods = { "testDeployVApp" }) public void testUndeployVApp() { // Power on VApp - vApp = powerOn(vApp); + vApp = powerOnVApp(vApp.getHref()); UndeployVAppParams params = UndeployVAppParams.builder().build(); @@ -379,7 +344,7 @@ public class VAppClientLiveTest extends AbstractVAppClientLiveTest { @Test(description = "POST /vApp/{id}/power/action/powerOff", dependsOnMethods = { "testUndeployVApp" }) public void testPowerOffVApp() { // Power on VApp - vApp = powerOn(vApp); + vApp = powerOnVApp(vApp.getHref()); // The method under test Task powerOffVApp = vAppClient.powerOff(vApp.getHref()); @@ -392,16 +357,6 @@ public class VAppClientLiveTest extends AbstractVAppClientLiveTest { assertVAppStatus(vAppURI, Status.POWERED_OFF); } - @Test(description = "POST /vApp/{id}/action/consolidate", dependsOnMethods = { "testDeployVApp" }) - public void testConsolidateVApp() { - // Power on VApp - vApp = powerOn(vApp); - - // The method under test - Task consolidateVApp = vAppClient.consolidateVm(vApp.getHref()); - assertTrue(retryTaskSuccess.apply(consolidateVApp), String.format(TASK_COMPLETE_TIMELY, "consolidateVApp")); - } - @Test(description = "POST /vApp/{id}/action/controlAccess", dependsOnMethods = { "testGetVApp" }) public void testControlAccessUser() { ControlAccessParams params = ControlAccessParams.builder() @@ -441,7 +396,7 @@ public class VAppClientLiveTest extends AbstractVAppClientLiveTest { @Test(description = "POST /vApp/{id}/action/discardSuspendedState", dependsOnMethods = { "testDeployVApp" }) public void testDiscardSuspendedState() { // Suspend the VApp - vApp = suspend(vAppURI); + vApp = suspendVApp(vApp.getHref()); // The method under test Task discardSuspendedState = vAppClient.discardSuspendedState(vApp.getHref()); @@ -500,16 +455,6 @@ public class VAppClientLiveTest extends AbstractVAppClientLiveTest { } } - @Test(description = "POST /vApp/{id}/action/installVMwareTools", dependsOnMethods = { "testDeployVApp" }) - public void testInstallVMwareTools() { - // First ensure the vApp is powered n - vApp = powerOn(vApp); - - // The method under test - Task installVMwareTools = vAppClient.installVMwareTools(vm.getHref()); - assertTrue(retryTaskSuccess.apply(installVMwareTools), String.format(TASK_COMPLETE_TIMELY, "installVMwareTools")); - } - // FIXME "Could not bind object to request[method=POST, endpoint=https://mycloud.greenhousedata.com/api/vApp/vapp-e124f3f0-adb9-4268-ad49-e54fb27e40af/action/recomposeVApp, // headers={Accept=[application/vnd.vmware.vcloud.task+xml]}, payload=[content=true, contentMetadata=[contentDisposition=null, contentEncoding=null, contentLanguage=null, // contentLength=0, contentMD5=null, contentType=application/vnd.vmware.vcloud.recomposeVAppParams+xml], written=false]]: Could not marshall object" @@ -522,29 +467,6 @@ public class VAppClientLiveTest extends AbstractVAppClientLiveTest { assertTrue(retryTaskSuccess.apply(recomposeVApp), String.format(TASK_COMPLETE_TIMELY, "recomposeVApp")); } - // NOTE This test is disabled, as it is not possible to look up datastores using the User API - @Test(description = "POST /vApp/{id}/action/relocate", dependsOnMethods = { "testGetVApp" }) - public void testRelocate() { - // Relocate to the last of the available datastores - QueryResultRecords records = context.getApi().getQueryClient().queryAll("datastore"); - QueryResultRecordType datastore = Iterables.getLast(records.getRecords()); - RelocateParams params = RelocateParams.builder().datastore(Reference.builder().href(datastore.getHref()).build()).build(); - - // The method under test - Task relocate = vAppClient.relocateVm(vApp.getHref(), params); - assertTrue(retryTaskSuccess.apply(relocate), String.format(TASK_COMPLETE_TIMELY, "relocate")); - } - - @Test(description = "POST /vApp/{id}/action/upgradeHardwareVersion", dependsOnMethods = { "testGetVApp" }) - public void testUpgradeHardwareVersion() { - // Power off VApp - vApp = powerOff(vApp); - - // The method under test - Task upgradeHardwareVersion = vAppClient.upgradeHardwareVersion(vm.getHref()); - assertTrue(retryTaskSuccess.apply(upgradeHardwareVersion), String.format(TASK_COMPLETE_TIMELY, "upgradeHardwareVersion")); - } - @Test(description = "GET /vApp/{id}/controlAccess", dependsOnMethods = { "testGetVApp" }) public void testGetControlAccess() { // The method under test @@ -554,47 +476,6 @@ public class VAppClientLiveTest extends AbstractVAppClientLiveTest { checkControlAccessParams(controlAccess); } - @Test(description = "GET /vApp/{id}/guestCustomizationSection", dependsOnMethods = { "testGetVApp" }) - public void testGetGuestCustomizationSection() { - getGuestCustomizationSection(new Function() { - @Override - public GuestCustomizationSection apply(URI uri) { - return vAppClient.getGuestCustomizationSection(uri); - } - }); - } - - @Test(description = "PUT /vApp/{id}/guestCustomizationSection", dependsOnMethods = { "testGetGuestCustomizationSection" }) - public void testModifyGuestCustomizationSection() { - // Copy existing section and update fields - GuestCustomizationSection oldSection = vAppClient.getGuestCustomizationSection(vm.getHref()); - GuestCustomizationSection newSection = oldSection.toBuilder() - .computerName(name("n")) - .enabled(Boolean.FALSE) - .adminPassword(null) // Not allowed - .build(); - - // The method under test - Task modifyGuestCustomizationSection = vAppClient.modifyGuestCustomizationSection(vm.getHref(), newSection); - assertTrue(retryTaskSuccess.apply(modifyGuestCustomizationSection), String.format(TASK_COMPLETE_TIMELY, "modifyGuestCustomizationSection")); - - // Retrieve the modified section - GuestCustomizationSection modified = vAppClient.getGuestCustomizationSection(vm.getHref()); - - // Check the retrieved object is well formed - checkGuestCustomizationSection(modified); - - // Check the modified section fields are set correctly - assertEquals(modified.getComputerName(), newSection.getComputerName()); - assertFalse(modified.isEnabled()); - - // Reset the admin password in the retrieved GuestCustomizationSection for equality check - modified = modified.toBuilder().adminPassword(null).build(); - - // Check the section was modified correctly - assertEquals(modified, newSection, String.format(ENTITY_EQUAL, "GuestCustomizationSection")); - } - @Test(description = "GET /vApp/{id}/leaseSettingsSection", dependsOnMethods = { "testGetVApp" }) public void testGetLeaseSettingsSection() { // The method under test @@ -653,31 +534,6 @@ public class VAppClientLiveTest extends AbstractVAppClientLiveTest { assertEquals(modified, newSection, String.format(ENTITY_EQUAL, "LeaseSettingsSection")); } - // FIXME "Error: The requested operation on media "com.vmware.vcloud.entity.media:abfcb4b7-809f-4b50-a0aa-8c97bf09a5b0" is not supported in the current state." - @Test(description = "PUT /vApp/{id}/media/action/insertMedia", dependsOnMethods = { "testGetVApp" }) - public void testInsertMedia() { - // Setup media params from configured media id - MediaInsertOrEjectParams params = MediaInsertOrEjectParams.builder() - .media(Reference.builder().href(mediaURI).type(MEDIA).build()) - .build(); - - // The method under test - Task insertMedia = vAppClient.insertMedia(vm.getHref(), params); - assertTrue(retryTaskSuccess.apply(insertMedia), String.format(TASK_COMPLETE_TIMELY, "insertMedia")); - } - - @Test(description = "PUT /vApp/{id}/media/action/ejectMedia", dependsOnMethods = { "testInsertMedia" }) - public void testEjectMedia() { - // Setup media params from configured media id - MediaInsertOrEjectParams params = MediaInsertOrEjectParams.builder() - .media(Reference.builder().href(mediaURI).type(MEDIA).build()) - .build(); - - // The method under test - Task ejectMedia = vAppClient.ejectMedia(vm.getHref(), params); - assertTrue(retryTaskSuccess.apply(ejectMedia), String.format(TASK_COMPLETE_TIMELY, "ejectMedia")); - } - @Test(description = "GET /vApp/{id}/networkConfigSection", dependsOnMethods = { "testGetVApp" }) public void testGetNetworkConfigSection() { // The method under test @@ -711,49 +567,6 @@ public class VAppClientLiveTest extends AbstractVAppClientLiveTest { assertEquals(modified, newSection, String.format(ENTITY_EQUAL, "NetworkConfigSection")); } - @Test(description = "GET /vApp/{id}/networkConnectionSection", dependsOnMethods = { "testGetVApp" }) - public void testGetNetworkConnectionSection() { - getNetworkConnectionSection(new Function() { - @Override - public NetworkConnectionSection apply(URI uri) { - return vAppClient.getNetworkConnectionSection(uri); - } - }); - } - - // FIXME "Task error: Unable to perform this action. Contact your cloud administrator." - @Test(description = "PUT /vApp/{id}/networkConnectionSection", dependsOnMethods = { "testGetNetworkConnectionSection" }) - public void testModifyNetworkConnectionSection() { - // Look up a network in the Vdc - Set networks = vdc.getAvailableNetworks(); - Reference network = Iterables.getLast(networks); - - // Copy existing section and update fields - NetworkConnectionSection oldSection = vAppClient.getNetworkConnectionSection(vm.getHref()); - NetworkConnectionSection newSection = oldSection.toBuilder() - .networkConnection(NetworkConnection.builder() - .ipAddressAllocationMode(IpAddressAllocationMode.DHCP.toString()) - .network(network.getName()) - .build()) - .build(); - - // The method under test - Task modifyNetworkConnectionSection = vAppClient.modifyNetworkConnectionSection(vm.getHref(), newSection); - assertTrue(retryTaskSuccess.apply(modifyNetworkConnectionSection), String.format(TASK_COMPLETE_TIMELY, "modifyNetworkConnectionSection")); - - // Retrieve the modified section - NetworkConnectionSection modified = vAppClient.getNetworkConnectionSection(vm.getHref()); - - // Check the retrieved object is well formed - checkNetworkConnectionSection(modified); - - // Check the modified section has an extra network connection - assertEquals(modified.getNetworkConnections().size(), newSection.getNetworkConnections().size() + 1); - - // Check the section was modified correctly - assertEquals(modified, newSection, String.format(ENTITY_EQUAL, "NetworkConnectionSection")); - } - @Test(description = "GET /vApp/{id}/networkSection", dependsOnMethods = { "testGetVApp" }) public void testGetNetworkSection() { // The method under test @@ -763,38 +576,6 @@ public class VAppClientLiveTest extends AbstractVAppClientLiveTest { checkNetworkSection(section); } - @Test(description = "GET /vApp/{id}/operatingSystemSection", dependsOnMethods = { "testGetVApp" }) - public void testGetOperatingSystemSection() { - // The method under test - OperatingSystemSection section = vAppClient.getOperatingSystemSection(vm.getHref()); - - // Check the retrieved object is well formed - checkOperatingSystemSection(section); - } - - @Test(description = "PUT /vApp/{id}/operatingSystemSection", dependsOnMethods = { "testGetOperatingSystemSection", "testModifyVirtualHardwareSection" }) - public void testModifyOperatingSystemSection() { - // Create new OperatingSystemSection - OperatingSystemSection newSection = OperatingSystemSection.builder() - .info("") // NOTE Required OVF field, ignored - .id(OSType.RHEL_64.getCode()) - .osType("rhel5_64Guest") - .build(); - - // The method under test - Task modifyOperatingSystemSection = vAppClient.modifyOperatingSystemSection(vm.getHref(), newSection); - assertTrue(retryTaskSuccess.apply(modifyOperatingSystemSection), String.format(TASK_COMPLETE_TIMELY, "modifyOperatingSystemSection")); - - // Retrieve the modified section - OperatingSystemSection modified = vAppClient.getOperatingSystemSection(vm.getHref()); - - // Check the retrieved object is well formed - checkOperatingSystemSection(modified); - - // Check the modified section fields are set correctly - assertEquals(modified.getId(), newSection.getId()); - } - @Test(description = "GET /vApp/{id}/owner", dependsOnMethods = { "testGetVApp" }) public void testGetOwner() { // The method under test @@ -861,78 +642,6 @@ public class VAppClientLiveTest extends AbstractVAppClientLiveTest { assertEquals(modified, newSections, String.format(ENTITY_EQUAL, "ProductSectionList")); } - // FIXME How do we force it to ask a question? - @Test(description = "GET /vApp/{id}/question", dependsOnMethods = { "testDeployVApp" }) - public void testGetPendingQuestion() { - // Power on VApp - vApp = powerOn(vAppURI); - - // TODO how to test? - - // The method under test - VmPendingQuestion question = vAppClient.getPendingQuestion(vm.getHref()); - - // Check the retrieved object is well formed - checkVmPendingQuestion(question); - } - - @Test(description = "POST /vApp/{id}/question/action/answer", dependsOnMethods = { "testGetPendingQuestion" }) - public void testAnswerQuestion() { - // TODO check that the question has been answered (e.g. asking for getPendingQuestion does not - // include our answered question). - - VmPendingQuestion question = vAppClient.getPendingQuestion(vm.getHref()); - List answerChoices = question.getChoices(); - VmQuestionAnswerChoice answerChoice = Iterables.getFirst(answerChoices, null); - assertNotNull(answerChoice, "Question "+question+" must have at least once answer-choice"); - - VmQuestionAnswer answer = VmQuestionAnswer.builder() - .choiceId(answerChoice.getId()) - .questionId(question.getQuestionId()) - .build(); - - vAppClient.answerQuestion(vm.getHref(), answer); - } - - @Test(description = "GET /vApp/{id}/runtimeInfoSection", dependsOnMethods = { "testGetVApp" }) - public void testGetRuntimeInfoSection() { - // The method under test - RuntimeInfoSection section = vAppClient.getRuntimeInfoSection(vm.getHref()); - - // Check the retrieved object is well formed - checkRuntimeInfoSection(section); - } - - // FIXME If still failing, consider escalating? - @Test(description = "GET /vApp/{id}/screen", dependsOnMethods = { "testDeployVApp" }) - public void testGetScreenImage() { - // Power on VApp - vApp = powerOn(vApp); - - // The method under test - byte[] image = vAppClient.getScreenImage(vm.getHref()); - - // Check returned bytes against PNG header magic number - byte[] pngHeaderBytes = new byte[] { (byte) 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }; - assertNotNull(image); - assertTrue(image.length > pngHeaderBytes.length); - for (int i = 0; i < pngHeaderBytes.length; i++) { - assertEquals(image[i], pngHeaderBytes[i], String.format("Image differs from PNG format at byte %d of header", i)); - } - } - - @Test(description = "GET /vApp/{id}/screen/action/acquireTicket", dependsOnMethods = { "testDeployVApp" }) - public void testGetScreenTicket() { - // Power on VApp - vApp = powerOn(vApp); - - // The method under test - ScreenTicket ticket = vAppClient.getScreenTicket(vm.getHref()); - - // Check the retrieved object is well formed - checkScreenTicket(ticket); - } - @Test(description = "GET /vApp/{id}/startupSection", dependsOnMethods = { "testGetVApp" }) public void testGetStartupSection() { // The method under test @@ -963,242 +672,6 @@ public class VAppClientLiveTest extends AbstractVAppClientLiveTest { assertEquals(modified, newSection); } - @Test(description = "GET /vApp/{id}/virtualHardwareSection", dependsOnMethods = { "testGetVApp" }) - public void testGetVirtualHardwareSection() { - // Method under test - VirtualHardwareSection hardware = vAppClient.getVirtualHardwareSection(vm.getHref()); - - // Check the retrieved object is well formed - checkVirtualHardwareSection(hardware); - } - - @Test(description = "PUT /vApp/{id}/virtualHardwareSection", dependsOnMethods = { "testGetVirtualHardwareSection" }) - public void testModifyVirtualHardwareSection() { - // Power off VApp - vApp = powerOff(vApp); - - // Copy existing section and update fields - VirtualHardwareSection oldSection = vAppClient.getVirtualHardwareSection(vm.getHref()); - Set oldItems = oldSection.getItems(); - Set newItems = Sets.newLinkedHashSet(oldItems); - ResourceAllocationSettingData oldMemory = Iterables.find(oldItems, new Predicate() { - @Override - public boolean apply(ResourceAllocationSettingData rasd) { - return rasd.getResourceType() == ResourceAllocationSettingData.ResourceType.MEMORY; - } - }); - ResourceAllocationSettingData newMemory = oldMemory.toBuilder() - .elementName("1024 MB of memory") - .virtualQuantity(new BigInteger("1024")) - .build(); - newItems.remove(oldMemory); - newItems.add(newMemory); - VirtualHardwareSection newSection = oldSection.toBuilder() - .items(newItems) - .build(); - - // The method under test - Task modifyVirtualHardwareSection = vAppClient.modifyVirtualHardwareSection(vm.getHref(), newSection); - assertTrue(retryTaskSuccess.apply(modifyVirtualHardwareSection), String.format(TASK_COMPLETE_TIMELY, "modifyVirtualHardwareSection")); - - // Retrieve the modified section - VirtualHardwareSection modifiedSection = vAppClient.getVirtualHardwareSection(vm.getHref()); - - // Check the retrieved object is well formed - checkVirtualHardwareSection(modifiedSection); - - // Check the modified section fields are set correctly - ResourceAllocationSettingData modifiedMemory = Iterables.find(modifiedSection.getItems(), - new Predicate() { - @Override - public boolean apply(ResourceAllocationSettingData rasd) { - return rasd.getResourceType() == ResourceAllocationSettingData.ResourceType.MEMORY; - } - }); - assertEquals(modifiedMemory.getVirtualQuantity(), new BigInteger("1024")); - assertEquals(modifiedMemory, newMemory); - assertEquals(modifiedSection, newSection); - } - - @Test(description = "GET /vApp/{id}/virtualHardwareSection/cpu", dependsOnMethods = { "testGetVirtualHardwareSection" }) - public void testGetVirtualHardwareSectionCpu() { - // Method under test - RasdItem rasd = vAppClient.getVirtualHardwareSectionCpu(vm.getHref()); - - // Check the retrieved object is well formed - checkResourceAllocationSettingData(rasd); - } - - @Test(description = "PUT /vApp/{id}/virtualHardwareSection/cpu", dependsOnMethods = { "testGetVirtualHardwareSectionCpu" }) - public void testModifyVirtualHardwareSectionCpu() { - // Copy existing section and update fields - RasdItem oldItem = vAppClient.getVirtualHardwareSectionCpu(vm.getHref()); - RasdItem newItem = oldItem.toBuilder() - .elementName("2 virtual CPU(s)") - .virtualQuantity(new BigInteger("2")) - .build(); - - // Method under test - Task modifyVirtualHardwareSectionCpu = vAppClient.modifyVirtualHardwareSectionCpu(vm.getHref(), newItem); - assertTrue(retryTaskSuccess.apply(modifyVirtualHardwareSectionCpu), String.format(TASK_COMPLETE_TIMELY, "modifyVirtualHardwareSectionCpu")); - - // Retrieve the modified section - RasdItem modified = vAppClient.getVirtualHardwareSectionCpu(vm.getHref()); - - // Check the retrieved object - checkResourceAllocationSettingData(modified); - - // Check modified item - assertEquals(modified.getVirtualQuantity(), new BigInteger("2"), - String.format(OBJ_FIELD_EQ, "ResourceAllocationSettingData", "VirtualQuantity", "2", modified.getVirtualQuantity().toString())); - assertEquals(modified, newItem); - } - - @Test(description = "GET /vApp/{id}/virtualHardwareSection/disks", dependsOnMethods = { "testGetVirtualHardwareSection" }) - public void testGetVirtualHardwareSectionDisks() { - // Method under test - RasdItemsList rasdItems = vAppClient.getVirtualHardwareSectionDisks(vm.getHref()); - - // Check the retrieved object is well formed - checkRasdItemsList(rasdItems); - } - - @Test(description = "PUT /vApp/{id}/virtualHardwareSection/disks", dependsOnMethods = { "testGetVirtualHardwareSectionDisks" }) - public void testModifyVirtualHardwareSectionDisks() { - // Copy the existing items list and modify the name of an item - RasdItemsList oldSection = vAppClient.getVirtualHardwareSectionDisks(vm.getHref()); - RasdItemsList newSection = oldSection.toBuilder().build(); - - // Method under test - Task modifyVirtualHardwareSectionDisks = vAppClient.modifyVirtualHardwareSectionDisks(vm.getHref(), newSection); - assertTrue(retryTaskSuccess.apply(modifyVirtualHardwareSectionDisks), String.format(TASK_COMPLETE_TIMELY, "modifyVirtualHardwareSectionDisks")); - - // Retrieve the modified section - RasdItemsList modified = vAppClient.getVirtualHardwareSectionDisks(vm.getHref()); - - // Check the retrieved object is well formed - checkRasdItemsList(modified); - - // TODO What is modifiable? What can we change, so we can assert the change took effect? - // I tried changing "elementName" of one of the items, but it continued to have the old value when looked up post-modify. - // - // List newItems = new ArrayList(oldSection.getItems()); - // ResourceAllocationSettingData item0 = newItems.get(0); - // String item0InstanceId = item0.getInstanceID().getValue(); - // String item0ElementName = item0.getElementName().getValue()+"-"+random.nextInt(Integer.MAX_VALUE); - // newItems.set(0, item0.toBuilder().elementName(newCimString(item0ElementName)).build()); - // RasdItemsList newSection = oldSection.toBuilder() - // .items(newItems) - // .build(); - // ... - // long weight = random.nextInt(Integer.MAX_VALUE); - // ResourceAllocationSettingData newSection = origSection.toBuilder() - // .weight(newCimUnsignedInt(weight)) - // .build(); - // ... - // checkHasMatchingItem("virtualHardwareSection/disk", modified, item0InstanceId, item0ElementName); - } - - @Test(description = "GET /vApp/{id}/virtualHardwareSection/media", dependsOnMethods = { "testGetVirtualHardwareSection" }) - public void testGetVirtualHardwareSectionMedia() { - // Method under test - RasdItemsList rasdItems = vAppClient.getVirtualHardwareSectionMedia(vm.getHref()); - - // Check the retrieved object is well formed - checkRasdItemsList(rasdItems); - } - - @Test(description = "GET /vApp/{id}/virtualHardwareSection/memory", dependsOnMethods = { "testGetVirtualHardwareSection" }) - public void testGetVirtualHardwareSectionMemory() { - // Method under test - RasdItem rasd = vAppClient.getVirtualHardwareSectionCpu(vm.getHref()); - - // Check the retrieved object is well formed - checkResourceAllocationSettingData(rasd); - } - - @Test(description = "PUT /vApp/{id}/virtualHardwareSection/memory", dependsOnMethods = { "testGetVirtualHardwareSectionMemory" }) - public void testModifyVirtualHardwareSectionMemory() { - RasdItem origItem = vAppClient.getVirtualHardwareSectionMemory(vm.getHref()); - RasdItem newItem = origItem.toBuilder() - .elementName("1024 MB of memory") - .virtualQuantity(new BigInteger("1024")) - .build(); - - // Method under test - Task modifyVirtualHardwareSectionMemory = vAppClient.modifyVirtualHardwareSectionMemory(vm.getHref(), newItem); - assertTrue(retryTaskSuccess.apply(modifyVirtualHardwareSectionMemory), String.format(TASK_COMPLETE_TIMELY, "modifyVirtualHardwareSectionMemory")); - - // Retrieve the modified section - RasdItem modified = vAppClient.getVirtualHardwareSectionMemory(vm.getHref()); - - // Check the retrieved object - checkResourceAllocationSettingData(modified); - - // Check modified item - assertEquals(modified.getVirtualQuantity(), new BigInteger("1024"), - String.format(OBJ_FIELD_EQ, "ResourceAllocationSettingData", "VirtualQuantity", "1024", modified.getVirtualQuantity().toString())); - assertEquals(modified, newItem); - } - - @Test(description = "GET /vApp/{id}/virtualHardwareSection/networkCards", dependsOnMethods = { "testGetVirtualHardwareSection" }) - public void testGetVirtualHardwareSectionNetworkCards() { - // Method under test - RasdItemsList rasdItems = vAppClient.getVirtualHardwareSectionNetworkCards(vm.getHref()); - - // Check the retrieved object is well formed - checkRasdItemsList(rasdItems); - } - - @Test(description = "PUT /vApp/{id}/virtualHardwareSection/networkCards", dependsOnMethods = { "testGetVirtualHardwareSectionNetworkCards" }) - public void testModifyVirtualHardwareSectionNetworkCards() { - RasdItemsList oldSection = vAppClient.getVirtualHardwareSectionNetworkCards(vm.getHref()); - RasdItemsList newSection = oldSection.toBuilder().build(); - - // Method under test - Task modifyVirtualHardwareSectionNetworkCards = vAppClient.modifyVirtualHardwareSectionNetworkCards(vm.getHref(), newSection); - assertTrue(retryTaskSuccess.apply(modifyVirtualHardwareSectionNetworkCards), String.format(TASK_COMPLETE_TIMELY, "modifyVirtualHardwareSectionNetworkCards")); - - // Retrieve the modified section - RasdItemsList modified = vAppClient.getVirtualHardwareSectionNetworkCards(vm.getHref()); - - // Check the retrieved object is well formed - checkRasdItemsList(modified); - - // TODO What is modifiable? What can we change, so we can assert the change took effect? - // I tried changing "elementName" of one of the items, but it continued to have the old value when looked up post-modify. - // See the description in testModifyVirtualHardwareSectionDisks - } - - @Test(description = "GET /vApp/{id}/virtualHardwareSection/serialPorts", dependsOnMethods = { "testGetVirtualHardwareSection" }) - public void testGetVirtualHardwareSectionSerialPorts() { - // Method under test - RasdItemsList rasdItems = vAppClient.getVirtualHardwareSectionSerialPorts(vm.getHref()); - - // Check the retrieved object is well formed - checkRasdItemsList(rasdItems); - } - - @Test(description = "PUT /vApp/{id}/virtualHardwareSection/serialPorts", dependsOnMethods = { "testGetVirtualHardwareSectionSerialPorts" }) - public void testModifyVirtualHardwareSectionSerialPorts() { - RasdItemsList oldSection = vAppClient.getVirtualHardwareSectionSerialPorts(vm.getHref()); - RasdItemsList newSection = oldSection.toBuilder().build(); - - // Method under test - Task modifyVirtualHardwareSectionSerialPorts = vAppClient.modifyVirtualHardwareSectionSerialPorts(vm.getHref(), newSection); - assertTrue(retryTaskSuccess.apply(modifyVirtualHardwareSectionSerialPorts), String.format(TASK_COMPLETE_TIMELY, "modifyVirtualHardwareSectionSerialPorts")); - - // Retrieve the modified section - RasdItemsList modified = vAppClient.getVirtualHardwareSectionSerialPorts(vm.getHref()); - - // Check the retrieved object is well formed - checkRasdItemsList(modified); - - // TODO What is modifiable? What can we change, so we can assert the change took effect? - // I tried changing "elementName" of one of the items, but it continued to have the old value when looked up post-modify. - // See the description in testModifyVirtualHardwareSectionDisks - } - @Test(description = "PUT /vApp/{id}/metadata", dependsOnMethods = { "testGetVApp" }) public void testSetMetadataValue() { key = name("key-"); diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppTemplateClientLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppTemplateClientLiveTest.java index 85b5607211..faf4c07531 100644 --- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppTemplateClientLiveTest.java +++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VAppTemplateClientLiveTest.java @@ -90,7 +90,7 @@ public class VAppTemplateClientLiveTest extends AbstractVAppClientLiveTest { private String key; private String val; - @AfterClass(alwaysRun = true) + @AfterClass(alwaysRun = true, dependsOnMethods = { "cleanUpEnvironment" }) protected void tidyUp() { if (key != null) { try { @@ -385,7 +385,7 @@ public class VAppTemplateClientLiveTest extends AbstractVAppClientLiveTest { Reference network = Iterables.getLast(networks); // Copy existing section and update fields - NetworkConnectionSection oldSection = vAppClient.getNetworkConnectionSection(vm.getHref()); + NetworkConnectionSection oldSection = vAppTemplateClient.getNetworkConnectionSection(vm.getHref()); NetworkConnectionSection newSection = oldSection.toBuilder() .networkConnection(NetworkConnection.builder() .ipAddressAllocationMode(IpAddressAllocationMode.DHCP.toString()) diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VmClientExpectTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VmClientExpectTest.java new file mode 100644 index 0000000000..79ba42fee1 --- /dev/null +++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VmClientExpectTest.java @@ -0,0 +1,1275 @@ +/* + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + *(Link.builder().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(Link.builder().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.vcloud.director.v1_5.features; + +import static org.testng.Assert.assertEquals; + +import java.net.URI; + +import org.jclouds.dmtf.ovf.NetworkSection; +import org.jclouds.dmtf.ovf.StartupSection; +import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType; +import org.jclouds.vcloud.director.v1_5.domain.Error; +import org.jclouds.vcloud.director.v1_5.domain.Link; +import org.jclouds.vcloud.director.v1_5.domain.Owner; +import org.jclouds.vcloud.director.v1_5.domain.ProductSectionList; +import org.jclouds.vcloud.director.v1_5.domain.RasdItemsList; +import org.jclouds.vcloud.director.v1_5.domain.Reference; +import org.jclouds.vcloud.director.v1_5.domain.ScreenTicket; +import org.jclouds.vcloud.director.v1_5.domain.Task; +import org.jclouds.vcloud.director.v1_5.domain.Vm; +import org.jclouds.vcloud.director.v1_5.domain.VmPendingQuestion; +import org.jclouds.vcloud.director.v1_5.domain.VmQuestionAnswer; +import org.jclouds.vcloud.director.v1_5.domain.dmtf.RasdItem; +import org.jclouds.vcloud.director.v1_5.domain.params.ControlAccessParams; +import org.jclouds.vcloud.director.v1_5.domain.params.DeployVAppParams; +import org.jclouds.vcloud.director.v1_5.domain.params.MediaInsertOrEjectParams; +import org.jclouds.vcloud.director.v1_5.domain.params.RelocateParams; +import org.jclouds.vcloud.director.v1_5.domain.params.UndeployVAppParams; +import org.jclouds.vcloud.director.v1_5.domain.section.GuestCustomizationSection; +import org.jclouds.vcloud.director.v1_5.domain.section.LeaseSettingsSection; +import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConfigSection; +import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConnectionSection; +import org.jclouds.vcloud.director.v1_5.domain.section.OperatingSystemSection; +import org.jclouds.vcloud.director.v1_5.domain.section.RuntimeInfoSection; +import org.jclouds.vcloud.director.v1_5.domain.section.VirtualHardwareSection; +import org.jclouds.vcloud.director.v1_5.internal.VCloudDirectorAdminClientExpectTest; +import org.jclouds.vcloud.director.v1_5.user.VCloudDirectorClient; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.testng.internal.annotations.Sets; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Multimaps; + +/** + * Allows us to test the {@link VmClient} via its side effects. + * + * @author grkvlt@apache.org + */ +@Test(groups = { "unit", "user" }, singleThreaded = true, testName = "VmClientExpectTest") +public class VmClientExpectTest extends VCloudDirectorAdminClientExpectTest { + + private String vmId = "vm-d0e2b6b9-4381-4ddc-9572-cdfae54059be"; + private URI vmURI = URI.create(endpoint + vmId); + + @BeforeClass + public void before() { + } + + @Test(enabled = false)//TODO + public void testGetVm() { + VCloudDirectorClient client = orderedRequestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("GET", vmId) + .acceptMedia(VCloudDirectorMediaType.VM) + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vm/vm.xml", VCloudDirectorMediaType.VM) + .httpResponseBuilder().build()); + + Vm expected = getVm(); + + assertEquals(client.getVmClient().getVm(vmURI), expected); + } + + @Test(enabled = false) + public void testModifyVm() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("PUT", vmId) + .xmlFilePayload("/vm/modifyVm.xml", VCloudDirectorMediaType.VM) + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vm/modifiedVm.xml", VCloudDirectorMediaType.VM) + .httpResponseBuilder().build()); + + Vm modified = getVm(); + modified.setName("new-name"); + modified.setDescription("New Description"); + + Task expected = modifyVmTask(); + + assertEquals(client.getVmClient().modifyVm(vmURI, modified), expected); + } + + @Test(enabled = false) + public void testDeleteVm() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("DELETE", vmId) + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vm/deleteVmTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + Task expected = deleteVmTask(); + + assertEquals(client.getVmClient().deleteVm(vmURI), expected); + } + + @Test(enabled = false) + public void testConsolidateVm() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("POST", vmId + "/action/consolidate") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vm/consolidateVmTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + Task expected = consolidateVmTask(); + + assertEquals(client.getVmClient().consolidateVm(vmURI), expected); + } + + @Test(enabled = false) + public void testDeploy() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("POST", vmId + "/action/deploy") + .xmlFilePayload("/vm/deployParams.xml", VCloudDirectorMediaType.DEPLOY_VAPP_PARAMS) + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/deployTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + DeployVAppParams params = DeployVAppParams.builder() + .build(); + + Task expected = deployTask(); + + assertEquals(client.getVmClient().deploy(vmURI, params), expected); + } + + @Test(enabled = false) + public void testDiscardSuspendedState() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("POST", vmId + "/action/discardSuspendedState") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/discardSuspendedStateTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + Task expected = discardSuspendedStateTask(); + + assertEquals(client.getVmClient().discardSuspendedState(vmURI), expected); + } + + @Test(enabled = false) + public void testInstallVMwareTools() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("POST", vmId + "/action/installVMwareTools") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/installVMwareToolsTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + Task expected = installVMwareToolsTask(); + + assertEquals(client.getVmClient().installVMwareTools(vmURI), expected); + } + + @Test(enabled = false) + public void testRelocate() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("POST", vmId + "/action/relocate") + .xmlFilePayload("/vApp/relocateParams.xml", VCloudDirectorMediaType.RELOCATE_VM_PARAMS) + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/relocateTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + RelocateParams params = RelocateParams.builder() + .build(); + + Task expected = relocateTask(); + + assertEquals(client.getVmClient().relocateVm(vmURI, params), expected); + } + + @Test(enabled = false) + public void testUndeploy() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("POST", vmId + "/action/undeploy") + .xmlFilePayload("/vApp/undeployParams.xml", VCloudDirectorMediaType.UNDEPLOY_VAPP_PARAMS) + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/undeployTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + UndeployVAppParams params = UndeployVAppParams.builder() + .build(); + + Task expected = undeployTask(); + + assertEquals(client.getVmClient().undeploy(vmURI, params), expected); + } + + @Test(enabled = false) + public void testUpgradeHardwareVersion() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("POST", vmId + "/action/upgradeHardwareVersion") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/upgradeHardwareVersionTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + Task expected = upgradeHardwareVersionTask(); + + assertEquals(client.getVmClient().upgradeHardwareVersion(vmURI), expected); + } + + @Test(enabled = false) + public void testPowerOff() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("POST", vmId + "/power/action/powerOff") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/powerOffTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + Task expected = powerOffTask(); + + assertEquals(client.getVmClient().powerOff(vmURI), expected); + } + + @Test(enabled = false) + public void testPowerOn() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("POST", vmId + "/power/action/powerOn") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/powerOnTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + Task expected = powerOnTask(); + + assertEquals(client.getVmClient().powerOn(vmURI), expected); + } + + @Test(enabled = false) + public void testReboot() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("POST", vmId + "/power/action/reboot") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/rebootTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + Task expected = rebootTask(); + + assertEquals(client.getVmClient().reboot(vmURI), expected); + } + + @Test(enabled = false) + public void testReset() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("POST", vmId + "/power/action/reset") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/resetTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + Task expected = resetTask(); + + assertEquals(client.getVmClient().reset(vmURI), expected); + } + + @Test(enabled = false) + public void testShutdown() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("POST", vmId + "/power/action/shutdown") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/shutdownTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + Task expected = shutdownTask(); + + assertEquals(client.getVmClient().shutdown(vmURI), expected); + } + + @Test(enabled = false) + public void testSuspend() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("POST", vmId + "/power/action/suspend") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/suspend.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + Task expected = suspendTask(); + + assertEquals(client.getVmClient().suspend(vmURI), expected); + } + + @Test(enabled = false) + public void testGetGuestCustomizationSection() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("GET", vmId + "/guestCustomizationSection") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/getGuestCustomizationSection.xml", VCloudDirectorMediaType.GUEST_CUSTOMIZATION_SECTION) + .httpResponseBuilder().build()); + + GuestCustomizationSection expected = getGuestCustomizationSection(); + + assertEquals(client.getVmClient().getGuestCustomizationSection(vmURI), expected); + } + + @Test(enabled = false) + public void testModifyGuestCustomizationSection() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("PUT", vmId + "/guestCustomizationSection") + .xmlFilePayload("/vApp/modifyGuestCustomizationSection.xml", VCloudDirectorMediaType.GUEST_CUSTOMIZATION_SECTION) + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/modifyGuestCustomizationSectionTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + GuestCustomizationSection section = getGuestCustomizationSection().toBuilder() + .build(); + + Task expected = modifyGuestCustomizationSectionTask(); + + assertEquals(client.getVmClient().modifyGuestCustomizationSection(vmURI, section), expected); + } + + @Test(enabled = false) + public void testEjectMedia() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("PUT", vmId + "/media/action/ejectMedia") + .xmlFilePayload("/vApp/ejectMediaParams.xml", VCloudDirectorMediaType.MEDIA_PARAMS) + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/ejectMediaTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + MediaInsertOrEjectParams params = MediaInsertOrEjectParams.builder() + .build(); + + Task expected = ejectMediaTask(); + + assertEquals(client.getVmClient().ejectMedia(vmURI, params), expected); + } + + @Test(enabled = false) + public void testInsertMedia() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("PUT", vmId + "/media/action/insertMedia") + .xmlFilePayload("/vApp/insertMediaParams.xml", VCloudDirectorMediaType.MEDIA_PARAMS) + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/insertMediaTask.xml", VCloudDirectorMediaType.VAPP) + .httpResponseBuilder().build()); + + MediaInsertOrEjectParams params = MediaInsertOrEjectParams.builder() + .build(); + + Task expected = insertMediaTask(); + + assertEquals(client.getVmClient().insertMedia(vmURI, params), expected); + } + + @Test(enabled = false) + public void testGetNetworkConnectionSection() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("GET", vmId + "/networkConnectionSection") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/getNetworkConnectionSection.xml", VCloudDirectorMediaType.NETWORK_CONNECTION_SECTION) + .httpResponseBuilder().build()); + + NetworkConnectionSection expected = getNetworkConnectionSection(); + + assertEquals(client.getVmClient().getNetworkConnectionSection(vmURI), expected); + } + + @Test(enabled = false) + public void testModifyNetworkConnectionSection() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("PUT", vmId + "/networkConnectionSection") + .xmlFilePayload("/vApp/modifyNetworkConnectionSection.xml", VCloudDirectorMediaType.NETWORK_CONNECTION_SECTION) + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/modifyNetworkConnectionSectionTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + NetworkConnectionSection section = getNetworkConnectionSection().toBuilder() + .build(); + + Task expected = modifyNetworkConnectionSectionTask(); + + assertEquals(client.getVmClient().modifyNetworkConnectionSection(vmURI, section), expected); + } + + @Test(enabled = false) + public void testGetOperatingSystemSection() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("GET", vmId + "/operatingSystemSection") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/getOperatingSystemSection.xml", VCloudDirectorMediaType.OPERATING_SYSTEM_SECTION) + .httpResponseBuilder().build()); + + OperatingSystemSection expected = getOperatingSystemSection(); + + assertEquals(client.getVmClient().getOperatingSystemSection(vmURI), expected); + } + + @Test(enabled = false) + public void testModifyOperatingSystemSection() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("PUT", vmId + "/operatingSystemSection") + .xmlFilePayload("/vApp/modifyOperatingSystemSection.xml", VCloudDirectorMediaType.OPERATING_SYSTEM_SECTION) + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/modifyOperatingSystemSectionTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + OperatingSystemSection section = getOperatingSystemSection().toBuilder() + .build(); + + Task expected = modifyOperatingSystemSectionTask(); + + assertEquals(client.getVmClient().modifyOperatingSystemSection(vmURI, section), expected); + } + + @Test(enabled = false) + public void testGetProductSections() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("GET", vmId + "/productSections") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/getProductSections.xml", VCloudDirectorMediaType.PRODUCT_SECTION_LIST) + .httpResponseBuilder().build()); + + ProductSectionList expected = getProductSections(); + + assertEquals(client.getVmClient().getProductSections(vmURI), expected); + } + + @Test(enabled = false) + public void testModifyProductSections() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("PUT", vmId + "/productSections") + .xmlFilePayload("/vApp/modifyProductSections.xml", VCloudDirectorMediaType.PRODUCT_SECTION_LIST) + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/modifyProductSections.xml", VCloudDirectorMediaType.VAPP) + .httpResponseBuilder().build()); + + Task expected = modifyProductSectionsTask(); + + assertEquals(client.getVmClient().modifyProductSections(vmURI, null), expected); + } + + @Test(enabled = false) + public void testGetPendingQuestion() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("GET", vmId + "/question") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/getPendingQuestion.xml", VCloudDirectorMediaType.VM_PENDING_QUESTION) + .httpResponseBuilder().build()); + + VmPendingQuestion expected = getPendingQuestion(); + + assertEquals(client.getVmClient().getPendingQuestion(vmURI), expected); + } + + @Test(enabled = false) + public void testAnswerQuestion() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("PUT", vmId + "/question/action/answer") + .xmlFilePayload("/vApp/answerQuestion.xml", VCloudDirectorMediaType.VM_PENDING_ANSWER) + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .httpResponseBuilder().statusCode(204).build()); + + VmQuestionAnswer answer = null; // = VmQuestionAnswer.builder(); +// .build; + + client.getVmClient().answerQuestion(vmURI, answer); + } + + @Test(enabled = false) + public void testGetRuntimeInfoSection() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("GET", vmId + "/runtimeInfoSection") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/getRuntimeInfoSection.xml", VCloudDirectorMediaType.RUNTIME_INFO_SECTION) + .httpResponseBuilder().build()); + + RuntimeInfoSection expected = getRuntimeInfoSection(); + + assertEquals(client.getVmClient().getRuntimeInfoSection(vmURI), expected); + } + + @Test(enabled = false) + public void testGetScreenImage() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("GET", vmId + "/screen") + .acceptMedia(VCloudDirectorMediaType.ANY_IMAGE) + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .httpResponseBuilder() + .headers(Multimaps.forMap(ImmutableMap.of("Content-Type", "image/png"))) + .message(new String(getScreenImage())) + .build()); + + byte[] expected = getScreenImage(); + + assertEquals(client.getVmClient().getScreenImage(vmURI), expected); + } + + @Test(enabled = false) + public void testGetScreenTicket() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("POST", vmId + "/screen/action/acquireTicket") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/getScreenTicket.xml", VCloudDirectorMediaType.SCREEN_TICKET) + .httpResponseBuilder().build()); + + ScreenTicket expected = getScreenTicket(); + + assertEquals(client.getVmClient().getScreenTicket(vmURI), expected); + } + + @Test(enabled = false) + public void testGetVirtualHardwareSection() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("GET", vmId + "/virtualHardwareSection") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/getVirtualHardwareSection.xml", VCloudDirectorMediaType.VIRTUAL_HARDWARE_SECTION) + .httpResponseBuilder().build()); + + VirtualHardwareSection expected = getVirtualHardwareSection(); + + assertEquals(client.getVmClient().getVirtualHardwareSection(vmURI), expected); + } + + @Test(enabled = false) + public void testModifyVirtualHardwareSection() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("PUT", vmId + "/virtualHardwareSection") + .xmlFilePayload("/vApp/modifyVirtualHardwareSection.xml", VCloudDirectorMediaType.VIRTUAL_HARDWARE_SECTION) + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/modifyVirtualHardwareSectionTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + VirtualHardwareSection section = getVirtualHardwareSection().toBuilder() + .build(); + + Task expected = modifyVirtualHardwareSectionTask(); + + assertEquals(client.getVmClient().modifyVirtualHardwareSection(vmURI, section), expected); + } + + @Test(enabled = false) + public void testGetVirtualHardwareSectionCpu() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("GET", vmId + "/virtualHardwareSection/cpu") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/getVirtualHardwareSectionCpu.xml", VCloudDirectorMediaType.OVF_RASD_ITEM) + .httpResponseBuilder().build()); + + RasdItem expected = getVirtualHardwareSectionCpu(); + + assertEquals(client.getVmClient().getVirtualHardwareSectionCpu(vmURI), expected); + } + + @Test(enabled = false) + public void testModifyVirtualHardwareSectionCpu() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("", vmId + "/virtualHardwareSection/cpu") + .xmlFilePayload("/vApp/modifyVirtualHardwareSectionCpu.xml", VCloudDirectorMediaType.OVF_RASD_ITEM) + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/modifyVirtualHardwareSectionCpuTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + RasdItem cpu = getVirtualHardwareSectionCpu(); // .toBuilder(); +// .build(); + + Task expected = modifyVirtualHardwareSectionCpuTask(); + + assertEquals(client.getVmClient().modifyVirtualHardwareSectionCpu(vmURI, cpu), expected); + } + + @Test(enabled = false) + public void testGetVirtualHardwareSectionDisks() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("GET", vmId + "/virtualHardwareSection/disks") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/getVirtualHardwareSectionDisks.xml", VCloudDirectorMediaType.OVF_RASD_ITEMS_LIST) + .httpResponseBuilder().build()); + + RasdItemsList expected = getVirtualHardwareSectionDisks(); + + assertEquals(client.getVmClient().getVirtualHardwareSectionDisks(vmURI), expected); + } + + @Test(enabled = false) + public void testModifyVirtualHardwareSectionDisks() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("PUT", vmId + "/virtualHardwareSection/disks") + .xmlFilePayload("/vApp/modifyVirtualHardwareSectionDisks.xml", VCloudDirectorMediaType.OVF_RASD_ITEMS_LIST) + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/modifyVirtualHardwareSectionDisksTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + RasdItemsList disks = getVirtualHardwareSectionDisks().toBuilder() + .build(); + + Task expected = modifyVirtualHardwareSectionDisksTask(); + + assertEquals(client.getVmClient().modifyVirtualHardwareSectionDisks(vmURI, disks), expected); + } + + @Test(enabled = false) + public void testGetVirtualHardwareSectionMedia() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("GET", vmId + "/virtualHardwareSection/media") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/getVirtualHardwareSectionMedia.xml", VCloudDirectorMediaType.OVF_RASD_ITEMS_LIST) + .httpResponseBuilder().build()); + + RasdItemsList expected = getVirtualHardwareSectionMedia(); + + assertEquals(client.getVmClient().getVirtualHardwareSectionMedia(vmURI), expected); + } + + @Test(enabled = false) + public void testGetVirtualHardwareSectionMemory() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("GET", vmId + "/virtualHardwareSection/memory") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/getVirtualHardwareSectionMemory.xml", VCloudDirectorMediaType.OVF_RASD_ITEM) + .httpResponseBuilder().build()); + + RasdItem expected = getVirtualHardwareSectionMemory(); + + assertEquals(client.getVmClient().getVirtualHardwareSectionMemory(vmURI), expected); + } + + @Test(enabled = false) + public void testModifyVirtualHardwareSectionMemory() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("PUT", vmId + "/virtualHardwareSection/memory") + .xmlFilePayload("/vApp/modifyVirtualHardwareSectionMemory.xml", VCloudDirectorMediaType.VAPP) + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/modifyVirtualHardwareSectionMemoryTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + RasdItem memory = getVirtualHardwareSectionCpu(); // .toBuilder(); +// .build(); + + Task expected = modifyVirtualHardwareSectionMemoryTask(); + + assertEquals(client.getVmClient().modifyVirtualHardwareSectionMemory(vmURI, memory), expected); + } + + @Test(enabled = false) + public void testGetVirtualHardwareSectionNetworkCards() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("GET", vmId + "/virtualHardwareSection/networkCards") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/getVirtualHardwareSectionNetworkCards.xml", VCloudDirectorMediaType.OVF_RASD_ITEMS_LIST) + .httpResponseBuilder().build()); + + RasdItemsList expected = getVirtualHardwareSectionNetworkCards(); + + assertEquals(client.getVmClient().getVirtualHardwareSectionNetworkCards(vmURI), expected); + } + + @Test(enabled = false) + public void testModifyVirtualHardwareSectionNetworkCards() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("PUT", vmId + "/virtualHardwareSection/networkCards") + .xmlFilePayload("/vApp/modifyVirtualHardwareSectionNetworkCards.xml", VCloudDirectorMediaType.OVF_RASD_ITEMS_LIST) + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/modifyVirtualHardwareSectionNetworkCardsTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + RasdItemsList networkCards = getVirtualHardwareSectionNetworkCards().toBuilder() + .build(); + + Task expected = modifyVirtualHardwareSectionNetworkCardsTask(); + + assertEquals(client.getVmClient().modifyVirtualHardwareSectionNetworkCards(vmURI, networkCards), expected); + } + + @Test(enabled = false) + public void testGetVirtualHardwareSectionSerialPorts() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("GET", vmId + "/virtualHardwareSection/serialPorts") + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/getVirtualHardwareSectionSerialPorts.xml", VCloudDirectorMediaType.VAPP) + .httpResponseBuilder().build()); + + RasdItemsList expected = getVirtualHardwareSectionSerialPorts(); + + assertEquals(client.getVmClient().getVirtualHardwareSectionSerialPorts(vmURI), expected); + } + + @Test(enabled = false) + public void testModifyVirtualHardwareSectionSerialPorts() { + VCloudDirectorClient client = requestsSendResponses(loginRequest, sessionResponse, + new VcloudHttpRequestPrimer() + .apiCommand("PUT", vmId + "/virtualHardwareSection/serialPorts") + .xmlFilePayload("/vApp/modifyVirtualHardwareSectionSerialPorts.xml", VCloudDirectorMediaType.OVF_RASD_ITEMS_LIST) + .acceptAnyMedia() + .httpRequestBuilder().build(), + new VcloudHttpResponsePrimer() + .xmlFilePayload("/vApp/modifyVirtualHardwareSectionSerialPortsTask.xml", VCloudDirectorMediaType.TASK) + .httpResponseBuilder().build()); + + RasdItemsList serialPorts = getVirtualHardwareSectionSerialPorts().toBuilder() + .build(); + + Task expected = modifyVirtualHardwareSectionSerialPortsTask(); + + assertEquals(client.getVmClient().modifyVirtualHardwareSectionSerialPorts(vmURI, serialPorts), expected); + } + + public static Vm getVm() { + // FIXME Does not match XML + Vm vm = Vm.builder() + .href(URI.create("https://mycloud.greenhousedata.com/api/vApp/vm-d0e2b6b9-4381-4ddc-9572-cdfae54059be")) +// .link(Link.builder() +// .href(URI.create()) +// .build()) + .build(); + +// +// +// +// +// +// +// +// +// +// +// + + return vm; + } + + public static Task modifyVmTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static Task deleteVmTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static Task consolidateVmTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static ControlAccessParams controlAccessParams() { + ControlAccessParams params = ControlAccessParams.builder() + .build(); + + return params; + } + + public static Task deployTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static Task discardSuspendedStateTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static Task installVMwareToolsTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static Task recomposeVmTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static Task relocateTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static Task undeployTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static Task upgradeHardwareVersionTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static Task powerOffTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static Task powerOnTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static Task rebootTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static Task resetTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static Task shutdownTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static Task suspendTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static ControlAccessParams getControlAccessParams() { + ControlAccessParams params = ControlAccessParams.builder() + .build(); + + return params; + } + + public static GuestCustomizationSection getGuestCustomizationSection() { + GuestCustomizationSection section = GuestCustomizationSection.builder() + .build(); + + return section; + } + + public static Task modifyGuestCustomizationSectionTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static LeaseSettingsSection getLeaseSettingsSection() { + LeaseSettingsSection section = LeaseSettingsSection.builder() + .build(); + + return section; + } + + public static Task modifyLeaseSettingsSectionTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static Task ejectMediaTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static Task insertMediaTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static NetworkConfigSection getNetworkConfigSection() { + NetworkConfigSection section = NetworkConfigSection.builder() + .build(); + + return section; + } + + public static Task modifyNetworkConfigSectionTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static NetworkConnectionSection getNetworkConnectionSection() { + NetworkConnectionSection section = NetworkConnectionSection.builder() + .build(); + + return section; + } + + public static Task modifyNetworkConnectionSectionTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static NetworkSection getNetworkSection() { + NetworkSection section = NetworkSection.builder() + .build(); + + return section; + } + + public static OperatingSystemSection getOperatingSystemSection() { + OperatingSystemSection section = OperatingSystemSection.builder() + .build(); + + return section; + } + + public static Task modifyOperatingSystemSectionTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static Owner getOwner() { + Owner owner = Owner.builder() + .build(); + + return owner; + } + + public static Task modifyOwnerTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static ProductSectionList getProductSections() { + ProductSectionList sectionItems = ProductSectionList.builder() + .build(); + + return sectionItems; + } + + public static Task modifyProductSectionsTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static VmPendingQuestion getPendingQuestion() { + VmPendingQuestion question = VmPendingQuestion.builder() + .build(); + + return question; + } + + public static VmQuestionAnswer answerQuestion() { + VmQuestionAnswer answer = null; // = VmQuestionAnswer.builder() +// .build(); + + return answer; + } + + public static RuntimeInfoSection getRuntimeInfoSection() { + RuntimeInfoSection section = RuntimeInfoSection.builder() + .build(); + + return section; + } + + public static byte[] getScreenImage() { + byte[] image = new byte[0]; + + return image; + } + + public static ScreenTicket getScreenTicket() { + ScreenTicket ticket = null; // = ScreenTicket.builder(); +// .build(); + + return ticket; + } + + public static StartupSection getStartupSection() { + StartupSection section = null; // = StartupSection.builder(); +// .build(); + + return section; + } + + public static Task modifyStartupSectionTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static VirtualHardwareSection getVirtualHardwareSection() { + VirtualHardwareSection section = VirtualHardwareSection.builder() + .build(); + + return section; + } + + public static Task modifyVirtualHardwareSectionTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static RasdItem getVirtualHardwareSectionCpu() { + RasdItem cpu = RasdItem.builder() + .build(); + + return cpu; + } + + public static Task modifyVirtualHardwareSectionCpuTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static RasdItemsList getVirtualHardwareSectionDisks() { + RasdItemsList disks = RasdItemsList.builder() + .build(); + + return disks; + } + + public static Task modifyVirtualHardwareSectionDisksTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static RasdItemsList getVirtualHardwareSectionMedia() { + RasdItemsList media = RasdItemsList.builder() + .build(); + + return media; + } + + public static RasdItem getVirtualHardwareSectionMemory() { + RasdItem memory = RasdItem.builder() + .build(); + + return memory; + } + + public static Task modifyVirtualHardwareSectionMemoryTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static RasdItemsList getVirtualHardwareSectionNetworkCards() { + RasdItemsList networkCards = RasdItemsList.builder() + .build(); + + return networkCards; + } + + public static Task modifyVirtualHardwareSectionNetworkCardsTask() { + Task task = Task.builder() + .build(); + + return task; + } + + public static RasdItemsList getVirtualHardwareSectionSerialPorts() { + RasdItemsList serialPorts = RasdItemsList.builder() + .build(); + + return serialPorts; + } + + public static Task modifyVirtualHardwareSectionSerialPortsTask() { + return task("id", "name", "description", "status", "operation", "operationName", "startTime"); + } + + /** Used by other methods to create a custom {@link Task} object. */ + private static Task task(String taskId, String name, String description, String status, String operation, String operationName, String startTime) { + Task task = Task.builder() + .error(Error.builder().build()) + .org(Reference.builder().build()) + .owner(Reference.builder().build()) + .user(Reference.builder().build()) + .params(null) + .progress(0) + .status(status) + .operation(operation) + .operationName(operationName) + .startTime(dateService.iso8601DateParse(startTime)) + .endTime(null) + .expiryTime(null) + .tasks(Sets.newLinkedHashSet()) + .description(description) + .name(name) + .id("urn:vcloud:" + taskId) + .href(URI.create(endpoint + "/task/" + taskId)) + .links(Sets.newLinkedHashSet()) + .build(); + + return task; + } +} diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VmClientLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VmClientLiveTest.java new file mode 100644 index 0000000000..bcb4f09413 --- /dev/null +++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/features/VmClientLiveTest.java @@ -0,0 +1,1014 @@ +/* + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + *(Link.builder().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(Link.builder().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.vcloud.director.v1_5.features; + +import static com.google.common.base.Predicates.and; +import static com.google.common.collect.Iterables.contains; +import static com.google.common.collect.Iterables.find; +import static com.google.common.collect.Iterables.getFirst; +import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.CORRECT_VALUE_OBJECT_FMT; +import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.ENTITY_EQUAL; +import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.NOT_EMPTY_OBJECT_FMT; +import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.OBJ_FIELD_EQ; +import static org.jclouds.vcloud.director.v1_5.VCloudDirectorLiveTestConstants.TASK_COMPLETE_TIMELY; +import static org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType.MEDIA; +import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkGuestCustomizationSection; +import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadata; +import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataFor; +import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataKeyAbsentFor; +import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataValue; +import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataValueFor; +import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkNetworkConnectionSection; +import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkOperatingSystemSection; +import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkProductSectionList; +import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkRasdItemsList; +import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkResourceAllocationSettingData; +import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkRuntimeInfoSection; +import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkScreenTicket; +import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkVirtualHardwareSection; +import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkVm; +import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkVmPendingQuestion; +import static org.jclouds.vcloud.director.v1_5.predicates.LinkPredicates.relEquals; +import static org.jclouds.vcloud.director.v1_5.predicates.LinkPredicates.typeEquals; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; + +import java.math.BigInteger; +import java.net.URI; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.jclouds.dmtf.cim.OSType; +import org.jclouds.dmtf.cim.ResourceAllocationSettingData; +import org.jclouds.dmtf.ovf.MsgType; +import org.jclouds.dmtf.ovf.ProductSection; +import org.jclouds.io.Payloads; +import org.jclouds.vcloud.director.v1_5.AbstractVAppClientLiveTest; +import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType; +import org.jclouds.vcloud.director.v1_5.domain.Checks; +import org.jclouds.vcloud.director.v1_5.domain.Link; +import org.jclouds.vcloud.director.v1_5.domain.Media; +import org.jclouds.vcloud.director.v1_5.domain.Metadata; +import org.jclouds.vcloud.director.v1_5.domain.MetadataEntry; +import org.jclouds.vcloud.director.v1_5.domain.MetadataValue; +import org.jclouds.vcloud.director.v1_5.domain.ProductSectionList; +import org.jclouds.vcloud.director.v1_5.domain.RasdItemsList; +import org.jclouds.vcloud.director.v1_5.domain.Reference; +import org.jclouds.vcloud.director.v1_5.domain.ResourceEntity.Status; +import org.jclouds.vcloud.director.v1_5.domain.ScreenTicket; +import org.jclouds.vcloud.director.v1_5.domain.Task; +import org.jclouds.vcloud.director.v1_5.domain.VApp; +import org.jclouds.vcloud.director.v1_5.domain.Vm; +import org.jclouds.vcloud.director.v1_5.domain.VmPendingQuestion; +import org.jclouds.vcloud.director.v1_5.domain.VmQuestionAnswer; +import org.jclouds.vcloud.director.v1_5.domain.VmQuestionAnswerChoice; +import org.jclouds.vcloud.director.v1_5.domain.dmtf.RasdItem; +import org.jclouds.vcloud.director.v1_5.domain.network.NetworkConnection; +import org.jclouds.vcloud.director.v1_5.domain.network.NetworkConnection.IpAddressAllocationMode; +import org.jclouds.vcloud.director.v1_5.domain.params.DeployVAppParams; +import org.jclouds.vcloud.director.v1_5.domain.params.MediaInsertOrEjectParams; +import org.jclouds.vcloud.director.v1_5.domain.params.RelocateParams; +import org.jclouds.vcloud.director.v1_5.domain.params.UndeployVAppParams; +import org.jclouds.vcloud.director.v1_5.domain.query.QueryResultRecordType; +import org.jclouds.vcloud.director.v1_5.domain.query.QueryResultRecords; +import org.jclouds.vcloud.director.v1_5.domain.section.GuestCustomizationSection; +import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConnectionSection; +import org.jclouds.vcloud.director.v1_5.domain.section.OperatingSystemSection; +import org.jclouds.vcloud.director.v1_5.domain.section.RuntimeInfoSection; +import org.jclouds.vcloud.director.v1_5.domain.section.VirtualHardwareSection; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; +import com.google.common.collect.Sets; + +/** + * Tests behavior of the {@link VmClient}. + * + * @author grkvlt@apache.org + */ +@Test(groups = { "live", "user" }, singleThreaded = true, testName = "VmClientLiveTest") +public class VmClientLiveTest extends AbstractVAppClientLiveTest { + + private MetadataValue metadataValue; + private String key; + private URI testUserURI; + private boolean mediaCreated = false; + private boolean testUserCreated = false; + + @BeforeClass(alwaysRun = true, dependsOnMethods = { "setupRequiredClients" }) + protected void setupRequiredEntities() { + Set links = vdcClient.getVdc(vdcURI).getLinks(); + + if (mediaURI == null) { + Predicate addMediaLink = and(relEquals(Link.Rel.ADD), typeEquals(VCloudDirectorMediaType.MEDIA)); + + if (contains(links, addMediaLink)) { + Link addMedia = find(links, addMediaLink); + byte[] iso = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; + + Media sourceMedia = Media.builder() + .type(VCloudDirectorMediaType.MEDIA) + .name(name("media")) + .size(iso.length) + .imageType(Media.ImageType.ISO) + .description("Test media generated by VmClientLiveTest") + .build(); + Media media = context.getApi().getMediaClient().createMedia(addMedia.getHref(), sourceMedia); + + Link uploadLink = getFirst(getFirst(media.getFiles(), null).getLinks(), null); + context.getApi().getUploadClient().upload(uploadLink.getHref(), Payloads.newByteArrayPayload(iso)); + + media = context.getApi().getMediaClient().getMedia(media.getHref()); + + if (media.getTasks().size() == 1) { + Task uploadTask = Iterables.getOnlyElement(media.getTasks()); + Checks.checkTask(uploadTask); + assertEquals(uploadTask.getStatus(), Task.Status.RUNNING); + assertTrue(retryTaskSuccess.apply(uploadTask), String.format(TASK_COMPLETE_TIMELY, "uploadTask")); + media = context.getApi().getMediaClient().getMedia(media.getHref()); + } + + mediaURI = media.getHref(); + mediaCreated = true; + } + } + + if (adminContext != null) { + Link orgLink = find(links, and(relEquals("up"), typeEquals(VCloudDirectorMediaType.ORG))); + testUserURI = adminContext.getApi().getUserClient().createUser(toAdminUri(orgLink), randomTestUser("VAppAccessTest")).getHref(); + } else { + testUserURI = userURI; + } + } + + @AfterClass(alwaysRun = true, dependsOnMethods = { "cleanUpEnvironment" }) + public void cleanUp() { + if (adminContext != null && mediaCreated && mediaURI != null) { + try { + Task delete = context.getApi().getMediaClient().deleteMedia(mediaURI); + taskDoneEventually(delete); + } catch (Exception e) { + logger.warn("Error when deleting media: %s", e.getMessage()); + } + } + if (adminContext != null && testUserCreated && testUserURI != null) { + try { + adminContext.getApi().getUserClient().deleteUser(testUserURI); + } catch (Exception e) { + logger.warn("Error when deleting user: %s", e.getMessage()); + } + } + } + + /** + * @see VmClient#getVm(URI) + */ + @Test(description = "GET /vApp/{id}") + public void testGetVm() { + // The method under test + vm = vmClient.getVm(vmURI); + + // Check the retrieved object is well formed + checkVm(vm); + + // Check the required fields are set + assertEquals(vm.isDeployed(), Boolean.FALSE, String.format(OBJ_FIELD_EQ, VAPP, "deployed", "FALSE", vm.isDeployed().toString())); + + // Check status + assertVmStatus(vm.getHref(), Status.POWERED_OFF); + } + + /** + * @see VmClient#modifyVm(URI, Vm) + */ + @Test(description = "PUT /vApp/{id}", dependsOnMethods = { "testGetVm" }) + public void testModifyVm() { + Vm newVm = Vm.builder() + .name(name("new-name-")) + .description("New Description") + .build(); + + // The method under test + Task modifyVm = vmClient.modifyVm(vm.getHref(), newVm); + assertTrue(retryTaskSuccess.apply(modifyVm), String.format(TASK_COMPLETE_TIMELY, "modifyVm")); + + // Get the updated Vm + vm = vmClient.getVm(vm.getHref()); + + // Check the required fields are set + assertEquals(vm.getName(), newVm.getName(), String.format(OBJ_FIELD_EQ, VM, "Name", newVm.getName(), vm.getName())); + assertEquals(vm.getDescription(), newVm.getDescription(), String.format(OBJ_FIELD_EQ, VM, "Description", newVm.getDescription(), vm.getDescription())); + } + + @Test(description = "POST /vApp/{id}/action/deploy", dependsOnMethods = { "testGetVm" }) + public void testDeployVm() { + DeployVAppParams params = DeployVAppParams.builder() + .deploymentLeaseSeconds((int) TimeUnit.SECONDS.convert(1L, TimeUnit.HOURS)) + .notForceCustomization() + .notPowerOn() + .build(); + + // The method under test + Task deployVm = vmClient.deploy(vm.getHref(), params); + assertTrue(retryTaskSuccessLong.apply(deployVm), String.format(TASK_COMPLETE_TIMELY, "deployVm")); + + // Get the updated Vm + vm = vmClient.getVm(vm.getHref()); + + // Check the required fields are set + assertTrue(vm.isDeployed(), String.format(OBJ_FIELD_EQ, VM, "deployed", "TRUE", vm.isDeployed().toString())); + + // Check status + assertVmStatus(vmURI, Status.POWERED_OFF); + } + + @Test(description = "POST /vApp/{id}/power/action/powerOn", dependsOnMethods = { "testDeployVm" }) + public void testPowerOnVm() { + // Power off Vm + vm = powerOffVm(vm.getHref()); + + // The method under test + Task powerOnVm = vmClient.powerOn(vm.getHref()); + assertTaskSucceedsLong(powerOnVm); + + // Get the updated Vm + vm = vmClient.getVm(vm.getHref()); + + // Check status + assertVmStatus(vm.getHref(), Status.POWERED_ON); + } + + @Test(description = "POST /vApp/{id}/power/action/reboot", dependsOnMethods = { "testDeployVm" }) + public void testReboot() { + // Power on Vm + vm = powerOnVm(vm.getHref()); + + // The method under test + Task reboot = vmClient.reboot(vm.getHref()); + assertTaskSucceedsLong(reboot); + + // Get the updated Vm + vm = vmClient.getVm(vm.getHref()); + + // Check status + assertVmStatus(vmURI, Status.POWERED_OFF); + } + + @Test(description = "POST /vApp/{id}/power/action/shutdown", dependsOnMethods = { "testDeployVm" }) + public void testShutdown() { + // Power on Vm + vm = powerOnVm(vm.getHref()); + + // The method under test + Task shutdown = vmClient.shutdown(vmURI); + assertTaskSucceedsLong(shutdown); + + // Get the updated Vm + vm = vmClient.getVm(vmURI); + + // Check status + assertVmStatus(vmURI, Status.POWERED_OFF); + + // Power on the Vm again + vm = powerOnVm(vm.getHref()); + } + + @Test(description = "POST /vApp/{id}/power/action/suspend", dependsOnMethods = { "testDeployVm" }) + public void testSuspend() { + // Power on Vm + vm = powerOnVm(vm.getHref()); + + // The method under test + Task suspend = vmClient.suspend(vmURI); + assertTaskSucceedsLong(suspend); + + // Get the updated Vm + vm = vmClient.getVm(vm.getHref()); + + // Check status + assertVmStatus(vmURI, Status.SUSPENDED); + + // Power on the Vm again + vm = powerOnVm(vm.getHref()); + } + + @Test(description = "POST /vApp/{id}/power/action/reset", dependsOnMethods = { "testDeployVm" }) + public void testReset() { + // Power on Vm + vm = powerOnVm(vm.getHref()); + + // The method under test + Task reset = vmClient.reset(vmURI); + assertTaskSucceedsLong(reset); + + // Get the updated Vm + vm = vmClient.getVm(vm.getHref()); + + // Check status + assertVmStatus(vmURI, Status.POWERED_ON); + } + + @Test(description = "POST /vApp/{id}/action/undeploy", dependsOnMethods = { "testDeployVm" }) + public void testUndeployVm() { + // Power on Vm + vm = powerOnVm(vm.getHref()); + + UndeployVAppParams params = UndeployVAppParams.builder().build(); + + // The method under test + Task undeploy = vmClient.undeploy(vm.getHref(), params); + assertTrue(retryTaskSuccess.apply(undeploy), String.format(TASK_COMPLETE_TIMELY, "undeploy")); + + // Get the updated Vm + vm = vmClient.getVm(vm.getHref()); + + // Check status + assertFalse(vm.isDeployed(), String.format(OBJ_FIELD_EQ, VAPP, "deployed", "FALSE", vm.isDeployed().toString())); + assertVmStatus(vmURI, Status.POWERED_OFF); + } + + @Test(description = "POST /vApp/{id}/power/action/powerOff", dependsOnMethods = { "testUndeployVm" }) + public void testPowerOffVm() { + // Power on Vm + vm = powerOnVm(vm.getHref()); + + // The method under test + Task powerOffVm = vmClient.powerOff(vm.getHref()); + assertTrue(retryTaskSuccess.apply(powerOffVm), String.format(TASK_COMPLETE_TIMELY, "powerOffVm")); + + // Get the updated Vm + vm = vmClient.getVm(vmURI); + + // Check status + assertVmStatus(vmURI, Status.POWERED_OFF); + } + + @Test(description = "POST /vApp/{id}/action/consolidate", dependsOnMethods = { "testDeployVm" }) + public void testConsolidateVm() { + // Power on Vm + vm = powerOnVm(vm.getHref()); + + // The method under test + Task consolidateVm = vmClient.consolidateVm(vm.getHref()); + assertTrue(retryTaskSuccess.apply(consolidateVm), String.format(TASK_COMPLETE_TIMELY, "consolidateVm")); + } + + @Test(description = "POST /vApp/{id}/action/discardSuspendedState", dependsOnMethods = { "testDeployVm" }) + public void testDiscardSuspendedState() { + // Suspend the Vm + vm = suspendVm(vm.getHref()); + + // The method under test + Task discardSuspendedState = vmClient.discardSuspendedState(vm.getHref()); + assertTrue(retryTaskSuccess.apply(discardSuspendedState), String.format(TASK_COMPLETE_TIMELY, "discardSuspendedState")); + } + + @Test(description = "POST /vApp/{id}/action/installVMwareTools", dependsOnMethods = { "testDeployVm" }) + public void testInstallVMwareTools() { + // First ensure the vApp is powered n + vm = powerOnVm(vm.getHref()); + + // The method under test + Task installVMwareTools = vmClient.installVMwareTools(vm.getHref()); + assertTrue(retryTaskSuccess.apply(installVMwareTools), String.format(TASK_COMPLETE_TIMELY, "installVMwareTools")); + } + + // NOTE This test is disabled, as it is not possible to look up datastores using the User API + @Test(description = "POST /vApp/{id}/action/relocate", dependsOnMethods = { "testGetVm" }) + public void testRelocate() { + // Relocate to the last of the available datastores + QueryResultRecords records = context.getApi().getQueryClient().queryAll("datastore"); + QueryResultRecordType datastore = Iterables.getLast(records.getRecords()); + RelocateParams params = RelocateParams.builder().datastore(Reference.builder().href(datastore.getHref()).build()).build(); + + // The method under test + Task relocate = vmClient.relocateVm(vm.getHref(), params); + assertTrue(retryTaskSuccess.apply(relocate), String.format(TASK_COMPLETE_TIMELY, "relocate")); + } + + @Test(description = "POST /vApp/{id}/action/upgradeHardwareVersion", dependsOnMethods = { "testGetVm" }) + public void testUpgradeHardwareVersion() { + // Power off Vm + vm = powerOffVm(vm.getHref()); + + // The method under test + Task upgradeHardwareVersion = vmClient.upgradeHardwareVersion(vm.getHref()); + assertTrue(retryTaskSuccess.apply(upgradeHardwareVersion), String.format(TASK_COMPLETE_TIMELY, "upgradeHardwareVersion")); + } + + @Test(description = "GET /vApp/{id}/guestCustomizationSection", dependsOnMethods = { "testGetVm" }) + public void testGetGuestCustomizationSection() { + getGuestCustomizationSection(new Function() { + @Override + public GuestCustomizationSection apply(URI uri) { + return vmClient.getGuestCustomizationSection(uri); + } + }); + } + + @Test(description = "PUT /vApp/{id}/guestCustomizationSection", dependsOnMethods = { "testGetGuestCustomizationSection" }) + public void testModifyGuestCustomizationSection() { + // Copy existing section and update fields + GuestCustomizationSection oldSection = vmClient.getGuestCustomizationSection(vm.getHref()); + GuestCustomizationSection newSection = oldSection.toBuilder() + .computerName(name("n")) + .enabled(Boolean.FALSE) + .adminPassword(null) // Not allowed + .build(); + + // The method under test + Task modifyGuestCustomizationSection = vmClient.modifyGuestCustomizationSection(vm.getHref(), newSection); + assertTrue(retryTaskSuccess.apply(modifyGuestCustomizationSection), String.format(TASK_COMPLETE_TIMELY, "modifyGuestCustomizationSection")); + + // Retrieve the modified section + GuestCustomizationSection modified = vmClient.getGuestCustomizationSection(vm.getHref()); + + // Check the retrieved object is well formed + checkGuestCustomizationSection(modified); + + // Check the modified section fields are set correctly + assertEquals(modified.getComputerName(), newSection.getComputerName()); + assertFalse(modified.isEnabled()); + + // Reset the admin password in the retrieved GuestCustomizationSection for equality check + modified = modified.toBuilder().adminPassword(null).build(); + + // Check the section was modified correctly + assertEquals(modified, newSection, String.format(ENTITY_EQUAL, "GuestCustomizationSection")); + } + + // FIXME "Error: The requested operation on media "com.vmware.vcloud.entity.media:abfcb4b7-809f-4b50-a0aa-8c97bf09a5b0" is not supported in the current state." + @Test(description = "PUT /vApp/{id}/media/action/insertMedia", dependsOnMethods = { "testGetVm" }) + public void testInsertMedia() { + // Setup media params from configured media id + MediaInsertOrEjectParams params = MediaInsertOrEjectParams.builder() + .media(Reference.builder().href(mediaURI).type(MEDIA).build()) + .build(); + + // The method under test + Task insertMedia = vmClient.insertMedia(vm.getHref(), params); + assertTrue(retryTaskSuccess.apply(insertMedia), String.format(TASK_COMPLETE_TIMELY, "insertMedia")); + } + + @Test(description = "PUT /vApp/{id}/media/action/ejectMedia", dependsOnMethods = { "testInsertMedia" }) + public void testEjectMedia() { + // Setup media params from configured media id + MediaInsertOrEjectParams params = MediaInsertOrEjectParams.builder() + .media(Reference.builder().href(mediaURI).type(MEDIA).build()) + .build(); + + // The method under test + Task ejectMedia = vmClient.ejectMedia(vm.getHref(), params); + assertTrue(retryTaskSuccess.apply(ejectMedia), String.format(TASK_COMPLETE_TIMELY, "ejectMedia")); + } + + @Test(description = "GET /vApp/{id}/networkConnectionSection", dependsOnMethods = { "testGetVm" }) + public void testGetNetworkConnectionSection() { + getNetworkConnectionSection(new Function() { + @Override + public NetworkConnectionSection apply(URI uri) { + return vmClient.getNetworkConnectionSection(uri); + } + }); + } + + // FIXME "Task error: Unable to perform this action. Contact your cloud administrator." + @Test(description = "PUT /vApp/{id}/networkConnectionSection", dependsOnMethods = { "testGetNetworkConnectionSection" }) + public void testModifyNetworkConnectionSection() { + // Look up a network in the Vdc + Set networks = vdc.getAvailableNetworks(); + Reference network = Iterables.getLast(networks); + + // Copy existing section and update fields + NetworkConnectionSection oldSection = vmClient.getNetworkConnectionSection(vm.getHref()); + NetworkConnectionSection newSection = oldSection.toBuilder() + .networkConnection(NetworkConnection.builder() + .ipAddressAllocationMode(IpAddressAllocationMode.DHCP.toString()) + .network(network.getName()) + .build()) + .build(); + + // The method under test + Task modifyNetworkConnectionSection = vmClient.modifyNetworkConnectionSection(vm.getHref(), newSection); + assertTrue(retryTaskSuccess.apply(modifyNetworkConnectionSection), String.format(TASK_COMPLETE_TIMELY, "modifyNetworkConnectionSection")); + + // Retrieve the modified section + NetworkConnectionSection modified = vmClient.getNetworkConnectionSection(vm.getHref()); + + // Check the retrieved object is well formed + checkNetworkConnectionSection(modified); + + // Check the modified section has an extra network connection + assertEquals(modified.getNetworkConnections().size(), newSection.getNetworkConnections().size() + 1); + + // Check the section was modified correctly + assertEquals(modified, newSection, String.format(ENTITY_EQUAL, "NetworkConnectionSection")); + } + + @Test(description = "GET /vApp/{id}/operatingSystemSection", dependsOnMethods = { "testGetVm" }) + public void testGetOperatingSystemSection() { + // The method under test + OperatingSystemSection section = vmClient.getOperatingSystemSection(vm.getHref()); + + // Check the retrieved object is well formed + checkOperatingSystemSection(section); + } + + @Test(description = "PUT /vApp/{id}/operatingSystemSection", dependsOnMethods = { "testGetOperatingSystemSection", "testModifyVirtualHardwareSection" }) + public void testModifyOperatingSystemSection() { + // Create new OperatingSystemSection + OperatingSystemSection newSection = OperatingSystemSection.builder() + .info("") // NOTE Required OVF field, ignored + .id(OSType.RHEL_64.getCode()) + .osType("rhel5_64Guest") + .build(); + + // The method under test + Task modifyOperatingSystemSection = vmClient.modifyOperatingSystemSection(vm.getHref(), newSection); + assertTrue(retryTaskSuccess.apply(modifyOperatingSystemSection), String.format(TASK_COMPLETE_TIMELY, "modifyOperatingSystemSection")); + + // Retrieve the modified section + OperatingSystemSection modified = vmClient.getOperatingSystemSection(vm.getHref()); + + // Check the retrieved object is well formed + checkOperatingSystemSection(modified); + + // Check the modified section fields are set correctly + assertEquals(modified.getId(), newSection.getId()); + } + + @Test(description = "GET /vApp/{id}/productSections", dependsOnMethods = { "testGetVm" }) + public void testGetProductSections() { + // The method under test + ProductSectionList sectionList = vmClient.getProductSections(vm.getHref()); + + // Check the retrieved object is well formed + checkProductSectionList(sectionList); + } + + @Test(description = "PUT /vApp/{id}/productSections", dependsOnMethods = { "testGetProductSections" }) + public void testModifyProductSections() { + // Copy existing section and update fields + ProductSectionList oldSections = vmClient.getProductSections(vm.getHref()); + ProductSectionList newSections = oldSections.toBuilder() + .productSection(ProductSection.builder() + .info("Information about the installed software") // Default ovf:Info text + .required() + .product(MsgType.builder().value("jclouds").build()) + .vendor(MsgType.builder().value("jclouds Inc.").build()) + // NOTE other ProductSection elements not returned by vCloud + .build()) + .build(); + + // The method under test + Task modifyProductSections = vmClient.modifyProductSections(vm.getHref(), newSections); + assertTrue(retryTaskSuccess.apply(modifyProductSections), String.format(TASK_COMPLETE_TIMELY, "modifyProductSections")); + + // Retrieve the modified section + ProductSectionList modified = vmClient.getProductSections(vm.getHref()); + + // Check the retrieved object is well formed + checkProductSectionList(modified); + + // Check the modified object has an extra ProductSection + assertEquals(modified.getProductSections().size(), oldSections.getProductSections().size() + 1); + + // Check the section was modified correctly + assertEquals(modified, newSections, String.format(ENTITY_EQUAL, "ProductSectionList")); + } + + // FIXME How do we force it to ask a question? + @Test(description = "GET /vApp/{id}/question", dependsOnMethods = { "testDeployVm" }) + public void testGetPendingQuestion() { + // Power on Vm + vm = powerOnVm(vm.getHref()); + + // TODO how to test? + + // The method under test + VmPendingQuestion question = vmClient.getPendingQuestion(vm.getHref()); + + // Check the retrieved object is well formed + checkVmPendingQuestion(question); + } + + @Test(description = "POST /vApp/{id}/question/action/answer", dependsOnMethods = { "testGetPendingQuestion" }) + public void testAnswerQuestion() { + // TODO check that the question has been answered (e.g. asking for getPendingQuestion does not + // include our answered question). + + VmPendingQuestion question = vmClient.getPendingQuestion(vm.getHref()); + List answerChoices = question.getChoices(); + VmQuestionAnswerChoice answerChoice = Iterables.getFirst(answerChoices, null); + assertNotNull(answerChoice, "Question "+question+" must have at least once answer-choice"); + + VmQuestionAnswer answer = VmQuestionAnswer.builder() + .choiceId(answerChoice.getId()) + .questionId(question.getQuestionId()) + .build(); + + vmClient.answerQuestion(vm.getHref(), answer); + } + + @Test(description = "GET /vApp/{id}/runtimeInfoSection", dependsOnMethods = { "testGetVm" }) + public void testGetRuntimeInfoSection() { + // The method under test + RuntimeInfoSection section = vmClient.getRuntimeInfoSection(vm.getHref()); + + // Check the retrieved object is well formed + checkRuntimeInfoSection(section); + } + + // FIXME If still failing, consider escalating? + @Test(description = "GET /vApp/{id}/screen", dependsOnMethods = { "testDeployVm" }) + public void testGetScreenImage() { + // Power on Vm + vm = powerOnVm(vm.getHref()); + + // The method under test + byte[] image = vmClient.getScreenImage(vm.getHref()); + + // Check returned bytes against PNG header magic number + byte[] pngHeaderBytes = new byte[] { (byte) 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }; + assertNotNull(image); + assertTrue(image.length > pngHeaderBytes.length); + for (int i = 0; i < pngHeaderBytes.length; i++) { + assertEquals(image[i], pngHeaderBytes[i], String.format("Image differs from PNG format at byte %d of header", i)); + } + } + + @Test(description = "GET /vApp/{id}/screen/action/acquireTicket", dependsOnMethods = { "testDeployVm" }) + public void testGetScreenTicket() { + // Power on Vm + vm = powerOnVm(vm.getHref()); + + // The method under test + ScreenTicket ticket = vmClient.getScreenTicket(vm.getHref()); + + // Check the retrieved object is well formed + checkScreenTicket(ticket); + } + + @Test(description = "GET /vApp/{id}/virtualHardwareSection", dependsOnMethods = { "testGetVm" }) + public void testGetVirtualHardwareSection() { + // Method under test + VirtualHardwareSection hardware = vmClient.getVirtualHardwareSection(vm.getHref()); + + // Check the retrieved object is well formed + checkVirtualHardwareSection(hardware); + } + + @Test(description = "PUT /vApp/{id}/virtualHardwareSection", dependsOnMethods = { "testGetVirtualHardwareSection" }) + public void testModifyVirtualHardwareSection() { + // Power off Vm + vm = powerOffVm(vm.getHref()); + + // Copy existing section and update fields + VirtualHardwareSection oldSection = vmClient.getVirtualHardwareSection(vm.getHref()); + Set oldItems = oldSection.getItems(); + Set newItems = Sets.newLinkedHashSet(oldItems); + ResourceAllocationSettingData oldMemory = Iterables.find(oldItems, new Predicate() { + @Override + public boolean apply(ResourceAllocationSettingData rasd) { + return rasd.getResourceType() == ResourceAllocationSettingData.ResourceType.MEMORY; + } + }); + ResourceAllocationSettingData newMemory = oldMemory.toBuilder() + .elementName("1024 MB of memory") + .virtualQuantity(new BigInteger("1024")) + .build(); + newItems.remove(oldMemory); + newItems.add(newMemory); + VirtualHardwareSection newSection = oldSection.toBuilder() + .items(newItems) + .build(); + + // The method under test + Task modifyVirtualHardwareSection = vmClient.modifyVirtualHardwareSection(vm.getHref(), newSection); + assertTrue(retryTaskSuccess.apply(modifyVirtualHardwareSection), String.format(TASK_COMPLETE_TIMELY, "modifyVirtualHardwareSection")); + + // Retrieve the modified section + VirtualHardwareSection modifiedSection = vmClient.getVirtualHardwareSection(vm.getHref()); + + // Check the retrieved object is well formed + checkVirtualHardwareSection(modifiedSection); + + // Check the modified section fields are set correctly + ResourceAllocationSettingData modifiedMemory = Iterables.find(modifiedSection.getItems(), + new Predicate() { + @Override + public boolean apply(ResourceAllocationSettingData rasd) { + return rasd.getResourceType() == ResourceAllocationSettingData.ResourceType.MEMORY; + } + }); + assertEquals(modifiedMemory.getVirtualQuantity(), new BigInteger("1024")); + assertEquals(modifiedMemory, newMemory); + assertEquals(modifiedSection, newSection); + } + + @Test(description = "GET /vApp/{id}/virtualHardwareSection/cpu", dependsOnMethods = { "testGetVirtualHardwareSection" }) + public void testGetVirtualHardwareSectionCpu() { + // Method under test + RasdItem rasd = vmClient.getVirtualHardwareSectionCpu(vm.getHref()); + + // Check the retrieved object is well formed + checkResourceAllocationSettingData(rasd); + } + + @Test(description = "PUT /vApp/{id}/virtualHardwareSection/cpu", dependsOnMethods = { "testGetVirtualHardwareSectionCpu" }) + public void testModifyVirtualHardwareSectionCpu() { + // Copy existing section and update fields + RasdItem oldItem = vmClient.getVirtualHardwareSectionCpu(vm.getHref()); + RasdItem newItem = oldItem.toBuilder() + .elementName("2 virtual CPU(s)") + .virtualQuantity(new BigInteger("2")) + .build(); + + // Method under test + Task modifyVirtualHardwareSectionCpu = vmClient.modifyVirtualHardwareSectionCpu(vm.getHref(), newItem); + assertTrue(retryTaskSuccess.apply(modifyVirtualHardwareSectionCpu), String.format(TASK_COMPLETE_TIMELY, "modifyVirtualHardwareSectionCpu")); + + // Retrieve the modified section + RasdItem modified = vmClient.getVirtualHardwareSectionCpu(vm.getHref()); + + // Check the retrieved object + checkResourceAllocationSettingData(modified); + + // Check modified item + assertEquals(modified.getVirtualQuantity(), new BigInteger("2"), + String.format(OBJ_FIELD_EQ, "ResourceAllocationSettingData", "VirtualQuantity", "2", modified.getVirtualQuantity().toString())); + assertEquals(modified, newItem); + } + + @Test(description = "GET /vApp/{id}/virtualHardwareSection/disks", dependsOnMethods = { "testGetVirtualHardwareSection" }) + public void testGetVirtualHardwareSectionDisks() { + // Method under test + RasdItemsList rasdItems = vmClient.getVirtualHardwareSectionDisks(vm.getHref()); + + // Check the retrieved object is well formed + checkRasdItemsList(rasdItems); + } + + @Test(description = "PUT /vApp/{id}/virtualHardwareSection/disks", dependsOnMethods = { "testGetVirtualHardwareSectionDisks" }) + public void testModifyVirtualHardwareSectionDisks() { + // Copy the existing items list and modify the name of an item + RasdItemsList oldSection = vmClient.getVirtualHardwareSectionDisks(vm.getHref()); + RasdItemsList newSection = oldSection.toBuilder().build(); + + // Method under test + Task modifyVirtualHardwareSectionDisks = vmClient.modifyVirtualHardwareSectionDisks(vm.getHref(), newSection); + assertTrue(retryTaskSuccess.apply(modifyVirtualHardwareSectionDisks), String.format(TASK_COMPLETE_TIMELY, "modifyVirtualHardwareSectionDisks")); + + // Retrieve the modified section + RasdItemsList modified = vmClient.getVirtualHardwareSectionDisks(vm.getHref()); + + // Check the retrieved object is well formed + checkRasdItemsList(modified); + + // TODO What is modifiable? What can we change, so we can assert the change took effect? + // I tried changing "elementName" of one of the items, but it continued to have the old value when looked up post-modify. + // + // List newItems = new ArrayList(oldSection.getItems()); + // ResourceAllocationSettingData item0 = newItems.get(0); + // String item0InstanceId = item0.getInstanceID().getValue(); + // String item0ElementName = item0.getElementName().getValue()+"-"+random.nextInt(Integer.MAX_VALUE); + // newItems.set(0, item0.toBuilder().elementName(newCimString(item0ElementName)).build()); + // RasdItemsList newSection = oldSection.toBuilder() + // .items(newItems) + // .build(); + // ... + // long weight = random.nextInt(Integer.MAX_VALUE); + // ResourceAllocationSettingData newSection = origSection.toBuilder() + // .weight(newCimUnsignedInt(weight)) + // .build(); + // ... + // checkHasMatchingItem("virtualHardwareSection/disk", modified, item0InstanceId, item0ElementName); + } + + @Test(description = "GET /vApp/{id}/virtualHardwareSection/media", dependsOnMethods = { "testGetVirtualHardwareSection" }) + public void testGetVirtualHardwareSectionMedia() { + // Method under test + RasdItemsList rasdItems = vmClient.getVirtualHardwareSectionMedia(vm.getHref()); + + // Check the retrieved object is well formed + checkRasdItemsList(rasdItems); + } + + @Test(description = "GET /vApp/{id}/virtualHardwareSection/memory", dependsOnMethods = { "testGetVirtualHardwareSection" }) + public void testGetVirtualHardwareSectionMemory() { + // Method under test + RasdItem rasd = vmClient.getVirtualHardwareSectionCpu(vm.getHref()); + + // Check the retrieved object is well formed + checkResourceAllocationSettingData(rasd); + } + + @Test(description = "PUT /vApp/{id}/virtualHardwareSection/memory", dependsOnMethods = { "testGetVirtualHardwareSectionMemory" }) + public void testModifyVirtualHardwareSectionMemory() { + RasdItem origItem = vmClient.getVirtualHardwareSectionMemory(vm.getHref()); + RasdItem newItem = origItem.toBuilder() + .elementName("1024 MB of memory") + .virtualQuantity(new BigInteger("1024")) + .build(); + + // Method under test + Task modifyVirtualHardwareSectionMemory = vmClient.modifyVirtualHardwareSectionMemory(vm.getHref(), newItem); + assertTrue(retryTaskSuccess.apply(modifyVirtualHardwareSectionMemory), String.format(TASK_COMPLETE_TIMELY, "modifyVirtualHardwareSectionMemory")); + + // Retrieve the modified section + RasdItem modified = vmClient.getVirtualHardwareSectionMemory(vm.getHref()); + + // Check the retrieved object + checkResourceAllocationSettingData(modified); + + // Check modified item + assertEquals(modified.getVirtualQuantity(), new BigInteger("1024"), + String.format(OBJ_FIELD_EQ, "ResourceAllocationSettingData", "VirtualQuantity", "1024", modified.getVirtualQuantity().toString())); + assertEquals(modified, newItem); + } + + @Test(description = "GET /vApp/{id}/virtualHardwareSection/networkCards", dependsOnMethods = { "testGetVirtualHardwareSection" }) + public void testGetVirtualHardwareSectionNetworkCards() { + // Method under test + RasdItemsList rasdItems = vmClient.getVirtualHardwareSectionNetworkCards(vm.getHref()); + + // Check the retrieved object is well formed + checkRasdItemsList(rasdItems); + } + + @Test(description = "PUT /vApp/{id}/virtualHardwareSection/networkCards", dependsOnMethods = { "testGetVirtualHardwareSectionNetworkCards" }) + public void testModifyVirtualHardwareSectionNetworkCards() { + RasdItemsList oldSection = vmClient.getVirtualHardwareSectionNetworkCards(vm.getHref()); + RasdItemsList newSection = oldSection.toBuilder().build(); + + // Method under test + Task modifyVirtualHardwareSectionNetworkCards = vmClient.modifyVirtualHardwareSectionNetworkCards(vm.getHref(), newSection); + assertTrue(retryTaskSuccess.apply(modifyVirtualHardwareSectionNetworkCards), String.format(TASK_COMPLETE_TIMELY, "modifyVirtualHardwareSectionNetworkCards")); + + // Retrieve the modified section + RasdItemsList modified = vmClient.getVirtualHardwareSectionNetworkCards(vm.getHref()); + + // Check the retrieved object is well formed + checkRasdItemsList(modified); + + // TODO What is modifiable? What can we change, so we can assert the change took effect? + // I tried changing "elementName" of one of the items, but it continued to have the old value when looked up post-modify. + // See the description in testModifyVirtualHardwareSectionDisks + } + + @Test(description = "GET /vApp/{id}/virtualHardwareSection/serialPorts", dependsOnMethods = { "testGetVirtualHardwareSection" }) + public void testGetVirtualHardwareSectionSerialPorts() { + // Method under test + RasdItemsList rasdItems = vmClient.getVirtualHardwareSectionSerialPorts(vm.getHref()); + + // Check the retrieved object is well formed + checkRasdItemsList(rasdItems); + } + + @Test(description = "PUT /vApp/{id}/virtualHardwareSection/serialPorts", dependsOnMethods = { "testGetVirtualHardwareSectionSerialPorts" }) + public void testModifyVirtualHardwareSectionSerialPorts() { + RasdItemsList oldSection = vmClient.getVirtualHardwareSectionSerialPorts(vm.getHref()); + RasdItemsList newSection = oldSection.toBuilder().build(); + + // Method under test + Task modifyVirtualHardwareSectionSerialPorts = vmClient.modifyVirtualHardwareSectionSerialPorts(vm.getHref(), newSection); + assertTrue(retryTaskSuccess.apply(modifyVirtualHardwareSectionSerialPorts), String.format(TASK_COMPLETE_TIMELY, "modifyVirtualHardwareSectionSerialPorts")); + + // Retrieve the modified section + RasdItemsList modified = vmClient.getVirtualHardwareSectionSerialPorts(vm.getHref()); + + // Check the retrieved object is well formed + checkRasdItemsList(modified); + + // TODO What is modifiable? What can we change, so we can assert the change took effect? + // I tried changing "elementName" of one of the items, but it continued to have the old value when looked up post-modify. + // See the description in testModifyVirtualHardwareSectionDisks + } + + @Test(description = "PUT /vApp/{id}/metadata", dependsOnMethods = { "testGetVm" }) + public void testSetMetadataValue() { + key = name("key-"); + String value = name("value-"); + metadataValue = MetadataValue.builder().value(value).build(); + vmClient.getMetadataClient().setMetadata(vm.getHref(), key, metadataValue); + + // Retrieve the value, and assert it was set correctly + MetadataValue newMetadataValue = vmClient.getMetadataClient().getMetadataValue(vm.getHref(), key); + + // Check the retrieved object is well formed + checkMetadataValueFor(VAPP, newMetadataValue, value); + } + + @Test(description = "GET /vApp/{id}/metadata", dependsOnMethods = { "testSetMetadataValue" }) + public void testGetMetadata() { + // Call the method being tested + Metadata metadata = vmClient.getMetadataClient().getMetadata(vm.getHref()); + + checkMetadata(metadata); + + // Check requirements for this test + assertFalse(Iterables.isEmpty(metadata.getMetadataEntries()), String.format(NOT_EMPTY_OBJECT_FMT, "MetadataEntry", "vm")); + } + + @Test(description = "GET /vApp/{id}/metadata/{key}", dependsOnMethods = { "testGetMetadata" }) + public void testGetOrgMetadataValue() { + // Call the method being tested + MetadataValue value = vmClient.getMetadataClient().getMetadataValue(vm.getHref(), key); + + String expected = metadataValue.getValue(); + + checkMetadataValue(value); + assertEquals(value.getValue(), expected, String.format(CORRECT_VALUE_OBJECT_FMT, "Value", "MetadataValue", expected, value.getValue())); + } + + @Test(description = "DELETE /vApp/{id}/metadata/{key}", dependsOnMethods = { "testSetMetadataValue" }) + public void testDeleteMetadataEntry() { + // Delete the entry + Task task = vmClient.getMetadataClient().deleteMetadataEntry(vm.getHref(), key); + retryTaskSuccess.apply(task); + + // Confirm the entry has been deleted + Metadata newMetadata = vmClient.getMetadataClient().getMetadata(vm.getHref()); + + // Check the retrieved object is well formed + checkMetadataKeyAbsentFor(VAPP, newMetadata, key); + } + + @Test(description = "POST /vApp/{id}/metadata", dependsOnMethods = { "testGetMetadata" }) + public void testMergeMetadata() { + Metadata oldMetadata = vmClient.getMetadataClient().getMetadata(vm.getHref()); + Map oldMetadataMap = Checks.metadataToMap(oldMetadata); + + // Store a value, to be deleted + String key = name("key-"); + String value = name("value-"); + Metadata addedMetadata = Metadata.builder() + .entry(MetadataEntry.builder().key(key).value(value).build()) + .build(); + Task task = vmClient.getMetadataClient().mergeMetadata(vm.getHref(), addedMetadata); + retryTaskSuccess.apply(task); + + // Confirm the entry contains everything that was there, and everything that was being added + Metadata newMetadata = vmClient.getMetadataClient().getMetadata(vm.getHref()); + Map expectedMetadataMap = ImmutableMap.builder() + .putAll(oldMetadataMap) + .put(key, value) + .build(); + + // Check the retrieved object is well formed + checkMetadataFor(VAPP, newMetadata, expectedMetadataMap); + } + + /** + * @see VmClient#deleteVm(URI) + */ + @Test(description = "DELETE /vApp/{id}") + public void testDeleteVm() { + // Create a temporary VApp to delete + VApp delete = instantiateVApp(); + DeployVAppParams params = DeployVAppParams.builder() + .deploymentLeaseSeconds((int)TimeUnit.SECONDS.convert(1L, TimeUnit.HOURS)) + .notForceCustomization() + .powerOn() + .build(); + Task deployVApp = vAppClient.deploy(delete.getHref(), params); + assertTaskSucceedsLong(deployVApp); + + // Get the updated VApp and the Vm + delete = vAppClient.getVApp(delete.getHref()); + Vm temp = Iterables.getOnlyElement(delete.getChildren().getVms()); + + // The method under test + Task deleteVm = vmClient.deleteVm(temp.getHref()); + assertTrue(retryTaskSuccess.apply(deleteVm), String.format(TASK_COMPLETE_TIMELY, "deleteVm")); + + Vm deleted = vmClient.getVm(temp.getHref()); + assertNull(deleted, "The Vm "+temp.getName()+" should have been deleted"); + } +} diff --git a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/internal/BaseVCloudDirectorClientLiveTest.java b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/internal/BaseVCloudDirectorClientLiveTest.java index 29148e5ff0..7cc8233b5e 100644 --- a/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/internal/BaseVCloudDirectorClientLiveTest.java +++ b/labs/vcloud-director/src/test/java/org/jclouds/vcloud/director/v1_5/internal/BaseVCloudDirectorClientLiveTest.java @@ -43,12 +43,13 @@ import org.jclouds.rest.RestContext; import org.jclouds.vcloud.director.testng.FormatApiResultsListener; import org.jclouds.vcloud.director.v1_5.VCloudDirectorApiMetadata; import org.jclouds.vcloud.director.v1_5.VCloudDirectorContext; -import org.jclouds.vcloud.director.v1_5.VCloudDirectorException; import org.jclouds.vcloud.director.v1_5.VCloudDirectorMediaType; import org.jclouds.vcloud.director.v1_5.admin.VCloudDirectorAdminAsyncClient; import org.jclouds.vcloud.director.v1_5.admin.VCloudDirectorAdminClient; import org.jclouds.vcloud.director.v1_5.domain.Link; import org.jclouds.vcloud.director.v1_5.domain.Reference; +import org.jclouds.vcloud.director.v1_5.domain.ResourceEntity.Status; +import org.jclouds.vcloud.director.v1_5.domain.Role.DefaultRoles; import org.jclouds.vcloud.director.v1_5.domain.RoleReferences; import org.jclouds.vcloud.director.v1_5.domain.Session; import org.jclouds.vcloud.director.v1_5.domain.Task; @@ -56,8 +57,6 @@ import org.jclouds.vcloud.director.v1_5.domain.User; import org.jclouds.vcloud.director.v1_5.domain.VApp; import org.jclouds.vcloud.director.v1_5.domain.VAppTemplate; import org.jclouds.vcloud.director.v1_5.domain.Vdc; -import org.jclouds.vcloud.director.v1_5.domain.ResourceEntity.Status; -import org.jclouds.vcloud.director.v1_5.domain.Role.DefaultRoles; import org.jclouds.vcloud.director.v1_5.domain.network.Network; import org.jclouds.vcloud.director.v1_5.domain.network.NetworkConfiguration; import org.jclouds.vcloud.director.v1_5.domain.network.VAppNetworkConfiguration; @@ -104,7 +103,7 @@ import com.google.inject.Guice; public abstract class BaseVCloudDirectorClientLiveTest extends BaseContextLiveTest { @Resource - protected Logger logger = Logger.CONSOLE; + protected Logger logger = Logger.NULL; protected static final long TASK_TIMEOUT_SECONDS = 100L; protected static final long LONG_TASK_TIMEOUT_SECONDS = 300L; @@ -429,15 +428,12 @@ public abstract class BaseVCloudDirectorClientLiveTest extends BaseContextLiveTe protected void cleanUpVApp(URI vAppURI) { VAppClient vAppClient = context.getApi().getVAppClient(); - VApp vApp; - try { - vApp = vAppClient.getVApp(vAppURI); // Refresh - logger.debug("Deleting VApp %s (%s)", vApp.getName(), vAppURI.getPath()); - } catch (VCloudDirectorException e) { - // Presumably vApp has already been deleted. Ignore. + VApp vApp = vAppClient.getVApp(vAppURI); // Refresh + if (vApp == null) { logger.info("Cannot find VApp at %s", vAppURI.getPath()); - return; + return; // Presumably vApp has already been deleted. Ignore. } + logger.debug("Deleting VApp %s (%s)", vApp.getName(), vAppURI.getPath()); // Wait for busy tasks to complete (don't care if it's failed or successful) // Otherwise, get error on delete "entity is busy completing an operation. @@ -463,7 +459,9 @@ public abstract class BaseVCloudDirectorClientLiveTest extends BaseContextLiveTe // Undeploy the VApp if necessary if (vApp.isDeployed()) { try { - UndeployVAppParams params = UndeployVAppParams.builder().build(); + UndeployVAppParams params = UndeployVAppParams.builder() + .undeployPowerAction(UndeployVAppParams.PowerAction.SHUTDOWN) + .build(); Task undeployTask = vAppClient.undeploy(vAppURI, params); taskDoneEventually(undeployTask); } catch (Exception e) { @@ -478,12 +476,7 @@ public abstract class BaseVCloudDirectorClientLiveTest extends BaseContextLiveTe vAppNames.remove(vApp.getName()); logger.info("Deleted VApp %s", vApp.getName()); } catch (Exception e) { - try { - vApp = vAppClient.getVApp(vAppURI); // Refresh - } catch (Exception e2) { - // Ignore - } - + vApp = vAppClient.getVApp(vAppURI); // Refresh logger.warn(e, "Deleting VApp %s failed (%s)", vApp.getName(), vAppURI.getPath()); } } diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToIpAddress.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToIpAddress.java index f7727e90ca..0e47da2c53 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToIpAddress.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToIpAddress.java @@ -54,7 +54,7 @@ public class IMachineToIpAddress implements Function { String macAddress = machine.getNetworkAdapter(0l).getMACAddress(); int offset = 0, step = 2; for (int j = 1; j <= 5; j++) { - macAddress = new StringBuffer(macAddress).insert(j * step + offset, ":").toString().toLowerCase(); + macAddress = new StringBuilder(macAddress).insert(j * step + offset, ":").toString().toLowerCase(); offset++; } @@ -64,14 +64,14 @@ public class IMachineToIpAddress implements Function { IMachine hostMachine = manager.getVBox().findMachine(hostId); if (isOSX(hostMachine)) { if (simplifiedMacAddressOfClonedVM.contains("00")) - simplifiedMacAddressOfClonedVM = new StringBuffer(simplifiedMacAddressOfClonedVM).delete( + simplifiedMacAddressOfClonedVM = new StringBuilder(simplifiedMacAddressOfClonedVM).delete( simplifiedMacAddressOfClonedVM.indexOf("00"), simplifiedMacAddressOfClonedVM.indexOf("00") + 1) .toString(); if (simplifiedMacAddressOfClonedVM.contains("0")) if (simplifiedMacAddressOfClonedVM.indexOf("0") + 1 != ':' && simplifiedMacAddressOfClonedVM.indexOf("0") - 1 != ':') - simplifiedMacAddressOfClonedVM = new StringBuffer(simplifiedMacAddressOfClonedVM).delete( + simplifiedMacAddressOfClonedVM = new StringBuilder(simplifiedMacAddressOfClonedVM).delete( simplifiedMacAddressOfClonedVM.indexOf("0"), simplifiedMacAddressOfClonedVM.indexOf("0") + 1) .toString(); } diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToSshClient.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToSshClient.java index e4ffe87a42..6290a8c97a 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToSshClient.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/IMachineToSshClient.java @@ -34,7 +34,6 @@ import org.jclouds.compute.options.RunScriptOptions; import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.domain.LoginCredentials; import org.jclouds.logging.Logger; -import org.jclouds.net.IPSocket; import org.jclouds.ssh.SshClient; import org.jclouds.virtualbox.domain.BridgedIf; import org.jclouds.virtualbox.statements.GetIPAddressFromMAC; @@ -48,6 +47,7 @@ import com.google.common.base.Function; import com.google.common.base.Splitter; import com.google.common.base.Supplier; import com.google.common.collect.Iterables; +import com.google.common.net.HostAndPort; import com.google.inject.Inject; @Singleton @@ -114,7 +114,7 @@ public class IMachineToSshClient implements Function { checkNotNull(clientIpAddress, "clientIpAddress"); client = sshClientFactory.create( - new IPSocket(clientIpAddress, Integer.parseInt(sshPort)), + HostAndPort.fromParts(clientIpAddress, Integer.parseInt(sshPort)), loginCredentials); checkNotNull(client); return client; diff --git a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/admin/StartVBoxIfNotAlreadyRunning.java b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/admin/StartVBoxIfNotAlreadyRunning.java index 8c231f11f2..6c9d561c42 100644 --- a/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/admin/StartVBoxIfNotAlreadyRunning.java +++ b/labs/virtualbox/src/main/java/org/jclouds/virtualbox/functions/admin/StartVBoxIfNotAlreadyRunning.java @@ -37,7 +37,6 @@ import org.jclouds.compute.predicates.RetryIfSocketNotYetOpen; import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.location.Provider; import org.jclouds.logging.Logger; -import org.jclouds.net.IPSocket; import org.jclouds.rest.annotations.Credential; import org.jclouds.rest.annotations.Identity; import org.jclouds.scriptbuilder.domain.Statements; @@ -46,6 +45,7 @@ import org.virtualbox_4_1.VirtualBoxManager; import com.google.common.base.Function; import com.google.common.base.Supplier; +import com.google.common.net.HostAndPort; @Singleton public class StartVBoxIfNotAlreadyRunning implements Supplier { @@ -78,7 +78,7 @@ public class StartVBoxIfNotAlreadyRunning implements Supplier public synchronized void start() { URI provider = providerSupplier.get(); - if (!socketTester.apply(new IPSocket(provider.getHost(), provider.getPort()))) { + if (!socketTester.apply(HostAndPort.fromParts(provider.getHost(), provider.getPort()))) { logger.debug("disabling password access"); runScriptOnNodeFactory.create(host.get(), Statements.exec("VBoxManage setproperty websrvauthlibrary null"), runAsRoot(false).wrapInInitScript(false)).init().call(); @@ -87,7 +87,7 @@ public class StartVBoxIfNotAlreadyRunning implements Supplier runScriptOnNodeFactory.create(host.get(), Statements.exec(vboxwebsrv), runAsRoot(false).wrapInInitScript(false).blockOnComplete(false).nameTask("vboxwebsrv")).init().call(); - if (!socketTester.apply(new IPSocket(provider.getHost(), provider.getPort()))){ + if (!socketTester.apply(HostAndPort.fromParts(provider.getHost(), provider.getPort()))){ throw new RuntimeException("could not connect to virtualbox"); } } diff --git a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/StartVBoxIfNotAlreadyRunningLiveTest.java b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/StartVBoxIfNotAlreadyRunningLiveTest.java index be64f61b88..45958fe7f4 100644 --- a/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/StartVBoxIfNotAlreadyRunningLiveTest.java +++ b/labs/virtualbox/src/test/java/org/jclouds/virtualbox/functions/admin/StartVBoxIfNotAlreadyRunningLiveTest.java @@ -36,7 +36,6 @@ import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.domain.NodeState; import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.predicates.RetryIfSocketNotYetOpen; -import org.jclouds.net.IPSocket; import org.jclouds.scriptbuilder.domain.Statements; import org.testng.annotations.Test; import org.virtualbox_4_1.VirtualBoxManager; @@ -44,6 +43,7 @@ import org.virtualbox_4_1.VirtualBoxManager; import com.google.common.base.Function; import com.google.common.base.Functions; import com.google.common.base.Suppliers; +import com.google.common.net.HostAndPort; @Test(groups = "live", singleThreaded = true, testName = "StartVBoxIfNotAlreadyRunningLiveTest") public class StartVBoxIfNotAlreadyRunningLiveTest { @@ -59,7 +59,7 @@ public class StartVBoxIfNotAlreadyRunningLiveTest { String identity = "adminstrator"; String credential = "12345"; expect(client.seconds(3)).andReturn(client); - expect(client.apply(new IPSocket(provider.getHost(), provider.getPort()))).andReturn(true).anyTimes(); + expect(client.apply(HostAndPort.fromParts(provider.getHost(), provider.getPort()))).andReturn(true).anyTimes(); manager.connect(provider.toASCIIString(), "", ""); expectLastCall().anyTimes(); @@ -87,7 +87,7 @@ public class StartVBoxIfNotAlreadyRunningLiveTest { String credential = "12345"; expect(client.seconds(3)).andReturn(client); - expect(client.apply(new IPSocket(provider.getHost(), provider.getPort()))).andReturn(false).once().andReturn(true).once(); + expect(client.apply(HostAndPort.fromParts(provider.getHost(), provider.getPort()))).andReturn(false).once().andReturn(true).once(); expect( runScriptOnNodeFactory.create(host, Statements.exec("VBoxManage setproperty websrvauthlibrary null"), runAsRoot(false).wrapInInitScript(false))).andReturn(runScriptOnNode); diff --git a/loadbalancer/src/test/java/org/jclouds/loadbalancer/BaseLoadBalancerServiceLiveTest.java b/loadbalancer/src/test/java/org/jclouds/loadbalancer/BaseLoadBalancerServiceLiveTest.java index 9ae48242e5..5ef28f1751 100644 --- a/loadbalancer/src/test/java/org/jclouds/loadbalancer/BaseLoadBalancerServiceLiveTest.java +++ b/loadbalancer/src/test/java/org/jclouds/loadbalancer/BaseLoadBalancerServiceLiveTest.java @@ -39,7 +39,6 @@ import org.jclouds.compute.predicates.NodePredicates; import org.jclouds.domain.LoginCredentials; import org.jclouds.domain.LoginCredentials.Builder; import org.jclouds.loadbalancer.domain.LoadBalancerMetadata; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.predicates.SocketOpen; import org.jclouds.ssh.SshClient; @@ -49,6 +48,7 @@ import org.testng.annotations.Test; import com.google.common.base.Splitter; import com.google.common.collect.Iterables; +import com.google.common.net.HostAndPort; import com.google.common.reflect.TypeToken; import com.google.inject.Guice; import com.google.inject.Module; @@ -95,7 +95,7 @@ public abstract class BaseLoadBalancerServiceLiveTest extends BaseViewLiveTest socketTester; + protected RetryablePredicate socketTester; protected Set nodes; protected Template template; protected Map keyPair; @@ -139,7 +139,7 @@ public abstract class BaseLoadBalancerServiceLiveTest extends BaseViewLiveTest(socketOpen, 60, 1, TimeUnit.SECONDS); + socketTester = new RetryablePredicate(socketOpen, 60, 1, TimeUnit.SECONDS); } abstract protected Module getSshModule(); diff --git a/project/pom.xml b/project/pom.xml index b5734c4274..eb5f893285 100644 --- a/project/pom.xml +++ b/project/pom.xml @@ -283,6 +283,78 @@ + + com.ning.maven.plugins + maven-duplicate-finder-plugin + 1.0.3 + + + + + + + org.jclouds.api + cloudsigma + ${project.version} + + + org.jclouds.provider + cloudsigma-lvs + ${project.version} + + + org.jclouds.provider + cloudsigma-zrh + ${project.version} + + + + org.jclouds.cloudsigma + + + + + + + com.google.appengine + appengine-api-1.0-sdk + 1.4.3 + + + com.google.appengine + appengine-testing + 1.4.3 + test + + + + com.google + + + + + + about\.html + + log4j.xml + os.xml + virtualhardwaresection.xml + logback.xml + amzn_images.xml + test.jks + CreateInternetService-options-test.xml + + true + + + + verify + + check + + + + com.theoryinpractise clojure-maven-plugin diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2ProviderMetadata.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2ProviderMetadata.java index a75ea1eec4..77be4f1d7f 100644 --- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2ProviderMetadata.java +++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2ProviderMetadata.java @@ -65,9 +65,9 @@ public class AWSEC2ProviderMetadata extends BaseProviderMetadata { // from stopping->stopped state on an ec2 micro properties.setProperty(TIMEOUT_NODE_SUSPENDED, 120 * 1000 + ""); properties.putAll(Region.regionProperties()); - // amazon, alestic, canonical, and rightscale + // Amazon Linux, Amazon Windows, alestic, canonical, and rightscale properties.setProperty(PROPERTY_EC2_AMI_QUERY, - "owner-id=137112412989,063491364108,099720109477,411009282317;state=available;image-type=machine"); + "owner-id=137112412989,801119661308,063491364108,099720109477,411009282317;state=available;image-type=machine"); // amis that work with the cluster instances properties.setProperty(PROPERTY_EC2_CC_REGIONS, Region.US_EAST_1); properties diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/WindowsClientLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/WindowsClientLiveTest.java similarity index 89% rename from apis/ec2/src/test/java/org/jclouds/ec2/services/WindowsClientLiveTest.java rename to providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/WindowsClientLiveTest.java index 0b7cecc82b..eeb514439e 100644 --- a/apis/ec2/src/test/java/org/jclouds/ec2/services/WindowsClientLiveTest.java +++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/WindowsClientLiveTest.java @@ -16,18 +16,21 @@ * specific language governing permissions and limitations * under the License. */ -package org.jclouds.ec2.services; +package org.jclouds.aws.ec2.services; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; +import java.util.ArrayList; +import java.util.List; import java.util.Properties; import java.util.Set; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; +import com.google.inject.Module; import org.jclouds.compute.ComputeService; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.OsFamily; @@ -41,6 +44,8 @@ import org.jclouds.ec2.compute.functions.WindowsLoginCredentialsFromEncryptedDat import org.jclouds.ec2.domain.InstanceType; import org.jclouds.ec2.domain.PasswordData; import org.jclouds.ec2.reference.EC2Constants; +import org.jclouds.ec2.services.WindowsClient; +import org.jclouds.encryption.bouncycastle.config.BouncyCastleCryptoModule; import org.jclouds.predicates.RetryablePredicate; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -57,7 +62,7 @@ import com.google.common.collect.Iterables; @Test(groups = "live", singleThreaded = true, testName = "WindowsClientLiveTest") public class WindowsClientLiveTest extends BaseComputeServiceContextLiveTest { public WindowsClientLiveTest() { - provider = "ec2"; + provider = "aws-ec2"; } private ComputeService computeService; @@ -65,13 +70,6 @@ public class WindowsClientLiveTest extends BaseComputeServiceContextLiveTest { private static final String DEFAULT_INSTANCE = "i-TODO"; private static final String DEFAULT_BUCKET = "TODO"; - @Override - protected Properties setupProperties() { - Properties overrides = super.setupProperties(); - overrides.put(EC2Constants.PROPERTY_EC2_AMI_OWNERS, "206029621532"); /* Amazon Owner ID */ - return overrides; - } - @Override @BeforeClass(groups = { "integration", "live" }) public void setupContext() { @@ -80,7 +78,15 @@ public class WindowsClientLiveTest extends BaseComputeServiceContextLiveTest { computeService = view.getComputeService(); } - + @Override + protected Iterable setupModules() { + Iterable superModules = super.setupModules(); + List modules = new ArrayList(); + Iterables.addAll(modules, superModules); + modules.add(new BouncyCastleCryptoModule()); + return modules; + } + @Test(enabled = false) // TODO get instance public void testBundleInstanceInRegion() { @@ -112,7 +118,7 @@ public class WindowsClientLiveTest extends BaseComputeServiceContextLiveTest { Template template = computeService.templateBuilder() .osFamily(OsFamily.WINDOWS) .os64Bit(true) - .imageNameMatches("Windows-2008R2-SP1-English-Base-") + .imageNameMatches("Windows_Server-2008-R2_SP1-English-64Bit-Base-") .hardwareId(InstanceType.M1_LARGE) .options(TemplateOptions.Builder.inboundPorts(3389)) .build(); diff --git a/providers/gogrid/src/test/java/org/jclouds/gogrid/GoGridLiveTestDisabled.java b/providers/gogrid/src/test/java/org/jclouds/gogrid/GoGridLiveTestDisabled.java index 940858cff0..8db55df797 100644 --- a/providers/gogrid/src/test/java/org/jclouds/gogrid/GoGridLiveTestDisabled.java +++ b/providers/gogrid/src/test/java/org/jclouds/gogrid/GoGridLiveTestDisabled.java @@ -53,7 +53,6 @@ import org.jclouds.gogrid.options.GetImageListOptions; import org.jclouds.gogrid.predicates.LoadBalancerLatestJobCompleted; import org.jclouds.gogrid.predicates.ServerLatestJobCompleted; import org.jclouds.javax.annotation.Nullable; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.InetSocketAddressConnect; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.rest.RestContext; @@ -66,6 +65,7 @@ import org.testng.annotations.Test; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; +import com.google.common.net.HostAndPort; /** * End to end live test for GoGrid @@ -341,9 +341,9 @@ public class GoGridLiveTestDisabled extends BaseComputeServiceContextLiveTest { LoginCredentials instanceCredentials = LoginCredentials.fromCredentials(credsMap.get(createdServer.getName())); assertNotNull(instanceCredentials); - IPSocket socket = new IPSocket(createdServer.getIp().getIp(), 22); + HostAndPort socket = HostAndPort.fromParts(createdServer.getIp().getIp(), 22); - RetryablePredicate socketOpen = new RetryablePredicate(new InetSocketAddressConnect(), 180, + RetryablePredicate socketOpen = new RetryablePredicate(new InetSocketAddressConnect(), 180, 5, TimeUnit.SECONDS); socketOpen.apply(socket); diff --git a/providers/hpcloud-compute/src/test/java/org/jclouds/hpcloud/compute/compute/HPCloudComputeTemplateBuilderLiveTest.java b/providers/hpcloud-compute/src/test/java/org/jclouds/hpcloud/compute/compute/HPCloudComputeTemplateBuilderLiveTest.java index 97ba69bd92..59f7b5d1be 100644 --- a/providers/hpcloud-compute/src/test/java/org/jclouds/hpcloud/compute/compute/HPCloudComputeTemplateBuilderLiveTest.java +++ b/providers/hpcloud-compute/src/test/java/org/jclouds/hpcloud/compute/compute/HPCloudComputeTemplateBuilderLiveTest.java @@ -73,9 +73,11 @@ public class HPCloudComputeTemplateBuilderLiveTest extends BaseTemplateBuilderLi assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true); assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "11.10"); assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU); - assertEquals(defaultTemplate.getImage().getName(), "Ubuntu Oneiric 11.10 Server 64-bit 20111212"); + assertEquals(defaultTemplate.getImage().getName(), "Ubuntu Oneiric 11.10 Server 64-bit 20120311"); assertEquals(defaultTemplate.getImage().getDefaultCredentials().getUser(), "ubuntu"); assertEquals(defaultTemplate.getLocation().getId(), "az-2.region-a.geo-1"); + assertEquals(defaultTemplate.getImage().getLocation().getId(), "az-2.region-a.geo-1"); + assertEquals(defaultTemplate.getHardware().getLocation().getId(), "az-2.region-a.geo-1"); assertEquals(defaultTemplate.getOptions().as(NovaTemplateOptions.class).shouldAutoAssignFloatingIp(), true); assertEquals(getCores(defaultTemplate.getHardware()), 1.0d); } diff --git a/providers/slicehost/src/test/java/org/jclouds/slicehost/SlicehostClientLiveTest.java b/providers/slicehost/src/test/java/org/jclouds/slicehost/SlicehostClientLiveTest.java index 5af27f5e48..44d00b92f9 100644 --- a/providers/slicehost/src/test/java/org/jclouds/slicehost/SlicehostClientLiveTest.java +++ b/providers/slicehost/src/test/java/org/jclouds/slicehost/SlicehostClientLiveTest.java @@ -32,7 +32,6 @@ import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest; import org.jclouds.domain.LoginCredentials; import org.jclouds.http.HttpResponseException; import org.jclouds.io.Payloads; -import org.jclouds.net.IPSocket; import org.jclouds.predicates.RetryablePredicate; import org.jclouds.predicates.SocketOpen; import org.jclouds.slicehost.domain.Flavor; @@ -46,6 +45,7 @@ import org.testng.annotations.Test; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; +import com.google.common.net.HostAndPort; import com.google.inject.Injector; /** @@ -62,7 +62,7 @@ public class SlicehostClientLiveTest extends BaseComputeServiceContextLiveTest { protected SlicehostClient client; protected SshClient.Factory sshFactory; - private Predicate socketTester; + private Predicate socketTester; @BeforeGroups(groups = { "integration", "live" }) @Override @@ -73,7 +73,7 @@ public class SlicehostClientLiveTest extends BaseComputeServiceContextLiveTest { client = injector.getInstance(SlicehostClient.class); sshFactory = injector.getInstance(SshClient.Factory.class); SocketOpen socketOpen = injector.getInstance(SocketOpen.class); - socketTester = new RetryablePredicate(socketOpen, 120, 1, TimeUnit.SECONDS); + socketTester = new RetryablePredicate(socketOpen, 120, 1, TimeUnit.SECONDS); injector.injectMembers(socketOpen); // add logger } @@ -254,7 +254,7 @@ public class SlicehostClientLiveTest extends BaseComputeServiceContextLiveTest { private void doCreateMarkerFile(Slice newDetails, String pass) throws IOException { String ip = getIp(newDetails); - IPSocket socket = new IPSocket(ip, 22); + HostAndPort socket = HostAndPort.fromParts(ip, 22); socketTester.apply(socket); SshClient client = sshFactory.create(socket, LoginCredentials.builder().user("root").password(pass).build()); diff --git a/providers/softlayer/src/test/java/org/jclouds/softlayer/compute/SoftLayerComputeServiceAdapterLiveTest.java b/providers/softlayer/src/test/java/org/jclouds/softlayer/compute/SoftLayerComputeServiceAdapterLiveTest.java index 2b40b84935..6f868a454c 100644 --- a/providers/softlayer/src/test/java/org/jclouds/softlayer/compute/SoftLayerComputeServiceAdapterLiveTest.java +++ b/providers/softlayer/src/test/java/org/jclouds/softlayer/compute/SoftLayerComputeServiceAdapterLiveTest.java @@ -29,7 +29,6 @@ import org.jclouds.compute.domain.Template; import org.jclouds.compute.functions.DefaultCredentialsFromImageOrOverridingCredentials; import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate; import org.jclouds.domain.LoginCredentials; -import org.jclouds.net.IPSocket; import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions; import org.jclouds.softlayer.compute.strategy.SoftLayerComputeServiceAdapter; import org.jclouds.softlayer.domain.ProductItem; @@ -41,6 +40,7 @@ import org.testng.annotations.BeforeGroups; import org.testng.annotations.Test; import com.google.common.collect.Iterables; +import com.google.common.net.HostAndPort; import com.google.common.net.InetAddresses; @Test(groups = "live", singleThreaded = true, testName = "SoftLayerComputeServiceAdapterLiveTest") @@ -82,7 +82,7 @@ public class SoftLayerComputeServiceAdapterLiveTest extends BaseSoftLayerClientL } protected void doConnectViaSsh(VirtualGuest guest, LoginCredentials creds) { - SshClient ssh = view.utils().sshFactory().create(new IPSocket(guest.getPrimaryIpAddress(), 22), creds); + SshClient ssh = view.utils().sshFactory().create(HostAndPort.fromParts(guest.getPrimaryIpAddress(), 22), creds); try { ssh.connect(); ExecResponse hello = ssh.exec("echo hello"); diff --git a/providers/trmk-ecloud/src/test/java/org/jclouds/trmk/ecloud/TerremarkECloudClientLiveTest.java b/providers/trmk-ecloud/src/test/java/org/jclouds/trmk/ecloud/TerremarkECloudClientLiveTest.java index 0c57ddd652..e16e914873 100644 --- a/providers/trmk-ecloud/src/test/java/org/jclouds/trmk/ecloud/TerremarkECloudClientLiveTest.java +++ b/providers/trmk-ecloud/src/test/java/org/jclouds/trmk/ecloud/TerremarkECloudClientLiveTest.java @@ -22,7 +22,6 @@ import java.util.Map.Entry; import java.util.Properties; import org.jclouds.domain.LoginCredentials; -import org.jclouds.net.IPSocket; import org.jclouds.ssh.SshClient; import org.jclouds.trmk.ecloud.suppliers.TerremarkECloudInternetServiceAndPublicIpAddressSupplier; import org.jclouds.trmk.vcloud_0_8.TerremarkClientLiveTest; @@ -33,6 +32,8 @@ import org.jclouds.trmk.vcloud_0_8.domain.VApp; import org.jclouds.trmk.vcloud_0_8.reference.VCloudConstants; import org.testng.annotations.Test; +import com.google.common.net.HostAndPort; + /** * Tests behavior of {@code TerremarkECloudClient} * @@ -56,7 +57,7 @@ public class TerremarkECloudClientLiveTest extends TerremarkClientLiveTest { @Override - protected SshClient getConnectionFor(IPSocket socket) { + protected SshClient getConnectionFor(HostAndPort socket) { return sshFactory.create(socket, LoginCredentials.builder().user("vcloud").password("TmrkCl0ud1s#1!").privateKey( key.getPrivateKey()).authenticateSudo(true).build()); } diff --git a/sandbox-apis/nirvanix/src/test/java/org/jclouds/nirvanix/sdn/SDNAsyncClientTest.java b/sandbox-apis/nirvanix/src/test/java/org/jclouds/nirvanix/sdn/SDNAsyncClientTest.java index 36c294427e..0a00db3f99 100644 --- a/sandbox-apis/nirvanix/src/test/java/org/jclouds/nirvanix/sdn/SDNAsyncClientTest.java +++ b/sandbox-apis/nirvanix/src/test/java/org/jclouds/nirvanix/sdn/SDNAsyncClientTest.java @@ -85,7 +85,7 @@ public class SDNAsyncClientTest extends RestClientTest { assertRequestLineEquals(request, "POST http://uploader/Upload.ashx?output=json&destFolderPath=adriansmovies&uploadToken=token HTTP/1.1"); assertNonPayloadHeadersEqual(request, ""); - StringBuffer expects = new StringBuffer(); + StringBuilder expects = new StringBuilder(); expects.append("----JCLOUDS--\r\n"); expects.append("Content-Disposition: form-data; name=\"hello\"\r\n"); expects.append("Content-Type: text/plain\r\n\r\n");