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 1422e84d11..6ebdad0d04 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 @@ -61,7 +61,7 @@ import com.google.inject.Module; * * @author Adrian Cole */ -@Test(groups = "live", sequential = true) +@Test(groups = "live", singleThreaded = true) public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest { public EC2ComputeServiceLiveTest() { diff --git a/apis/eucalyptus/src/test/java/org/jclouds/eucalyptus/compute/EucalyptusComputeServiceLiveTest.java b/apis/eucalyptus/src/test/java/org/jclouds/eucalyptus/compute/EucalyptusComputeServiceLiveTest.java index dd8dd0b37e..49f4f34b19 100644 --- a/apis/eucalyptus/src/test/java/org/jclouds/eucalyptus/compute/EucalyptusComputeServiceLiveTest.java +++ b/apis/eucalyptus/src/test/java/org/jclouds/eucalyptus/compute/EucalyptusComputeServiceLiveTest.java @@ -18,6 +18,8 @@ */ package org.jclouds.eucalyptus.compute; +import org.jclouds.compute.domain.ExecResponse; +import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.ec2.compute.EC2ComputeServiceLiveTest; import org.jclouds.http.HttpResponseException; import org.testng.annotations.Test; @@ -69,5 +71,9 @@ public class EucalyptusComputeServiceLiveTest extends EC2ComputeServiceLiveTest public void testDestroyNodes() { super.testDestroyNodes(); } - + + protected void checkResponseEqualsHostname(ExecResponse execResponse, NodeMetadata node1) { + // hostname is not predictable based on node metadata + assert execResponse.getOutput().trim().equals("ubuntu"); + } } diff --git a/compute/src/main/java/org/jclouds/compute/callables/RunScriptOnNodeUsingSsh.java b/compute/src/main/java/org/jclouds/compute/callables/RunScriptOnNodeUsingSsh.java index 8b922bc918..b23310a816 100644 --- a/compute/src/main/java/org/jclouds/compute/callables/RunScriptOnNodeUsingSsh.java +++ b/compute/src/main/java/org/jclouds/compute/callables/RunScriptOnNodeUsingSsh.java @@ -44,6 +44,8 @@ import com.google.inject.assistedinject.AssistedInject; * @author Adrian Cole */ public class RunScriptOnNodeUsingSsh implements RunScriptOnNode { + public static final String MARKER = "RUN_SCRIPT_AS_ROOT_SSH"; + @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) protected Logger logger = Logger.NULL; @@ -102,9 +104,9 @@ public class RunScriptOnNodeUsingSsh implements RunScriptOnNode { public String execAsRoot(String command) { if (node.getCredentials().identity.equals("root")) { } else if (node.getAdminPassword() != null) { - command = String.format("echo '%s'|sudo -S %s", node.getAdminPassword(), command); + command = String.format("sudo -S sh <<'%s'\n%s\n%s%s\n", MARKER, node.getAdminPassword(), command, MARKER); } else { - command = "sudo " + command; + command = String.format("sudo sh <<'%s'\n%s%s\n", MARKER, command, MARKER); } return command; } diff --git a/compute/src/main/java/org/jclouds/compute/predicates/NodePresentAndInIntendedState.java b/compute/src/main/java/org/jclouds/compute/predicates/NodePresentAndInIntendedState.java index 53c4f77c55..dd79eaa8b6 100644 --- a/compute/src/main/java/org/jclouds/compute/predicates/NodePresentAndInIntendedState.java +++ b/compute/src/main/java/org/jclouds/compute/predicates/NodePresentAndInIntendedState.java @@ -20,6 +20,8 @@ package org.jclouds.compute.predicates; import static com.google.common.base.Preconditions.checkNotNull; +import java.util.Set; + import javax.annotation.Resource; import javax.inject.Singleton; @@ -29,6 +31,7 @@ import org.jclouds.compute.domain.NodeState; import org.jclouds.logging.Logger; import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableSet; import com.google.inject.Inject; /** @@ -42,13 +45,19 @@ public class NodePresentAndInIntendedState implements Predicate { private final ComputeService client; private final NodeState intended; + private final Set invalids; @Resource protected Logger logger = Logger.NULL; @Inject public NodePresentAndInIntendedState(NodeState intended, ComputeService client) { + this(intended, ImmutableSet.of(NodeState.ERROR), client); + } + + public NodePresentAndInIntendedState(NodeState intended, Set invalids, ComputeService client) { this.intended = intended; this.client = client; + this.invalids = invalids; } public boolean apply(NodeMetadata node) { @@ -57,9 +66,9 @@ public class NodePresentAndInIntendedState implements Predicate { if (node == null) return false; logger.trace("%s: looking for node state %s: currently: %s", node.getId(), intended, node.getState()); - if (node.getState() == NodeState.ERROR) + if (invalids.contains(node.getState())) throw new IllegalStateException("node " + node.getId() + " in location " + node.getLocation() - + " is in error state"); + + " is in invalid state "+node.getState()); return node.getState() == intended; } diff --git a/compute/src/main/java/org/jclouds/compute/predicates/NodeRunning.java b/compute/src/main/java/org/jclouds/compute/predicates/NodeRunning.java index bb38120f1d..0c03ce697d 100644 --- a/compute/src/main/java/org/jclouds/compute/predicates/NodeRunning.java +++ b/compute/src/main/java/org/jclouds/compute/predicates/NodeRunning.java @@ -23,6 +23,7 @@ import javax.inject.Singleton; import org.jclouds.compute.ComputeService; import org.jclouds.compute.domain.NodeState; +import com.google.common.collect.ImmutableSet; import com.google.inject.Inject; /** @@ -36,6 +37,6 @@ public class NodeRunning extends NodePresentAndInIntendedState { @Inject public NodeRunning(ComputeService client) { - super(NodeState.RUNNING, client); + super(NodeState.RUNNING, ImmutableSet.of(NodeState.ERROR, NodeState.TERMINATED), client); } } diff --git a/compute/src/test/java/org/jclouds/compute/callable/RunScriptOnNodeUsingSshTest.java b/compute/src/test/java/org/jclouds/compute/callable/RunScriptOnNodeUsingSshTest.java new file mode 100644 index 0000000000..976d742482 --- /dev/null +++ b/compute/src/test/java/org/jclouds/compute/callable/RunScriptOnNodeUsingSshTest.java @@ -0,0 +1,139 @@ +/** + * 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.compute.callable; + +import com.google.common.base.Function; +import org.jclouds.compute.callables.RunScriptOnNodeUsingSsh; +import org.jclouds.compute.domain.ExecResponse; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.domain.Credentials; +import org.jclouds.javax.annotation.Nullable; +import org.jclouds.scriptbuilder.statements.login.UserAdd; +import org.jclouds.ssh.SshClient; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import static org.easymock.EasyMock.*; +import static org.jclouds.compute.options.RunScriptOptions.Builder.wrapInInitScript; +import static org.jclouds.scriptbuilder.domain.Statements.exec; + +/** + * @author Adam Lowe + */ +@Test(groups={"unit"}, singleThreaded = true) +public class RunScriptOnNodeUsingSshTest { + private SshClient sshClient; + private NodeMetadata node; + private Function sshFactory; + + @BeforeMethod(groups={"unit"}) + public void init() { + sshClient = createMock(SshClient.class); + sshFactory = new Function() { + @Override + public SshClient apply(@Nullable NodeMetadata nodeMetadata) { + return sshClient; + } + }; + node = createMock(NodeMetadata.class); + expect(node.getCredentials()).andReturn(new Credentials("tester", "notalot")); + expect(node.getAdminPassword()).andReturn(null).atLeastOnce(); + replay(node); + } + + public void simpleTest() { + RunScriptOnNodeUsingSsh testMe = new RunScriptOnNodeUsingSsh(sshFactory, node, exec("echo $USER\necho $USER"), + wrapInInitScript(false).runAsRoot(false)); + + testMe.init(); + + sshClient.connect(); + expect(sshClient.getUsername()).andReturn("tester"); + expect(sshClient.getHostAddress()).andReturn("somewhere.example.com"); + expect(sshClient.exec("echo $USER\n" + + "echo $USER\n")).andReturn(new ExecResponse("tester\ntester\n", null, 0)); + sshClient.disconnect(); + replay(sshClient); + + testMe.call(); + } + + public void simpleRootTest() { + RunScriptOnNodeUsingSsh testMe = new RunScriptOnNodeUsingSsh(sshFactory, node, exec("echo $USER\necho $USER"), + wrapInInitScript(false).runAsRoot(true)); + + testMe.init(); + + sshClient.connect(); + expect(sshClient.getUsername()).andReturn("tester"); + expect(sshClient.getHostAddress()).andReturn("somewhere.example.com"); + expect(sshClient.exec("sudo sh <<'RUN_SCRIPT_AS_ROOT_SSH'\n" + + "echo $USER\n" + + "echo $USER\n" + + "RUN_SCRIPT_AS_ROOT_SSH\n")).andReturn(new ExecResponse("root\nroot\n", null, 0)); + sshClient.disconnect(); + replay(sshClient); + + testMe.call(); + } + + public void simpleRootTestWithSudoPassword() { + node = createMock(NodeMetadata.class); + expect(node.getCredentials()).andReturn(new Credentials("tester", "notalot")); + expect(node.getAdminPassword()).andReturn("testpassword!").atLeastOnce(); + replay(node); + RunScriptOnNodeUsingSsh testMe = new RunScriptOnNodeUsingSsh(sshFactory, node, exec("echo $USER\necho $USER"), + wrapInInitScript(false).runAsRoot(true)); + testMe.init(); + + sshClient.connect(); + expect(sshClient.getUsername()).andReturn("tester"); + expect(sshClient.getHostAddress()).andReturn("somewhere.example.com"); + expect(sshClient.exec("sudo -S sh <<'RUN_SCRIPT_AS_ROOT_SSH'\n" + + "testpassword!\n" + + "echo $USER\n" + + "echo $USER\n" + + "RUN_SCRIPT_AS_ROOT_SSH\n")).andReturn(new ExecResponse("root\nroot\n", null, 0)); + sshClient.disconnect(); + replay(sshClient); + + testMe.call(); + } + + public void testUserAddAsRoot() { + RunScriptOnNodeUsingSsh testMe = new RunScriptOnNodeUsingSsh(sshFactory, node, + UserAdd.builder().login("testuser").build(), + wrapInInitScript(false).runAsRoot(true).overrideLoginCredentialWith("test")); + + testMe.init(); + + sshClient.connect(); + expect(sshClient.getUsername()).andReturn("tester"); + expect(sshClient.getHostAddress()).andReturn("somewhere.example.com"); + expect(sshClient.exec("sudo sh <<'RUN_SCRIPT_AS_ROOT_SSH'\n" + + "mkdir -p /home/users/testuser\n" + + "useradd -s /bin/bash -d /home/users/testuser testuser\n" + + "chown -R testuser /home/users/testuser\n" + + "RUN_SCRIPT_AS_ROOT_SSH\n")).andReturn(new ExecResponse("done", null, 0)); + sshClient.disconnect(); + replay(sshClient); + + testMe.call(); + } +} diff --git a/compute/src/test/java/org/jclouds/compute/predicates/NodePredicatesTest.java b/compute/src/test/java/org/jclouds/compute/predicates/NodePredicatesTest.java new file mode 100644 index 0000000000..0abfcd9cb9 --- /dev/null +++ b/compute/src/test/java/org/jclouds/compute/predicates/NodePredicatesTest.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.compute.predicates; + +import static org.easymock.EasyMock.expect; +import static org.easymock.classextension.EasyMock.createMock; +import static org.easymock.classextension.EasyMock.replay; + +import org.jclouds.compute.ComputeService; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.NodeState; +import org.testng.Assert; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** + * Tests possible uses of OperatingSystemPredicates + * + * @author Aled Sage + */ +@Test(singleThreaded = true, testName = "NodePredicatesTest") +public class NodePredicatesTest { + + private NodeMetadata node; + private ComputeService computeService; + + @BeforeMethod + public void setUp() throws Exception { + node = createMock(NodeMetadata.class); + computeService = createMock(ComputeService.class); + + expect(node.getId()).andReturn("myid").anyTimes(); + expect(computeService.getNodeMetadata("myid")).andReturn(node).anyTimes(); + expect(node.getLocation()).andReturn(null).anyTimes(); + } + + @Test + public void testNodeRunningReturnsTrueWhenRunning() { + expect(node.getState()).andReturn(NodeState.RUNNING).atLeastOnce(); + replay(node); + replay(computeService); + + NodeRunning nodeRunning = new NodeRunning(computeService); + Assert.assertTrue(nodeRunning.apply(node)); + } + + @Test(expectedExceptions = IllegalStateException.class) + public void testNodeRunningFailsOnTerminated() { + expect(node.getState()).andReturn(NodeState.TERMINATED).atLeastOnce(); + replay(node); + replay(computeService); + + NodeRunning nodeRunning = new NodeRunning(computeService); + nodeRunning.apply(node); + } + + @Test(expectedExceptions = IllegalStateException.class) + public void testNodeRunningFailsOnError() { + expect(node.getState()).andReturn(NodeState.ERROR).atLeastOnce(); + replay(node); + replay(computeService); + + NodeRunning nodeRunning = new NodeRunning(computeService); + nodeRunning.apply(node); + } +} diff --git a/core/pom.xml b/core/pom.xml index ba806763cc..b621d1778c 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -104,7 +104,7 @@ com.google.code.gson gson - 1.7.1 + 1.7.2 com.google.guava diff --git a/core/src/main/java/org/jclouds/rest/config/ClientProvider.java b/core/src/main/java/org/jclouds/rest/config/ClientProvider.java index 5fd6307f5a..4f27a0ba11 100644 --- a/core/src/main/java/org/jclouds/rest/config/ClientProvider.java +++ b/core/src/main/java/org/jclouds/rest/config/ClientProvider.java @@ -35,6 +35,8 @@ import com.google.inject.TypeLiteral; import com.google.inject.name.Names; /** + * ClientProvider makes the primary interface for the provider context. ex. {@code + * context.getProviderSpecificContext().getApi()} is created by ClientProvider, which is a singleton * * @author Adrian Cole */ @@ -47,8 +49,7 @@ public class ClientProvider implements Provider { private final Map, Class> sync2Async; @Inject - ClientProvider(Class syncClientType, Class asyncClientType, - Map, Class> sync2Async) { + ClientProvider(Class syncClientType, Class asyncClientType, Map, Class> sync2Async) { this.asyncClientType = asyncClientType; this.syncClientType = syncClientType; this.sync2Async = sync2Async; diff --git a/core/src/main/java/org/jclouds/rest/config/CreateClientForCaller.java b/core/src/main/java/org/jclouds/rest/config/CreateClientForCaller.java index 277e789f69..ea89877b8a 100644 --- a/core/src/main/java/org/jclouds/rest/config/CreateClientForCaller.java +++ b/core/src/main/java/org/jclouds/rest/config/CreateClientForCaller.java @@ -36,6 +36,9 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheLoader; /** + * CreateClientForCaller is parameterized, so clients it creates aren't singletons. For example, + * CreateClientForCaller satisfies a call like this: + * {@code context.getProviderSpecificContext().getApi().getOrgClientForName(name)} * * @author Adrian Cole */ @@ -57,8 +60,7 @@ public class CreateClientForCaller extends CacheLoader public Object load(ClassMethodArgs from) throws ExecutionException { Class syncClass = from.getMethod().getReturnType(); Class asyncClass = sync2Async.get(syncClass); - checkState(asyncClass != null, "configuration error, sync class " + syncClass - + " not mapped to an async class"); + checkState(asyncClass != null, "configuration error, sync class " + syncClass + " not mapped to an async class"); Object asyncClient = asyncMap.get(from); checkState(asyncClient != null, "configuration error, sync client for " + from + " not found"); try { diff --git a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java index b6f7b95403..6ea7e2a4a7 100644 --- a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java +++ b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java @@ -46,9 +46,9 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; import java.util.SortedSet; +import java.util.Map.Entry; import java.util.concurrent.ExecutionException; import javax.annotation.Resource; @@ -77,7 +77,6 @@ import org.jclouds.http.HttpUtils; import org.jclouds.http.functions.ParseFirstJsonValueNamed; import org.jclouds.http.functions.ParseJson; import org.jclouds.http.functions.ParseSax; -import org.jclouds.http.functions.ParseSax.HandlerWithResult; import org.jclouds.http.functions.ParseURIFromListOrLocationHeaderIf20x; import org.jclouds.http.functions.ReleasePayloadAndReturn; import org.jclouds.http.functions.ReturnInputStream; @@ -87,6 +86,7 @@ import org.jclouds.http.functions.UnwrapOnlyJsonValue; import org.jclouds.http.functions.UnwrapOnlyJsonValueInSet; import org.jclouds.http.functions.UnwrapOnlyNestedJsonValue; import org.jclouds.http.functions.UnwrapOnlyNestedJsonValueInSet; +import org.jclouds.http.functions.ParseSax.HandlerWithResult; import org.jclouds.http.options.HttpRequestOptions; import org.jclouds.http.utils.ModifyRequest; import org.jclouds.internal.ClassMethodArgs; @@ -135,6 +135,7 @@ import org.jclouds.util.Strings2; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; import com.google.common.base.Functions; +import com.google.common.base.Preconditions; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.base.Throwables; @@ -144,12 +145,12 @@ import com.google.common.cache.CacheLoader; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSet.Builder; import com.google.common.collect.Iterables; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.LinkedListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; +import com.google.common.collect.ImmutableSet.Builder; import com.google.common.util.concurrent.ListenableFuture; import com.google.inject.Inject; import com.google.inject.Injector; @@ -920,12 +921,12 @@ public class RestAnnotationProcessor { }; public GeneratedHttpRequest decorateRequest(GeneratedHttpRequest request) throws NegativeArraySizeException, - ExecutionException { + ExecutionException { OUTER: for (Entry> entry : concat(// - filterValues(methodToIndexOfParamToBinderParamAnnotation.get(request.getJavaMethod()).asMap(), notEmpty) - .entrySet(), // - filterValues(methodToIndexOfParamToWrapWithAnnotation.get(request.getJavaMethod()).asMap(), notEmpty) - .entrySet())) { + filterValues(methodToIndexOfParamToBinderParamAnnotation.get(request.getJavaMethod()).asMap(), notEmpty) + .entrySet(), // + filterValues(methodToIndexOfParamToWrapWithAnnotation.get(request.getJavaMethod()).asMap(), notEmpty) + .entrySet())) { boolean shouldBreak = false; Annotation annotation = Iterables.get(entry.getValue(), 0); Binder binder; @@ -933,7 +934,7 @@ public class RestAnnotationProcessor { binder = injector.getInstance(BinderParam.class.cast(annotation).value()); else binder = injector.getInstance(BindToJsonPayloadWrappedWith.Factory.class).create( - WrapWith.class.cast(annotation).value()); + WrapWith.class.cast(annotation).value()); if (request.getArgs().size() >= entry.getKey() + 1 && request.getArgs().get(entry.getKey()) != null) { Object input; Class parameterType = request.getJavaMethod().getParameterTypes()[entry.getKey()]; @@ -959,6 +960,27 @@ public class RestAnnotationProcessor { } if (shouldBreak) break OUTER; + } else { + // either arg is null, or request.getArgs().size() < entry.getKey() + 1 + // in either case, we require that null be allowed + // (first, however, let's make sure we have enough args on the actual method) + if (entry.getKey() >= request.getJavaMethod().getParameterAnnotations().length) { + // not known whether this happens + throw new IllegalArgumentException("Argument index " + (entry.getKey() + 1) + + " is out of bounds for method " + request.getJavaMethod()); + } + + if (request.getJavaMethod().isVarArgs() + && entry.getKey() + 1 == request.getJavaMethod().getParameterTypes().length) + // allow null/missing for var args + continue OUTER; + + Annotation[] annotations = request.getJavaMethod().getParameterAnnotations()[entry.getKey()]; + for (Annotation a : annotations) { + if (Nullable.class.isAssignableFrom(a.annotationType())) + continue OUTER; + } + Preconditions.checkNotNull(null, request.getJavaMethod().getName() + " parameter " + (entry.getKey() + 1)); } } @@ -1093,7 +1115,9 @@ public class RestAnnotationProcessor { options.contentType(param.contentType()); if (!PartParam.NO_FILENAME.equals(param.filename())) options.filename(Strings2.replaceTokens(param.filename(), iterable)); - Part part = Part.create(param.name(), newPayload(args[entry.getKey()]), options); + Object arg = args[entry.getKey()]; + Preconditions.checkNotNull(arg, param.name()); + Part part = Part.create(param.name(), newPayload(arg), options); parts.add(part); } } @@ -1200,7 +1224,9 @@ public class RestAnnotationProcessor { ParamParser extractor = (ParamParser) extractors.iterator().next(); paramValue = injector.getInstance(extractor.value()).apply(args[entry.getKey()]); } else { - paramValue = args[entry.getKey()].toString(); + Object pvo = args[entry.getKey()]; + Preconditions.checkNotNull(pvo, paramKey); + paramValue = pvo.toString(); } formParamValues.put(paramKey, paramValue); } 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 f98fb7ab18..ced959e11b 100644 --- a/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java +++ b/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java @@ -143,6 +143,7 @@ import org.jclouds.rest.binders.BindToJsonPayload; import org.jclouds.rest.binders.BindToStringPayload; import org.jclouds.rest.config.RestClientModule; import org.jclouds.util.Strings2; +import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -552,6 +553,9 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest { @POST void post(@Nullable @BinderParam(BindToStringPayload.class) String content); + @POST + void postNonnull(@BinderParam(BindToStringPayload.class) String content); + @POST public void postAsJson(@BinderParam(BindToJsonPayload.class) String content); @@ -587,7 +591,7 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest { assertPayloadEquals(request, "data", "application/unknown", false); } - public void testCreatePostRequestNullOk() throws SecurityException, NoSuchMethodException, IOException { + public void testCreatePostRequestNullOk1() throws SecurityException, NoSuchMethodException, IOException { Method method = TestPost.class.getMethod("post", String.class); HttpRequest request = factory(TestPost.class).createRequest(method); @@ -596,6 +600,41 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest { assertPayloadEquals(request, null, "application/unknown", false); } + public void testCreatePostRequestNullOk2() throws SecurityException, NoSuchMethodException, IOException { + Method method = TestPost.class.getMethod("post", String.class); + HttpRequest request = factory(TestPost.class).createRequest(method, (String) null); + + assertRequestLineEquals(request, "POST http://localhost:9999 HTTP/1.1"); + assertNonPayloadHeadersEqual(request, ""); + assertPayloadEquals(request, null, "application/unknown", false); + } + + public void testCreatePostRequestNullNotOk1() throws SecurityException, NoSuchMethodException, IOException { + Method method = TestPost.class.getMethod("postNonnull", String.class); + try { + HttpRequest request = factory(TestPost.class).createRequest(method); + Assert + .fail("call should have failed with illegal null parameter, not permitted " + request + + " to be created"); + } catch (NullPointerException e) { + Assert.assertTrue(e.toString().indexOf("postNonnull parameter 1") >= 0, + "Error message should have referred to 'parameter 1': " + e); + } + } + + public void testCreatePostRequestNullNotOk2() throws SecurityException, NoSuchMethodException, IOException { + Method method = TestPost.class.getMethod("postNonnull", String.class); + try { + HttpRequest request = factory(TestPost.class).createRequest(method, (String) null); + Assert + .fail("call should have failed with illegal null parameter, not permitted " + request + + " to be created"); + } catch (NullPointerException e) { + Assert.assertTrue(e.toString().indexOf("postNonnull parameter 1") >= 0, + "Error message should have referred to parameter 'parameter 1': " + e); + } + } + public void testCreatePostJsonRequest() throws SecurityException, NoSuchMethodException, IOException { Method method = TestPost.class.getMethod("postAsJson", String.class); HttpRequest request = factory(TestPost.class).createRequest(method, "data"); @@ -684,6 +723,17 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest { "----JCLOUDS----\r\n", "multipart/form-data; boundary=--JCLOUDS--", false); } + public void testMultipartWithStringPartNullNotOkay() throws SecurityException, NoSuchMethodException, IOException { + Method method = TestMultipartForm.class.getMethod("withStringPart", String.class); + try { + GeneratedHttpRequest httpRequest = factory(TestMultipartForm.class).createRequest(method, + (String)null); + Assert.fail("call should have failed with illegal null parameter, not permitted "+httpRequest+" to be created"); + } catch (NullPointerException e) { + Assert.assertTrue(e.toString().indexOf("fooble")>=0, "Error message should have referred to parameter 'fooble': "+e); + } + } + public void testMultipartWithParamStringPart() throws SecurityException, NoSuchMethodException, IOException { Method method = TestMultipartForm.class.getMethod("withParamStringPart", String.class, String.class); GeneratedHttpRequest httpRequest = factory(TestMultipartForm.class).createRequest(method, @@ -702,6 +752,17 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest { "----JCLOUDS----\r\n", "multipart/form-data; boundary=--JCLOUDS--", false); } + public void testMultipartWithParamStringPartNullNotOk() throws SecurityException, NoSuchMethodException, IOException { + Method method = TestMultipartForm.class.getMethod("withParamStringPart", String.class, String.class); + try { + GeneratedHttpRequest httpRequest = factory(TestMultipartForm.class).createRequest(method, + null, "foobledata"); + Assert.fail("call should have failed with illegal null parameter, not permitted "+httpRequest+" to be created"); + } catch (NullPointerException e) { + Assert.assertTrue(e.toString().indexOf("name")>=0, "Error message should have referred to parameter 'name': "+e); + } + } + public void testMultipartWithParamFilePart() throws SecurityException, NoSuchMethodException, IOException { Method method = TestMultipartForm.class.getMethod("withParamFilePart", String.class, File.class); File file = File.createTempFile("foo", "bar"); diff --git a/providers/eucalyptus-partnercloud-ec2/src/test/java/org/jclouds/epc/compute/EucalyptusPartnerCloudEucalyptusComputeServiceLiveTest.java b/providers/eucalyptus-partnercloud-ec2/src/test/java/org/jclouds/epc/compute/EucalyptusPartnerCloudEucalyptusComputeServiceLiveTest.java index e0dd96036e..80607c2016 100644 --- a/providers/eucalyptus-partnercloud-ec2/src/test/java/org/jclouds/epc/compute/EucalyptusPartnerCloudEucalyptusComputeServiceLiveTest.java +++ b/providers/eucalyptus-partnercloud-ec2/src/test/java/org/jclouds/epc/compute/EucalyptusPartnerCloudEucalyptusComputeServiceLiveTest.java @@ -27,7 +27,7 @@ import org.testng.annotations.Test; * * @author Adrian Cole */ -@Test(groups = "live", sequential = true, testName = "EucalyptusPartnerCloudEucalyptusComputeServiceLiveTest") +@Test(groups = "live", singleThreaded = true, testName = "EucalyptusPartnerCloudEucalyptusComputeServiceLiveTest") public class EucalyptusPartnerCloudEucalyptusComputeServiceLiveTest extends EucalyptusComputeServiceLiveTest { public EucalyptusPartnerCloudEucalyptusComputeServiceLiveTest() { @@ -45,8 +45,4 @@ public class EucalyptusPartnerCloudEucalyptusComputeServiceLiveTest extends Euca return overrides; } - // test hangs - @Override - public void testExtendedOptionsAndLogin() throws Exception { - } } diff --git a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/SoftLayerPropertiesBuilder.java b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/SoftLayerPropertiesBuilder.java index c6aeeaa538..32bab70201 100644 --- a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/SoftLayerPropertiesBuilder.java +++ b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/SoftLayerPropertiesBuilder.java @@ -39,6 +39,7 @@ public class SoftLayerPropertiesBuilder extends PropertiesBuilder { properties.setProperty(PROPERTY_ENDPOINT, "https://api.softlayer.com/rest"); properties.setProperty(PROPERTY_API_VERSION, "3"); properties.setProperty(SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME, "Cloud Server"); + properties.setProperty(SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY, ""+60*60*1000); properties.setProperty(PROPERTY_ISO3166_CODES, "SG,US-CA,US-TX,US-VA,US-WA,US-TX"); return properties; } diff --git a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/compute/config/SoftLayerComputeServiceContextModule.java b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/compute/config/SoftLayerComputeServiceContextModule.java index 0bc9dfd027..4bfe242d62 100644 --- a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/compute/config/SoftLayerComputeServiceContextModule.java +++ b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/compute/config/SoftLayerComputeServiceContextModule.java @@ -36,6 +36,7 @@ import org.jclouds.softlayer.compute.functions.ProductItemsToHardware; import org.jclouds.softlayer.compute.functions.VirtualGuestToNodeMetadata; import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions; import org.jclouds.softlayer.compute.strategy.SoftLayerComputeServiceAdapter; +import org.jclouds.softlayer.config.SoftLayerParserModule; import org.jclouds.softlayer.domain.Datacenter; import org.jclouds.softlayer.domain.ProductItem; import org.jclouds.softlayer.domain.VirtualGuest; @@ -59,6 +60,7 @@ public class SoftLayerComputeServiceContextModule extends @Override protected void configure() { super.configure(); + install(new SoftLayerParserModule()); bind(new TypeLiteral, ProductItem, Datacenter>>() {}) .to(SoftLayerComputeServiceAdapter.class); bind(new TypeLiteral>() {}) diff --git a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/compute/functions/ProductItemsToHardware.java b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/compute/functions/ProductItemsToHardware.java index b6c7ff3268..bf618dc9bb 100644 --- a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/compute/functions/ProductItemsToHardware.java +++ b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/compute/functions/ProductItemsToHardware.java @@ -48,7 +48,7 @@ import static org.jclouds.softlayer.predicates.ProductItemPredicates.*; @Singleton public class ProductItemsToHardware implements Function, Hardware> { - private static final double CORE_SPEED = 2.0; + static final double CORE_SPEED = 2.0; @Override public Hardware apply(Set items) { diff --git a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/compute/functions/VirtualGuestToNodeMetadata.java b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/compute/functions/VirtualGuestToNodeMetadata.java index 052aa8dab9..9931251e48 100644 --- a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/compute/functions/VirtualGuestToNodeMetadata.java +++ b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/compute/functions/VirtualGuestToNodeMetadata.java @@ -20,6 +20,7 @@ package org.jclouds.softlayer.compute.functions; import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName; +import static org.jclouds.softlayer.compute.functions.ProductItemsToHardware.CORE_SPEED; import java.util.Map; import java.util.Set; @@ -29,13 +30,10 @@ import javax.inject.Singleton; import org.jclouds.collect.FindResourceInSet; import org.jclouds.collect.Memoized; -import org.jclouds.compute.domain.Hardware; -import org.jclouds.compute.domain.Image; -import org.jclouds.compute.domain.NodeMetadata; -import org.jclouds.compute.domain.NodeMetadataBuilder; -import org.jclouds.compute.domain.NodeState; +import org.jclouds.compute.domain.*; import org.jclouds.domain.Credentials; import org.jclouds.domain.Location; +import org.jclouds.softlayer.domain.Datacenter; import org.jclouds.softlayer.domain.VirtualGuest; import com.google.common.base.Function; @@ -50,25 +48,18 @@ import com.google.common.collect.ImmutableSet; public class VirtualGuestToNodeMetadata implements Function { public static final Map serverStateToNodeState = ImmutableMap - . builder() - .put(VirtualGuest.State.HALTED, NodeState.PENDING) - .put(VirtualGuest.State.PAUSED, NodeState.SUSPENDED) - .put(VirtualGuest.State.RUNNING, NodeState.RUNNING) - .put(VirtualGuest.State.UNRECOGNIZED, NodeState.UNRECOGNIZED) - .build(); + . builder().put(VirtualGuest.State.HALTED, NodeState.PENDING).put( + VirtualGuest.State.PAUSED, NodeState.SUSPENDED).put(VirtualGuest.State.RUNNING, NodeState.RUNNING) + .put(VirtualGuest.State.UNRECOGNIZED, NodeState.UNRECOGNIZED).build(); - private final FindHardwareForVirtualGuest findHardwareForVirtualGuest; - private final FindLocationForVirtualGuest findLocationForVirtualGuest; - private final FindImageForVirtualGuest findImageForVirtualGuest; private final Map credentialStore; + private final FindLocationForVirtualGuest findLocationForVirtualGuest; @Inject - VirtualGuestToNodeMetadata(Map credentialStore, FindHardwareForVirtualGuest findHardwareForVirtualGuest, - FindLocationForVirtualGuest findLocationForVirtualGuest, FindImageForVirtualGuest findImageForVirtualGuest) { + VirtualGuestToNodeMetadata(Map credentialStore, + FindLocationForVirtualGuest findLocationForVirtualGuest) { this.credentialStore = checkNotNull(credentialStore, "credentialStore"); - this.findHardwareForVirtualGuest = checkNotNull(findHardwareForVirtualGuest, "findHardwareForVirtualGuest"); this.findLocationForVirtualGuest = checkNotNull(findLocationForVirtualGuest, "findLocationForVirtualGuest"); - this.findImageForVirtualGuest = checkNotNull(findImageForVirtualGuest, "findImageForVirtualGuest"); } @Override @@ -76,64 +67,57 @@ public class VirtualGuestToNodeMetadata implements Function of(from.getPrimaryIpAddress())); - builder.privateAddresses(ImmutableSet. of(from.getPrimaryBackendIpAddress())); - builder.credentials(credentialStore.get("node#"+ from.getId())); + builder.group(parseGroupFromName(from.getHostname())); + // TODO determine image id (product price)from virtual guest + // builder.imageId(from.imageId + ""); + // TODO make operating system from virtual guest + // builder.operatingSystem(OperatingSystem.builder()...); + + builder.hardware(getHardware(from)); + builder.state(serverStateToNodeState.get(from.getPowerState().getKeyName())); + + // These are null for 'bad' guest orders in the HALTED state. + if (from.getPrimaryIpAddress() != null) + builder.publicAddresses(ImmutableSet. of(from.getPrimaryIpAddress())); + if (from.getPrimaryBackendIpAddress() != null) + builder.privateAddresses(ImmutableSet. of(from.getPrimaryBackendIpAddress())); + + builder.credentials(credentialStore.get("node#" + from.getId())); return builder.build(); } - @Singleton - public static class FindHardwareForVirtualGuest extends FindResourceInSet { - - @Inject - public FindHardwareForVirtualGuest(@Memoized Supplier> hardware) { - super(hardware); - } - - @Override - public boolean matches(VirtualGuest from, Hardware input) { - return input.getProviderId().equals(from.getId() + ""); - } - } - - @Singleton - public static class FindImageForVirtualGuest extends FindResourceInSet { - - @Inject - public FindImageForVirtualGuest(@Memoized Supplier> hardware) { - super(hardware); - } - - @Override - public boolean matches(VirtualGuest from, Image input) { - // TODO determine the price list from the virtual guest which would have the image in it. - return false; - } - } - @Singleton public static class FindLocationForVirtualGuest extends FindResourceInSet { @Inject - public FindLocationForVirtualGuest(@Memoized Supplier> hardware) { - super(hardware); + public FindLocationForVirtualGuest(@Memoized Supplier> location) { + super(location); } @Override public boolean matches(VirtualGuest from, Location input) { - // TODO determine the price list from the virtual guest which would have the image in it. - return false; + Datacenter dc = from.getDatacenter(); + if (dc == null) + return false; + return input.getId().equals(Integer.toString(dc.getId())); } } + + private Hardware getHardware(VirtualGuest from) { + HardwareBuilder builder = new HardwareBuilder().id("TODO"); + + final double cpus = from.getMaxCpu(); + if (cpus>0) { + builder.processor(new Processor(cpus, CORE_SPEED)); + } + + final int maxMemory = from.getMaxMemory(); + if (maxMemory>0) { + builder.ram(maxMemory); + } + + return builder.build(); + } } diff --git a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/compute/strategy/SoftLayerComputeServiceAdapter.java b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/compute/strategy/SoftLayerComputeServiceAdapter.java index ed9f19b017..edcb6ddd08 100644 --- a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/compute/strategy/SoftLayerComputeServiceAdapter.java +++ b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/compute/strategy/SoftLayerComputeServiceAdapter.java @@ -18,46 +18,37 @@ */ package org.jclouds.softlayer.compute.strategy; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static org.jclouds.softlayer.predicates.ProductItemPredicates.categoryCode; -import static org.jclouds.softlayer.predicates.ProductItemPredicates.matches; -import static org.jclouds.softlayer.predicates.ProductItemPredicates.units; -import static org.jclouds.softlayer.predicates.ProductPackagePredicates.named; - -import java.util.Map; -import java.util.Set; - -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Singleton; - -import org.jclouds.compute.ComputeService; -import org.jclouds.compute.ComputeServiceAdapter; -import org.jclouds.compute.domain.Template; -import org.jclouds.domain.Credentials; -import org.jclouds.softlayer.SoftLayerClient; -import org.jclouds.softlayer.compute.functions.ProductItems; -import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions; -import org.jclouds.softlayer.domain.BillingItemVirtualGuest; -import org.jclouds.softlayer.domain.Datacenter; -import org.jclouds.softlayer.domain.OperatingSystem; -import org.jclouds.softlayer.domain.Password; -import org.jclouds.softlayer.domain.ProductItem; -import org.jclouds.softlayer.domain.ProductItemPrice; -import org.jclouds.softlayer.domain.ProductOrder; -import org.jclouds.softlayer.domain.ProductPackage; -import org.jclouds.softlayer.domain.VirtualGuest; -import org.jclouds.softlayer.features.AccountClient; -import org.jclouds.softlayer.features.ProductPackageClient; -import org.jclouds.softlayer.reference.SoftLayerConstants; - +import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.common.collect.Sets; +import org.jclouds.compute.ComputeService; +import org.jclouds.compute.ComputeServiceAdapter; +import org.jclouds.compute.domain.Template; +import org.jclouds.domain.Credentials; +import org.jclouds.predicates.RetryablePredicate; +import org.jclouds.softlayer.SoftLayerClient; +import org.jclouds.softlayer.compute.functions.ProductItems; +import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions; +import org.jclouds.softlayer.domain.*; +import org.jclouds.softlayer.features.AccountClient; +import org.jclouds.softlayer.features.ProductPackageClient; +import org.jclouds.softlayer.reference.SoftLayerConstants; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; +import java.util.Map; +import java.util.Set; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static org.jclouds.softlayer.predicates.ProductItemPredicates.*; +import static org.jclouds.softlayer.predicates.ProductPackagePredicates.named; /** * defines the connection between the {@link SoftLayerClient} implementation and the jclouds @@ -66,19 +57,28 @@ import com.google.common.collect.Sets; */ @Singleton public class SoftLayerComputeServiceAdapter implements - ComputeServiceAdapter, ProductItem, Datacenter> { + ComputeServiceAdapter, ProductItem, Datacenter> { - public static final String SAN_DESCRIPTION_REGEX=".*GB \\(SAN\\).*"; + public static final String SAN_DESCRIPTION_REGEX = ".*GB \\(SAN\\).*"; private static final Float BOOT_VOLUME_CAPACITY = 100F; private final SoftLayerClient client; private final String virtualGuestPackageName; + private final RetryablePredicate loginDetailsTester; + private final long guestLoginDelay; @Inject public SoftLayerComputeServiceAdapter(SoftLayerClient client, - @Named(SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME) String virtualGuestPackageName) { + @Named(SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME) String virtualGuestPackageName, + VirtualGuestHasLoginDetailsPresent virtualGuestHasLoginDetailsPresent, + @Named(SoftLayerConstants.PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY) long guestLoginDelay) { this.client = checkNotNull(client, "client"); this.virtualGuestPackageName = checkNotNull(virtualGuestPackageName, "virtualGuestPackageName"); + checkArgument(guestLoginDelay > 500, "guestOrderDelay must be in milliseconds and greater than 500"); + this.guestLoginDelay =guestLoginDelay; + + this.loginDetailsTester = new RetryablePredicate(virtualGuestHasLoginDetailsPresent, + guestLoginDelay); } @Override @@ -87,62 +87,31 @@ public class SoftLayerComputeServiceAdapter implements checkNotNull(template, "template was null"); checkNotNull(template.getOptions(), "template options was null"); checkArgument(template.getOptions().getClass().isAssignableFrom(SoftLayerTemplateOptions.class), - "options class %s should have been assignable from SoftLayerTemplateOptions", template.getOptions() - .getClass()); + "options class %s should have been assignable from SoftLayerTemplateOptions", template.getOptions() + .getClass()); - Iterable existing = findVirtualGuests(name,group); - if(!Iterables.isEmpty(existing)) { - throw new IllegalStateException( - "VirtualGuest(s) already exist with hostname:"+name+", group:"+group+". Existing:"+existing); - } + String domainName = template.getOptions().as(SoftLayerTemplateOptions.class).getDomainName(); - VirtualGuest newGuest = VirtualGuest.builder() - .domain(template.getOptions().as(SoftLayerTemplateOptions.class).getDomainName()) - .hostname(name) - .build(); + VirtualGuest newGuest = VirtualGuest.builder().domain(domainName).hostname(name).build(); - ProductOrder order = ProductOrder.builder() - .packageId(getProductPackage().getId()) - .location(template.getLocation().getId()) - .quantity(1) - .useHourlyPricing(true) - .prices(getPrices(template)) - .virtualGuest(newGuest) - .build(); + ProductOrder order = ProductOrder.builder().packageId(getProductPackage().getId()).location( + template.getLocation().getId()).quantity(1).useHourlyPricing(true).prices(getPrices(template)) + .virtualGuest(newGuest).build(); - client.getVirtualGuestClient().orderVirtualGuest(order); + ProductOrderReceipt productOrderReceipt = client.getVirtualGuestClient().orderVirtualGuest(order); + VirtualGuest result = Iterables.get(productOrderReceipt.getOrderDetails().getVirtualGuests(), 0); + boolean orderInSystem = loginDetailsTester.apply(result); - VirtualGuest result = Iterables.getOnlyElement(findVirtualGuests(name, group)); - Credentials credentials = new Credentials(null,null); + checkState(orderInSystem, "order for guest %s doesn't have login details within %sms", result, Long.toString(guestLoginDelay)); + result = client.getVirtualGuestClient().getVirtualGuest(result.getId()); - // This information is not always available. - OperatingSystem os = result.getOperatingSystem(); - if(os!=null) { - Set passwords = os.getPasswords(); - if(passwords.size()>0) { - Password pw = Iterables.get(passwords,0); - credentials = new Credentials(pw.getUsername(),pw.getPassword()); - } - } - credentialStore.put("node#"+result.getId(),credentials); + Password pw = Iterables.get(result.getOperatingSystem().getPasswords(),0); + Credentials credentials = new Credentials(pw.getUsername(), pw.getPassword()); + credentialStore.put("node#" + result.getId(), credentials); return result; } - private Iterable findVirtualGuests(String hostname,String domain) { - checkNotNull(hostname,"hostname"); - checkNotNull(domain,"domain"); - - Set result = Sets.newLinkedHashSet(); - - for( VirtualGuest guest : client.getVirtualGuestClient().listVirtualGuests()) { - if ( guest.getHostname().equals(hostname) && guest.getDomain().equals(domain)) { - result.add(guest); - } - } - - return result; - } private Iterable getPrices(Template template) { Set result = Sets.newLinkedHashSet(); @@ -151,7 +120,7 @@ public class SoftLayerComputeServiceAdapter implements result.add(ProductItemPrice.builder().id(imageId).build()); Iterable hardwareIds = Splitter.on(",").split(template.getHardware().getId()); - for(String hardwareId: hardwareIds) { + for (String hardwareId : hardwareIds) { int id = Integer.parseInt(hardwareId); result.add(ProductItemPrice.builder().id(id).build()); } @@ -161,32 +130,32 @@ public class SoftLayerComputeServiceAdapter implements return result; } - - @Override public Iterable> listHardwareProfiles() { ProductPackage productPackage = getProductPackage(); Set items = productPackage.getItems(); Iterable cpuItems = Iterables.filter(items, units("PRIVATE_CORE")); - Iterable ramItems = Iterables.filter(items,categoryCode("ram")); - Iterable sanItems = Iterables.filter(items, Predicates.and(matches(SAN_DESCRIPTION_REGEX),categoryCode("one_time_charge"))); + Iterable ramItems = Iterables.filter(items, categoryCode("ram")); + Iterable sanItems = Iterables.filter(items, Predicates.and(matches(SAN_DESCRIPTION_REGEX), + categoryCode("one_time_charge"))); Map cpuMap = Maps.uniqueIndex(cpuItems, ProductItems.capacity()); Map ramMap = Maps.uniqueIndex(ramItems, ProductItems.capacity()); Map sanMap = Maps.uniqueIndex(sanItems, ProductItems.capacity()); final ProductItem bootVolume = sanMap.get(BOOT_VOLUME_CAPACITY); - assert bootVolume!=null : "Boot volume capacity not found:"+BOOT_VOLUME_CAPACITY+", available:"+sanItems; + assert bootVolume != null : "Boot volume capacity not found:" + BOOT_VOLUME_CAPACITY + ", available:" + sanItems; Set> result = Sets.newLinkedHashSet(); - for(Map.Entry coresEntry : cpuMap.entrySet()) { + for (Map.Entry coresEntry : cpuMap.entrySet()) { Float cores = coresEntry.getKey(); ProductItem ramItem = ramMap.get(cores); - //Amount of RAM and number of cores must match. - if(ramItem==null) continue; + // Amount of RAM and number of cores must match. + if (ramItem == null) + continue; - result.add(ImmutableSet.of(coresEntry.getValue(),ramItem,bootVolume)); + result.add(ImmutableSet.of(coresEntry.getValue(), ramItem, bootVolume)); } return result; @@ -211,7 +180,7 @@ public class SoftLayerComputeServiceAdapter implements AccountClient accountClient = client.getAccountClient(); ProductPackageClient productPackageClient = client.getProductPackageClient(); - ProductPackage p = Iterables.find(accountClient.getActivePackages(),named(virtualGuestPackageName)); + ProductPackage p = Iterables.find(accountClient.getActivePackages(), named(virtualGuestPackageName)); return productPackageClient.getProductPackage(p.getId()); } @@ -224,12 +193,13 @@ public class SoftLayerComputeServiceAdapter implements @Override public void destroyNode(String id) { VirtualGuest guest = getNode(id); - if(guest==null) return; + if (guest == null) + return; - BillingItemVirtualGuest billingItem = guest.getBillingItem(); - if (billingItem==null) return; + if (guest.getBillingItemId() == -1) + return; - client.getVirtualGuestClient().cancelService(billingItem.getId()); + client.getVirtualGuestClient().cancelService(guest.getBillingItemId()); } @Override @@ -246,4 +216,25 @@ public class SoftLayerComputeServiceAdapter implements public void suspendNode(String id) { client.getVirtualGuestClient().pauseVirtualGuest(Long.parseLong(id)); } + + public static class VirtualGuestHasLoginDetailsPresent implements Predicate { + private final SoftLayerClient client; + + @Inject + public VirtualGuestHasLoginDetailsPresent(SoftLayerClient client) { + this.client = checkNotNull(client, "client was null"); + } + + @Override + public boolean apply(VirtualGuest guest) { + checkNotNull(guest, "virtual guest was null"); + + VirtualGuest newGuest = client.getVirtualGuestClient().getVirtualGuest(guest.getId()); + boolean hasBackendIp = newGuest.getPrimaryBackendIpAddress() != null; + boolean hasPrimaryIp = newGuest.getPrimaryIpAddress() != null; + boolean hasPasswords = newGuest.getOperatingSystem()!=null && newGuest.getOperatingSystem().getPasswords().size() > 0; + + return hasBackendIp && hasPrimaryIp && hasPasswords; + } + } } \ No newline at end of file diff --git a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/config/SoftLayerParserModule.java b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/config/SoftLayerParserModule.java new file mode 100644 index 0000000000..f13f2689ef --- /dev/null +++ b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/config/SoftLayerParserModule.java @@ -0,0 +1,114 @@ +/** + * 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.softlayer.config; + +import java.lang.reflect.Type; +import java.util.Date; +import java.util.Map; + +import javax.inject.Singleton; + +import org.jclouds.softlayer.domain.Datacenter; +import org.jclouds.softlayer.domain.OperatingSystem; +import org.jclouds.softlayer.domain.PowerState; +import org.jclouds.softlayer.domain.VirtualGuest; + +import com.google.common.collect.ImmutableMap; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import com.google.inject.AbstractModule; +import com.google.inject.TypeLiteral; + +/** + * + * @author Adrian Cole + */ +public class SoftLayerParserModule extends AbstractModule { + + @Singleton + public static class VirtualGuestAdapter implements JsonSerializer, JsonDeserializer { + + public JsonElement serialize(VirtualGuest src, Type typeOfSrc, JsonSerializationContext context) { + return context.serialize(src); + } + + public VirtualGuest deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + return apply(context. deserialize(json, VirtualGuestInternal.class)); + } + + public VirtualGuest apply(VirtualGuestInternal in) { + return in; + } + + /** + * Internal class that flattens billingItem into billingItemId + */ + public static class VirtualGuestInternal extends VirtualGuest { + private BillingItem billingItem; + + public VirtualGuestInternal(int accountId, Date createDate, boolean dedicatedAccountHostOnly, String domain, + String fullyQualifiedDomainName, String hostname, int id, Date lastVerifiedDate, int maxCpu, + String maxCpuUnits, int maxMemory, Date metricPollDate, Date modifyDate, String notes, + boolean privateNetworkOnly, int startCpus, int statusId, String uuid, String primaryBackendIpAddress, + String primaryIpAddress, int billingItemId, OperatingSystem operatingSystem, Datacenter datacenter, + PowerState powerState) { + super(accountId, createDate, dedicatedAccountHostOnly, domain, fullyQualifiedDomainName, hostname, id, + lastVerifiedDate, maxCpu, maxCpuUnits, maxMemory, metricPollDate, modifyDate, notes, + privateNetworkOnly, startCpus, statusId, uuid, primaryBackendIpAddress, primaryIpAddress, + billingItemId, operatingSystem, datacenter, powerState); + } + + @Override + public int getBillingItemId() { + return billingItem != null ? billingItem.id : -1; + } + } + + public static class BillingItem { + + private int id = -1; + + // for deserializer + BillingItem() { + + } + + public BillingItem(int id) { + this.id = id; + } + + @Override + public String toString() { + return "[id=" + id + "]"; + } + } + } + + @Override + protected void configure() { + bind(new TypeLiteral>() { + }).toInstance(ImmutableMap. of(VirtualGuest.class, new VirtualGuestAdapter())); + } + +} diff --git a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/config/SoftLayerRestClientModule.java b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/config/SoftLayerRestClientModule.java index 6133465f02..1b047bc05c 100644 --- a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/config/SoftLayerRestClientModule.java +++ b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/config/SoftLayerRestClientModule.java @@ -18,8 +18,7 @@ */ package org.jclouds.softlayer.config; -import java.util.Map; - +import com.google.common.collect.ImmutableMap; import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.RequiresHttp; @@ -33,17 +32,10 @@ import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.config.RestClientModule; import org.jclouds.softlayer.SoftLayerAsyncClient; import org.jclouds.softlayer.SoftLayerClient; -import org.jclouds.softlayer.features.AccountAsyncClient; -import org.jclouds.softlayer.features.AccountClient; -import org.jclouds.softlayer.features.DatacenterAsyncClient; -import org.jclouds.softlayer.features.DatacenterClient; -import org.jclouds.softlayer.features.ProductPackageAsyncClient; -import org.jclouds.softlayer.features.ProductPackageClient; -import org.jclouds.softlayer.features.VirtualGuestAsyncClient; -import org.jclouds.softlayer.features.VirtualGuestClient; +import org.jclouds.softlayer.features.*; import org.jclouds.softlayer.handlers.SoftLayerErrorHandler; -import com.google.common.collect.ImmutableMap; +import java.util.Map; /** * Configures the SoftLayer connection. diff --git a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/BillingItemVirtualGuest.java b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/BillingItemVirtualGuest.java deleted file mode 100644 index 42f47817fe..0000000000 --- a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/BillingItemVirtualGuest.java +++ /dev/null @@ -1,101 +0,0 @@ -/** - * 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.softlayer.domain; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Strings.emptyToNull; - -/** - * - * @author Jason King - * @see - */ -public class BillingItemVirtualGuest implements Comparable { - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - private int id = -1; - - public Builder id(int id) { - this.id = id; - return this; - } - - public static Builder fromBillingItemVirtualGuest(BillingItemVirtualGuest in) { - return BillingItemVirtualGuest.builder().id(in.getId()); - } - } - - private int id = -1; - - // for deserializer - BillingItemVirtualGuest() { - - } - - public BillingItemVirtualGuest(int id) { - this.id = id; - } - - @Override - public int compareTo(BillingItemVirtualGuest arg0) { - return new Integer(id).compareTo(arg0.getId()); - } - - /** - * @return The unique identifier for this billing item. - */ - public int getId() { - return id; - } - - public Builder toBuilder() { - return Builder.fromBillingItemVirtualGuest(this); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (id ^ (id >>> 32)); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - BillingItemVirtualGuest other = (BillingItemVirtualGuest) obj; - if (id != other.id) - return false; - return true; - } - - @Override - public String toString() { - return "[id=" + id + "]"; - } -} diff --git a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/OperatingSystem.java b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/OperatingSystem.java index 053c740e36..0b10bee531 100644 --- a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/OperatingSystem.java +++ b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/OperatingSystem.java @@ -132,6 +132,6 @@ public class OperatingSystem implements Comparable { @Override public String toString() { - return "OperatingSystem [id=" + id + ", passwords=" + passwords + "]"; + return "[id=" + id + ", passwords=" + passwords + "]"; } } diff --git a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/PowerState.java b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/PowerState.java new file mode 100644 index 0000000000..8a80a1da50 --- /dev/null +++ b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/PowerState.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.softlayer.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * The power state class provides a common set of values for which a guest's power state will be presented in the SoftLayer API. + * @author Jason King + * @see + */ +public class PowerState implements Comparable { + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private VirtualGuest.State keyName; + + public Builder keyName(VirtualGuest.State keyName) { + this.keyName = keyName; + return this; + } + + public PowerState build() { + return new PowerState(keyName); + } + + public static Builder fromAddress(PowerState in) { + return PowerState.builder().keyName(in.getKeyName()); + } + } + + private VirtualGuest.State keyName; + + // for deserializer + PowerState() { + + } + + public PowerState(VirtualGuest.State keyName) { + this.keyName = checkNotNull(keyName,"keyName cannot be null or empty:"+keyName); + } + + @Override + public int compareTo(PowerState arg0) { + return keyName.compareTo(arg0.keyName); + } + + /** + * Maps onto {@code VirtualGuest.State} + * @return The key name of a power state. + * + */ + public VirtualGuest.State getKeyName() { + return keyName; + } + + public Builder toBuilder() { + return Builder.fromAddress(this); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + PowerState that = (PowerState) o; + if (keyName != null ? !keyName.equals(that.keyName) : that.keyName != null) + return false; + + return true; + } + + @Override + public int hashCode() { + return keyName != null ? keyName.hashCode() : 0; + } + + @Override + public String toString() { + return "[keyName=" + keyName + "]"; + } + + +} diff --git a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/ProductOrderReceipt.java b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/ProductOrderReceipt.java index ff89d1fbea..64b3456ee2 100644 --- a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/ProductOrderReceipt.java +++ b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/ProductOrderReceipt.java @@ -31,30 +31,38 @@ public class ProductOrderReceipt implements Comparable { public static class Builder { private int orderId = -1; + private ProductOrder orderDetails; public Builder orderId(int orderId) { this.orderId = orderId; return this; } + public Builder orderDetails(ProductOrder orderDetails) { + this.orderDetails = orderDetails; + return this; + } + public ProductOrderReceipt build() { - return new ProductOrderReceipt(orderId); + return new ProductOrderReceipt(orderId,orderDetails); } public static Builder fromAddress(ProductOrderReceipt in) { - return ProductOrderReceipt.builder().orderId(in.getOrderId()); + return ProductOrderReceipt.builder().orderId(in.getOrderId()).orderDetails(in.getOrderDetails()); } } private int orderId = -1; + private ProductOrder orderDetails; // for deserializer ProductOrderReceipt() { } - public ProductOrderReceipt(int orderId) { + public ProductOrderReceipt(int orderId,ProductOrder orderDetails) { this.orderId = orderId; + this.orderDetails = orderDetails; } @Override @@ -69,6 +77,16 @@ public class ProductOrderReceipt implements Comparable { return orderId; } + /** + * This is a copy of the SoftLayer_Container_Product_Order + * which holds all the data related to an order. + * This will only return when an order is processed successfully. + * It will contain all the items in an order as well as the order totals. + */ + public ProductOrder getOrderDetails() { + return orderDetails; + } + public Builder toBuilder() { return Builder.fromAddress(this); } @@ -97,7 +115,7 @@ public class ProductOrderReceipt implements Comparable { @Override public String toString() { - return "[orderId=" + orderId + "]"; + return "[orderId=" + orderId + ", orderDetails="+orderDetails+"]"; } diff --git a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/VirtualGuest.java b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/VirtualGuest.java index e1a1f2711f..f44233f64b 100644 --- a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/VirtualGuest.java +++ b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/domain/VirtualGuest.java @@ -18,12 +18,12 @@ */ package org.jclouds.softlayer.domain; -import static com.google.common.base.Preconditions.checkNotNull; +import com.google.common.base.CaseFormat; +import com.google.gson.annotations.SerializedName; import java.util.Date; -import com.google.common.base.CaseFormat; -import com.google.gson.annotations.SerializedName; +import static com.google.common.base.Preconditions.checkNotNull; /** * The virtual guest data type presents the structure in which all virtual guests will be presented. @@ -74,8 +74,10 @@ public class VirtualGuest implements Comparable { private String uuid; private String primaryBackendIpAddress; private String primaryIpAddress; - private BillingItemVirtualGuest billingItem; + private int billingItemId; private OperatingSystem operatingSystem; + private Datacenter datacenter; + private PowerState powerState; public Builder id(int id) { this.id = id; @@ -177,8 +179,8 @@ public class VirtualGuest implements Comparable { return this; } - public Builder billingItem(BillingItemVirtualGuest billingItem) { - this.billingItem = billingItem; + public Builder billingItemId(int billingItemId) { + this.billingItemId = billingItemId; return this; } @@ -187,12 +189,22 @@ public class VirtualGuest implements Comparable { return this; } + public Builder datacenter(Datacenter datacenter) { + this.datacenter = datacenter; + return this; + } + + public Builder powerState(PowerState powerState) { + this.powerState = powerState; + return this; + } + public VirtualGuest build() { return new VirtualGuest(accountId, createDate, dedicatedAccountHostOnly, domain, fullyQualifiedDomainName, hostname, id, lastVerifiedDate, maxCpu, maxCpuUnits, maxMemory, metricPollDate, modifyDate, notes, privateNetworkOnly, startCpus, statusId, uuid, primaryBackendIpAddress, - primaryIpAddress,billingItem,operatingSystem); + primaryIpAddress, billingItemId,operatingSystem,datacenter,powerState); } public static Builder fromVirtualGuest(VirtualGuest in) { @@ -217,9 +229,10 @@ public class VirtualGuest implements Comparable { .uuid(in.getUuid()) .primaryBackendIpAddress(in.getPrimaryBackendIpAddress()) .primaryIpAddress(in.getPrimaryIpAddress()) - .billingItem(in.getBillingItem()) - .operatingSystem(in.getOperatingSystem()); - + .billingItemId(in.getBillingItemId()) + .operatingSystem(in.getOperatingSystem()) + .datacenter(in.getDatacenter()) + .powerState(in.getPowerState()); } } @@ -270,9 +283,11 @@ public class VirtualGuest implements Comparable { private String primaryBackendIpAddress; private String primaryIpAddress; - private BillingItemVirtualGuest billingItem; + private int billingItemId = -1; private OperatingSystem operatingSystem; - + private Datacenter datacenter; + private PowerState powerState; + // for deserializer VirtualGuest() { @@ -282,7 +297,7 @@ public class VirtualGuest implements Comparable { String fullyQualifiedDomainName, String hostname, int id, Date lastVerifiedDate, int maxCpu, String maxCpuUnits, int maxMemory, Date metricPollDate, Date modifyDate, String notes, boolean privateNetworkOnly, int startCpus, int statusId, String uuid, String primaryBackendIpAddress, - String primaryIpAddress,BillingItemVirtualGuest billingItem, OperatingSystem operatingSystem) { + String primaryIpAddress,int billingItemId, OperatingSystem operatingSystem, Datacenter datacenter, PowerState powerState) { this.accountId = accountId; this.createDate = createDate; this.dedicatedAccountHostOnly = dedicatedAccountHostOnly; @@ -303,8 +318,10 @@ public class VirtualGuest implements Comparable { this.uuid = uuid; this.primaryBackendIpAddress = primaryBackendIpAddress; this.primaryIpAddress = primaryIpAddress; - this.billingItem = billingItem; + this.billingItemId = billingItemId; this.operatingSystem = operatingSystem; + this.datacenter = datacenter; + this.powerState = powerState; } @Override @@ -458,8 +475,8 @@ public class VirtualGuest implements Comparable { /** * @return The billing item for a CloudLayer Compute Instance. */ - public BillingItemVirtualGuest getBillingItem() { - return billingItem; + public int getBillingItemId() { + return billingItemId; } /** @@ -469,6 +486,21 @@ public class VirtualGuest implements Comparable { return operatingSystem; } + /** + * @return The guest's datacenter + */ + public Datacenter getDatacenter() { + return datacenter; + } + + /** + * @return The current power state of a virtual guest. + */ + public PowerState getPowerState() { + return powerState; + } + + @Override public int hashCode() { final int prime = 31; @@ -493,8 +525,10 @@ public class VirtualGuest implements Comparable { result = prime * result + startCpus; result = prime * result + statusId; result = prime * result + ((uuid == null) ? 0 : uuid.hashCode()); - result = prime * result + ((billingItem == null) ? 0 : billingItem.hashCode()); + result = prime * result + (getBillingItemId() ^ (getBillingItemId() >>> 32)); result = prime * result + ((operatingSystem == null) ? 0 : operatingSystem.hashCode()); + result = prime * result + ((datacenter == null) ? 0 : datacenter.hashCode()); + result = prime * result + ((powerState == null) ? 0 : powerState.hashCode()); return result; } @@ -583,16 +617,23 @@ public class VirtualGuest implements Comparable { return false; } else if (!uuid.equals(other.uuid)) return false; - if (billingItem == null) { - if (other.billingItem != null) - return false; - } else if (!billingItem.equals(other.billingItem)) + if (getBillingItemId() != other.getBillingItemId()) return false; if (operatingSystem == null) { if (other.operatingSystem != null) return false; } else if (!operatingSystem.equals(other.operatingSystem)) return false; + if (datacenter == null) { + if (other.datacenter != null) + return false; + } else if (!datacenter.equals(other.datacenter)) + return false; + if (powerState == null) { + if (other.powerState != null) + return false; + } else if (!powerState.equals(other.powerState)) + return false; return true; } @@ -605,7 +646,8 @@ public class VirtualGuest implements Comparable { + ", metricPollDate=" + metricPollDate + ", modifyDate=" + modifyDate + ", notes=" + notes + ", primaryBackendIpAddress=" + primaryBackendIpAddress + ", primaryIpAddress=" + primaryIpAddress + ", privateNetworkOnly=" + privateNetworkOnly + ", startCpus=" + startCpus + ", statusId=" + statusId - + ", uuid=" + uuid + ", billingItem="+billingItem+", operatingSystem="+operatingSystem+"]"; + + ", uuid=" + uuid + ", billingItemId="+getBillingItemId()+", operatingSystem="+operatingSystem+", datacenter="+datacenter + + ", powerState="+powerState+"]"; } } diff --git a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/reference/SoftLayerConstants.java b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/reference/SoftLayerConstants.java index a90115643a..13c1f6bdd0 100644 --- a/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/reference/SoftLayerConstants.java +++ b/sandbox-providers/softlayer/src/main/java/org/jclouds/softlayer/reference/SoftLayerConstants.java @@ -33,6 +33,12 @@ public interface SoftLayerConstants { * Name of the product package corresponding to cloud servers */ public static final String PROPERTY_SOFTLAYER_VIRTUALGUEST_PACKAGE_NAME = "jclouds.softlayer.virtualguest.package-name"; + + + /** + * number of milliseconds to wait for an order to arrive on the api. + */ + public static final String PROPERTY_SOFTLAYER_VIRTUALGUEST_LOGIN_DETAILS_DELAY = "jclouds.softlayer.virtualguest.order-delay"; public static final Set DEFAULT_VIRTUAL_GUEST_PRICES = ImmutableSet.builder() .add(ProductItemPrice.builder().id(1639).build()) // 100 GB (SAN) diff --git a/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/compute/SoftLayerComputeServiceAdapterLiveTest.java b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/compute/SoftLayerComputeServiceAdapterLiveTest.java index ccc6f0fca6..04f4382d1d 100644 --- a/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/compute/SoftLayerComputeServiceAdapterLiveTest.java +++ b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/compute/SoftLayerComputeServiceAdapterLiveTest.java @@ -24,6 +24,7 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import java.util.Map; +import java.util.Random; import java.util.Set; import org.jclouds.compute.domain.ExecResponse; @@ -55,7 +56,8 @@ public class SoftLayerComputeServiceAdapterLiveTest extends BaseSoftLayerClientL public void setupClient() { super.setupClient(); adapter = new SoftLayerComputeServiceAdapter(context.getApi(), - ProductPackageClientLiveTest.CLOUD_SERVER_PACKAGE_NAME); + ProductPackageClientLiveTest.CLOUD_SERVER_PACKAGE_NAME, + new SoftLayerComputeServiceAdapter.VirtualGuestHasLoginDetailsPresent(context.getApi()),60*60*1000); } @Test @@ -66,7 +68,7 @@ public class SoftLayerComputeServiceAdapterLiveTest extends BaseSoftLayerClientL @Test public void testCreateNodeWithGroupEncodedIntoNameThenStoreCredentials() { String group = "foo"; - String name = "foo-ef4"; + String name = "node"+new Random().nextInt(); Template template = computeContext.getComputeService().templateBuilder() .locationId("3") // the default (singapore) doesn't work. .build(); @@ -87,7 +89,7 @@ public class SoftLayerComputeServiceAdapterLiveTest extends BaseSoftLayerClientL protected void doConnectViaSsh(VirtualGuest guest, Credentials creds) { SshClient ssh = computeContext.utils().sshFactory() - .create(new IPSocket(guest.getPrimaryBackendIpAddress(), 22), creds); + .create(new IPSocket(guest.getPrimaryIpAddress(), 22), creds); try { ssh.connect(); ExecResponse hello = ssh.exec("echo hello"); diff --git a/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/compute/SoftLayerComputeServiceLiveTest.java b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/compute/SoftLayerComputeServiceLiveTest.java new file mode 100644 index 0000000000..ae78a965a8 --- /dev/null +++ b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/compute/SoftLayerComputeServiceLiveTest.java @@ -0,0 +1,89 @@ +/** + * 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.softlayer.compute; + +import com.google.inject.Module; +import org.jclouds.compute.BaseComputeServiceLiveTest; +import org.jclouds.compute.ComputeServiceContextFactory; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.domain.LocationScope; +import org.jclouds.rest.RestContext; +import org.jclouds.softlayer.SoftLayerAsyncClient; +import org.jclouds.softlayer.SoftLayerClient; +import org.jclouds.sshj.config.SshjSshClientModule; +import org.testng.annotations.Test; + +import java.io.IOException; + +import static org.testng.Assert.assertEquals; + +/** + * + * Generally disabled, as it incurs higher fees. + * + * @author Adrian Cole + */ +@Test(groups = "live", enabled = true, sequential = true) +public class SoftLayerComputeServiceLiveTest extends BaseComputeServiceLiveTest { + public SoftLayerComputeServiceLiveTest() { + provider = "softlayer"; + } + + @Override + protected Module getSshModule() { + return new SshjSshClientModule(); + } + + public void testAssignability() throws Exception { + @SuppressWarnings("unused") + RestContext tmContext = new ComputeServiceContextFactory() + .createContext(provider, identity, credential).getProviderSpecificContext(); + } + + @Override + protected void checkNodes(Iterable nodes, String tag) throws IOException { + super.checkNodes(nodes, tag); + for (NodeMetadata node : nodes) { + assertEquals(node.getLocation().getScope(), LocationScope.HOST); + } + } + + @Test(enabled = true, dependsOnMethods = "testReboot", expectedExceptions = UnsupportedOperationException.class) + public void testSuspendResume() throws Exception { + super.testSuspendResume(); + } + + @Test(enabled = true, dependsOnMethods = "testSuspendResume") + @Override + public void testGetNodesWithDetails() throws Exception { + super.testGetNodesWithDetails(); + } + + @Test(enabled = true, dependsOnMethods = "testSuspendResume") + @Override + public void testListNodes() throws Exception { + super.testListNodes(); + } + + @Test(enabled = true, dependsOnMethods = { "testListNodes", "testGetNodesWithDetails" }) + @Override + public void testDestroyNodes() { + super.testDestroyNodes(); + } +} diff --git a/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/compute/SoftLayerExperimentLiveTest.java b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/compute/SoftLayerExperimentLiveTest.java index 26257ef066..3d2c50df4b 100644 --- a/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/compute/SoftLayerExperimentLiveTest.java +++ b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/compute/SoftLayerExperimentLiveTest.java @@ -20,9 +20,14 @@ package org.jclouds.softlayer.compute; import static com.google.common.base.Preconditions.checkNotNull; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import com.google.common.collect.Iterables; import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContextFactory; +import org.jclouds.compute.RunNodesException; +import org.jclouds.compute.domain.NodeMetadata; +import org.jclouds.compute.domain.Template; import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.sshj.config.SshjSshClientModule; import org.testng.annotations.BeforeClass; @@ -31,6 +36,8 @@ import org.testng.annotations.Test; import com.google.common.collect.ImmutableSet; import com.google.inject.Module; +import java.util.Set; + /** * * @author Adrian Cole @@ -69,4 +76,29 @@ public class SoftLayerExperimentLiveTest { } } + @Test + public void testCreateAndDestoryNode() throws RunNodesException { + ComputeServiceContext context = null; + try { + String identity = checkNotNull(System.getProperty("test.softlayer.identity"), "test.softlayer.identity"); + String credential = checkNotNull(System.getProperty("test.softlayer.credential"), "test.softlayer.credential"); + + context = new ComputeServiceContextFactory().createContext("softlayer", identity, credential, ImmutableSet + . of(new Log4JLoggingModule(), new SshjSshClientModule())); + + Template template = context.getComputeService().templateBuilder() + .locationId("3") // the default (singapore) doesn't work. + .build(); + + Set nodes = context.getComputeService().createNodesInGroup("computeservice",1,template); + assertTrue(nodes.size() == 1); + NodeMetadata data = Iterables.get(nodes,0); + context.getComputeService().destroyNode(data.getId()); + + } finally { + if (context != null) + context.close(); + } + } + } \ No newline at end of file diff --git a/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/compute/functions/DatacenterToLocationTest.java b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/compute/functions/DatacenterToLocationTest.java index 520e3aaf2e..6bb8e8761e 100644 --- a/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/compute/functions/DatacenterToLocationTest.java +++ b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/compute/functions/DatacenterToLocationTest.java @@ -28,7 +28,6 @@ import org.jclouds.domain.Location; import org.jclouds.location.suppliers.JustProvider; import org.jclouds.softlayer.domain.Address; import org.jclouds.softlayer.domain.Datacenter; -import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import com.google.common.collect.ImmutableSet; @@ -41,24 +40,14 @@ import com.google.common.collect.ImmutableSet; @Test(singleThreaded = true, groups = "unit") public class DatacenterToLocationTest { - private DatacenterToLocation function; - - @BeforeMethod - public void setup() { - function = new DatacenterToLocation(new JustProvider(ImmutableSet.of(), "softlayer", URI.create("foo"))); - } + static DatacenterToLocation function = new DatacenterToLocation(new JustProvider(ImmutableSet. of(), "softlayer", + URI.create("foo")));; @Test public void testDatacenterToLocation() { - Address address = Address.builder().country("US") - .state("TX") - .description("This is Texas!") - .build(); + Address address = Address.builder().country("US").state("TX").description("This is Texas!").build(); - Datacenter datacenter = Datacenter.builder().id(1) - .longName("Texas Datacenter") - .locationAddress(address) - .build(); + Datacenter datacenter = Datacenter.builder().id(1).longName("Texas Datacenter").locationAddress(address).build(); Location location = function.apply(datacenter); @@ -70,9 +59,7 @@ public class DatacenterToLocationTest { @Test public void testGetIso3166CodeNoCountryAndState() { - Datacenter datacenter = Datacenter.builder().id(1) - .longName("Nowhere") - .build(); + Datacenter datacenter = Datacenter.builder().id(1).longName("Nowhere").build(); Location location = function.apply(datacenter); @@ -83,14 +70,9 @@ public class DatacenterToLocationTest { @Test public void testGetIso3166CodeCountryOnly() { - Address address = Address.builder().country("US") - .description("This is North America!") - .build(); + Address address = Address.builder().country("US").description("This is North America!").build(); - Datacenter datacenter = Datacenter.builder().id(1) - .longName("Nowhere") - .locationAddress(address) - .build(); + Datacenter datacenter = Datacenter.builder().id(1).longName("Nowhere").locationAddress(address).build(); Location location = function.apply(datacenter); @@ -102,15 +84,10 @@ public class DatacenterToLocationTest { @Test public void testGetIso3166CodeWhitespaceTrimmer() { - Address address = Address.builder().country(" US ") - .state(" TX ") - .description("This is spaced out Texas") - .build(); + Address address = Address.builder().country(" US ").state(" TX ").description("This is spaced out Texas") + .build(); - Datacenter datacenter = Datacenter.builder().id(1) - .longName("Nowhere") - .locationAddress(address) - .build(); + Datacenter datacenter = Datacenter.builder().id(1).longName("Nowhere").locationAddress(address).build(); Location location = function.apply(datacenter); diff --git a/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/compute/functions/VirtualGuestToNodeMetadataTest.java b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/compute/functions/VirtualGuestToNodeMetadataTest.java new file mode 100644 index 0000000000..ac743db46d --- /dev/null +++ b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/compute/functions/VirtualGuestToNodeMetadataTest.java @@ -0,0 +1,196 @@ +/** + * 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.softlayer.compute.functions; + +import static org.testng.Assert.assertEquals; + +import java.net.UnknownHostException; +import java.util.Map; +import java.util.Set; + +import com.google.common.collect.Iterables; +import org.jclouds.compute.domain.*; +import org.jclouds.domain.Credentials; +import org.jclouds.domain.Location; +import org.jclouds.softlayer.compute.functions.VirtualGuestToNodeMetadata.FindLocationForVirtualGuest; +import org.jclouds.softlayer.domain.Password; +import org.jclouds.softlayer.domain.VirtualGuest; +import org.jclouds.softlayer.parse.*; +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.ImmutableSet; + +/** + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "VirtualGuestToNodeMetadataTest") +public class VirtualGuestToNodeMetadataTest { + + @Test + public void testApplyWhereVirtualGuestWithNoPassword() throws UnknownHostException { + + // notice if we've already parsed this properly here, we can rely on it. + VirtualGuest guest = new ParseVirtualGuestWithNoPasswordTest().expected(); + + // note we are testing when no credentials are here. otherwise would be ("node#416696", new + // Credentials("root", "password")) + Map credentialStore = ImmutableMap. of(); + + // setup so that we have an expected Location to be parsed from the guest. + Location expectedLocation = DatacenterToLocationTest.function.apply(guest.getDatacenter()); + Supplier> locationSupplier = Suppliers.> ofInstance(ImmutableSet + . of(expectedLocation)); + + VirtualGuestToNodeMetadata parser = new VirtualGuestToNodeMetadata(credentialStore, + new FindLocationForVirtualGuest(locationSupplier)); + + NodeMetadata node = parser.apply(guest); + + assertEquals(node, new NodeMetadataBuilder().ids("416788").name("node1000360500").location( + expectedLocation).state(NodeState.PENDING).publicAddresses(ImmutableSet.of("173.192.29.186")) + .privateAddresses(ImmutableSet.of("10.37.102.194")) + .hardware(new HardwareBuilder().id("TODO").processor(new Processor(1,2.0)).ram(1042).build()) + .build()); + + // because it wasn't present in the credential store. + assertEquals(node.getCredentials(), null); + } + + @Test + public void testApplyWhereVirtualIsBad() throws UnknownHostException { + + // notice if we've already parsed this properly here, we can rely on it. + VirtualGuest guest = new ParseBadVirtualGuest().expected(); + + // note we are testing when no credentials are here. otherwise would be ("node#416696", new + // Credentials("root", "password")) + Map credentialStore = ImmutableMap. of(); + + // no location here + Supplier> locationSupplier = Suppliers.> ofInstance(ImmutableSet + . of()); + + VirtualGuestToNodeMetadata parser = new VirtualGuestToNodeMetadata(credentialStore, + new FindLocationForVirtualGuest(locationSupplier)); + + NodeMetadata node = parser.apply(guest); + + assertEquals(node, new NodeMetadataBuilder().ids("413348") + .name("foo-ef4").group("foo") + .state(NodeState.PENDING) + .hardware(new HardwareBuilder().id("TODO").ram(256).build()) + .build()); + + // because it wasn't present in the credential store. + assertEquals(node.getCredentials(), null); + } + + @Test + public void testApplyWhereVirtualGuestIsHalted() throws UnknownHostException { + + // notice if we've already parsed this properly here, we can rely on it. + VirtualGuest guest = new ParseVirtualGuestHaltedTest().expected(); + + Password password = Iterables.get(guest.getOperatingSystem().getPasswords(), 0); + Credentials credentials = new Credentials(password.getUsername(),password.getPassword()); + Map credentialStore = ImmutableMap. of("node#416700",credentials); + + // setup so that we have an expected Location to be parsed from the guest. + Location expectedLocation = DatacenterToLocationTest.function.apply(guest.getDatacenter()); + Supplier> locationSupplier = Suppliers.> ofInstance(ImmutableSet + . of(expectedLocation)); + + VirtualGuestToNodeMetadata parser = new VirtualGuestToNodeMetadata(credentialStore, + new FindLocationForVirtualGuest(locationSupplier)); + + NodeMetadata node = parser.apply(guest); + + assertEquals(node, new NodeMetadataBuilder().ids("416700").name("node1703810489").location( + expectedLocation).state(NodeState.PENDING).credentials(credentials) + .publicAddresses(ImmutableSet.of("173.192.29.187")).privateAddresses(ImmutableSet.of("10.37.102.195")) + .hardware(new HardwareBuilder().id("TODO").processor(new Processor(1,2.0)).ram(1042).build()) + .build()); + + // because it wasn't present in the credential store. + assertEquals(node.getCredentials(), credentials); + } + + @Test + public void testApplyWhereVirtualGuestIsPaused() throws UnknownHostException { + + // notice if we've already parsed this properly here, we can rely on it. + VirtualGuest guest = new ParseVirtualGuestPausedTest().expected(); + + Password password = Iterables.get(guest.getOperatingSystem().getPasswords(),0); + Credentials credentials = new Credentials(password.getUsername(),password.getPassword()); + Map credentialStore = ImmutableMap. of("node#416700",credentials); + + // setup so that we have an expected Location to be parsed from the guest. + Location expectedLocation = DatacenterToLocationTest.function.apply(guest.getDatacenter()); + Supplier> locationSupplier = Suppliers.> ofInstance(ImmutableSet + . of(expectedLocation)); + + VirtualGuestToNodeMetadata parser = new VirtualGuestToNodeMetadata(credentialStore, + new FindLocationForVirtualGuest(locationSupplier)); + + NodeMetadata node = parser.apply(guest); + + assertEquals(node, new NodeMetadataBuilder().ids("416700").name("node1703810489").location( + expectedLocation).state(NodeState.SUSPENDED).credentials(credentials) + .publicAddresses(ImmutableSet.of("173.192.29.187")).privateAddresses(ImmutableSet.of("10.37.102.195")) + .hardware(new HardwareBuilder().id("TODO").processor(new Processor(1,2.0)).ram(1042).build()) + .build()); + + // because it wasn't present in the credential store. + assertEquals(node.getCredentials(), credentials); + } + + @Test + public void testApplyWhereVirtualGuestIsRunning() throws UnknownHostException { + + // notice if we've already parsed this properly here, we can rely on it. + VirtualGuest guest = new ParseVirtualGuestRunningTest().expected(); + + Password password = Iterables.get(guest.getOperatingSystem().getPasswords(),0); + Credentials credentials = new Credentials(password.getUsername(),password.getPassword()); + Map credentialStore = ImmutableMap. of("node#416700",credentials); + + // setup so that we have an expected Location to be parsed from the guest. + Location expectedLocation = DatacenterToLocationTest.function.apply(guest.getDatacenter()); + Supplier> locationSupplier = Suppliers.> ofInstance(ImmutableSet + . of(expectedLocation)); + + VirtualGuestToNodeMetadata parser = new VirtualGuestToNodeMetadata(credentialStore, + new FindLocationForVirtualGuest(locationSupplier)); + + NodeMetadata node = parser.apply(guest); + + assertEquals(node, new NodeMetadataBuilder().ids("416700").name("node1703810489").location( + expectedLocation).state(NodeState.RUNNING).credentials(credentials) + .publicAddresses(ImmutableSet.of("173.192.29.187")).privateAddresses(ImmutableSet.of("10.37.102.195")) + .hardware(new HardwareBuilder().id("TODO").processor(new Processor(1,2.0)).ram(1042).build()) + .build()); + + // because it wasn't present in the credential store. + assertEquals(node.getCredentials(), credentials); + } +} diff --git a/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/features/VirtualGuestClientLiveTest.java b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/features/VirtualGuestClientLiveTest.java index d8f3444567..575ceeb1e2 100644 --- a/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/features/VirtualGuestClientLiveTest.java +++ b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/features/VirtualGuestClientLiveTest.java @@ -73,9 +73,8 @@ public class VirtualGuestClientLiveTest extends BaseSoftLayerClientLiveTest { // objectMask: virtualGuests.activeTransaction for( VirtualGuest guest: client.listVirtualGuests()) { if (guest.getHostname().startsWith(TEST_HOSTNAME_PREFIX)) { - BillingItemVirtualGuest billingItem = guest.getBillingItem(); - if(billingItem!=null) { - client.cancelService(billingItem.getId()); + if(guest.getBillingItemId()!=-1) { + client.cancelService(guest.getBillingItemId()); } } } @@ -125,8 +124,7 @@ public class VirtualGuestClientLiveTest extends BaseSoftLayerClientLiveTest { private void checkVirtualGuest(VirtualGuest vg) { - if (vg.getBillingItem()==null) return;//Quotes and shutting down guests - checkBillingItem(vg.getBillingItem()); + if (vg.getBillingItemId()==-1) return;//Quotes and shutting down guests assert vg.getAccountId() > 0 : vg; assert vg.getCreateDate() != null : vg; @@ -146,9 +144,4 @@ public class VirtualGuestClientLiveTest extends BaseSoftLayerClientLiveTest { assert vg.getPrimaryIpAddress() != null : vg; } - private void checkBillingItem(BillingItemVirtualGuest billingItem) { - assert null != billingItem; - assert billingItem.getId() > 0 : billingItem; - } - } diff --git a/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/parse/ParseBadVirtualGuest.java b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/parse/ParseBadVirtualGuest.java new file mode 100644 index 0000000000..8cea0180bd --- /dev/null +++ b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/parse/ParseBadVirtualGuest.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.softlayer.parse; + +import com.google.inject.Guice; +import com.google.inject.Injector; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.json.BaseItemParserTest; +import org.jclouds.json.config.GsonModule; +import org.jclouds.softlayer.config.SoftLayerParserModule; +import org.jclouds.softlayer.domain.PowerState; +import org.jclouds.softlayer.domain.VirtualGuest; +import org.testng.annotations.Test; + +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "ParseVirtualGuestWithNoPasswordTest") +public class ParseBadVirtualGuest extends BaseItemParserTest { + + @Override + public String resource() { + return "/virtual_guest_bad_halted.json"; + } + + @Override + @Consumes(MediaType.APPLICATION_JSON) + public VirtualGuest expected() { + return VirtualGuest + .builder() + .id(413348).accountId(93750).billingItemId(-1) + .createDate(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-09-28T01:52:45-08:00")) + .domain("jclouds.org").fullyQualifiedDomainName("foo-ef4.jclouds.org") + .hostname("foo-ef4").maxCpu(0).maxCpuUnits("CORE").maxMemory(256) + .statusId(1001).startCpus(0) + //TODO: maybe powerState can be flattened like billingItemId + .powerState(new PowerState(VirtualGuest.State.HALTED)).build(); + } + + protected Injector injector() { + return Guice.createInjector(new SoftLayerParserModule(), new GsonModule() { + + @Override + protected void configure() { + bind(DateAdapter.class).to(Iso8601DateAdapter.class); + super.configure(); + } + + }); + } + +} diff --git a/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/parse/ParseVirtualGuestHaltedTest.java b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/parse/ParseVirtualGuestHaltedTest.java new file mode 100644 index 0000000000..fb82296ea4 --- /dev/null +++ b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/parse/ParseVirtualGuestHaltedTest.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.softlayer.parse; + +import com.google.inject.Guice; +import com.google.inject.Injector; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.json.BaseItemParserTest; +import org.jclouds.json.config.GsonModule; +import org.jclouds.softlayer.config.SoftLayerParserModule; +import org.jclouds.softlayer.domain.*; +import org.testng.annotations.Test; + +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "ParseVirtualGuestWithNoPasswordTest") +public class ParseVirtualGuestHaltedTest extends BaseItemParserTest { + + @Override + public String resource() { + return "/virtual_guest_good_halted.json"; + } + + @Override + @Consumes(MediaType.APPLICATION_JSON) + public VirtualGuest expected() { + return VirtualGuest + .builder() + .id(416700).accountId(93750).billingItemId(7184019) + .createDate(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-10-01T11:47:35-08:00")) + .metricPollDate(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-10-02T02:32:00-08:00")) + .dedicatedAccountHostOnly(true).domain("me.org").fullyQualifiedDomainName("node1703810489.me.org") + .hostname("node1703810489").maxCpu(1).maxCpuUnits("CORE").maxMemory(1024) + .modifyDate(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-10-02T03:19:43-08:00")) + .primaryBackendIpAddress("10.37.102.195").primaryIpAddress("173.192.29.187").startCpus(1).statusId(1001) + .uuid("02ddbbba-9225-3d54-6de5-fc603b309dd8") + .operatingSystem(OperatingSystem.builder().id(913824) + .password(Password.builder().id(729122).username("root").password("KnJqhC2l").build()) + .build()) + .datacenter(Datacenter.builder().id(3).name("dal01").longName("Dallas").build()) + //TODO: maybe powerState can be flattened like billingItemId + .powerState(new PowerState(VirtualGuest.State.HALTED)).build(); + } + + protected Injector injector() { + return Guice.createInjector(new SoftLayerParserModule(), new GsonModule() { + + @Override + protected void configure() { + bind(DateAdapter.class).to(Iso8601DateAdapter.class); + super.configure(); + } + + }); + } + +} diff --git a/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/parse/ParseVirtualGuestPausedTest.java b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/parse/ParseVirtualGuestPausedTest.java new file mode 100644 index 0000000000..14f0e97fde --- /dev/null +++ b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/parse/ParseVirtualGuestPausedTest.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.softlayer.parse; + +import com.google.inject.Guice; +import com.google.inject.Injector; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.json.BaseItemParserTest; +import org.jclouds.json.config.GsonModule; +import org.jclouds.softlayer.config.SoftLayerParserModule; +import org.jclouds.softlayer.domain.*; +import org.testng.annotations.Test; + +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "ParseVirtualGuestWithNoPasswordTest") +public class ParseVirtualGuestPausedTest extends BaseItemParserTest { + + @Override + public String resource() { + return "/virtual_guest_paused.json"; + } + + @Override + @Consumes(MediaType.APPLICATION_JSON) + public VirtualGuest expected() { + return VirtualGuest + .builder() + .id(416700).accountId(93750).billingItemId(7184019) + .createDate(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-10-01T11:47:35-08:00")) + .metricPollDate(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-10-02T02:32:00-08:00")) + .dedicatedAccountHostOnly(true).domain("me.org").fullyQualifiedDomainName("node1703810489.me.org") + .hostname("node1703810489").maxCpu(1).maxCpuUnits("CORE").maxMemory(1024) + .modifyDate(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-10-02T03:18:12-08:00")) + .primaryBackendIpAddress("10.37.102.195").primaryIpAddress("173.192.29.187").startCpus(1).statusId(1001) + .uuid("02ddbbba-9225-3d54-6de5-fc603b309dd8") + .operatingSystem(OperatingSystem.builder().id(913824) + .password(Password.builder().id(729122).username("root").password("KnJqhC2l").build()) + .build()) + .datacenter(Datacenter.builder().id(3).name("dal01").longName("Dallas").build()) + //TODO: maybe powerState can be flattened like billingItemId + .powerState(new PowerState(VirtualGuest.State.PAUSED)).build(); + } + + protected Injector injector() { + return Guice.createInjector(new SoftLayerParserModule(), new GsonModule() { + + @Override + protected void configure() { + bind(DateAdapter.class).to(Iso8601DateAdapter.class); + super.configure(); + } + + }); + } + +} diff --git a/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/parse/ParseVirtualGuestRunningTest.java b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/parse/ParseVirtualGuestRunningTest.java new file mode 100644 index 0000000000..753a9b018e --- /dev/null +++ b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/parse/ParseVirtualGuestRunningTest.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.softlayer.parse; + +import com.google.inject.Guice; +import com.google.inject.Injector; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.json.BaseItemParserTest; +import org.jclouds.json.config.GsonModule; +import org.jclouds.softlayer.config.SoftLayerParserModule; +import org.jclouds.softlayer.domain.*; +import org.testng.annotations.Test; + +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "ParseVirtualGuestWithNoPasswordTest") +public class ParseVirtualGuestRunningTest extends BaseItemParserTest { + + @Override + public String resource() { + return "/virtual_guest_running.json"; + } + + @Override + @Consumes(MediaType.APPLICATION_JSON) + public VirtualGuest expected() { + return VirtualGuest + .builder() + .id(416700).accountId(93750).billingItemId(7184019) + .createDate(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-10-01T11:47:35-08:00")) + .metricPollDate(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-10-02T02:32:00-08:00")) + .dedicatedAccountHostOnly(true).domain("me.org").fullyQualifiedDomainName("node1703810489.me.org") + .hostname("node1703810489").maxCpu(1).maxCpuUnits("CORE").maxMemory(1024) + .modifyDate(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-10-02T02:32:40-08:00")) + .primaryBackendIpAddress("10.37.102.195").primaryIpAddress("173.192.29.187").startCpus(1).statusId(1001) + .uuid("02ddbbba-9225-3d54-6de5-fc603b309dd8") + .operatingSystem(OperatingSystem.builder().id(913824) + .password(Password.builder().id(729122).username("root").password("KnJqhC2l").build()) + .build()) + .datacenter(Datacenter.builder().id(3).name("dal01").longName("Dallas").build()) + //TODO: maybe powerState can be flattened like billingItemId + .powerState(new PowerState(VirtualGuest.State.RUNNING)).build(); + } + + protected Injector injector() { + return Guice.createInjector(new SoftLayerParserModule(), new GsonModule() { + + @Override + protected void configure() { + bind(DateAdapter.class).to(Iso8601DateAdapter.class); + super.configure(); + } + + }); + } + +} diff --git a/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/parse/ParseVirtualGuestWithNoPasswordTest.java b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/parse/ParseVirtualGuestWithNoPasswordTest.java new file mode 100644 index 0000000000..216f8b648b --- /dev/null +++ b/sandbox-providers/softlayer/src/test/java/org/jclouds/softlayer/parse/ParseVirtualGuestWithNoPasswordTest.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.softlayer.parse; + +import com.google.inject.Guice; +import com.google.inject.Injector; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.json.BaseItemParserTest; +import org.jclouds.json.config.GsonModule; +import org.jclouds.softlayer.config.SoftLayerParserModule; +import org.jclouds.softlayer.domain.Datacenter; +import org.jclouds.softlayer.domain.OperatingSystem; +import org.jclouds.softlayer.domain.PowerState; +import org.jclouds.softlayer.domain.VirtualGuest; +import org.testng.annotations.Test; + +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; + +/** + * + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "ParseVirtualGuestWithNoPasswordTest") +public class ParseVirtualGuestWithNoPasswordTest extends BaseItemParserTest { + + @Override + public String resource() { + return "/virtual_guest_no_password.json"; + } + + @Override + @Consumes(MediaType.APPLICATION_JSON) + public VirtualGuest expected() { + return VirtualGuest + .builder() + .id(416788).accountId(93750).billingItemId(7185261) + .createDate(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-10-02T03:24:43-08:00")) + .dedicatedAccountHostOnly(true).domain("me.org").fullyQualifiedDomainName("node1000360500.me.org") + .hostname("node1000360500").maxCpu(1).maxCpuUnits("CORE").maxMemory(1024) + .modifyDate(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-10-02T03:25:33-08:00")) + .primaryBackendIpAddress("10.37.102.194").primaryIpAddress("173.192.29.186").startCpus(1).statusId(1001) + .uuid("96fe22ad-8182-924d-ce51-a037e477dd83") + .operatingSystem(OperatingSystem.builder().id(913960).build()) + .datacenter(Datacenter.builder().id(3).name("dal01").longName("Dallas").build()) + //TODO: maybe powerState can be flattened like billingItemId + .powerState(new PowerState(VirtualGuest.State.HALTED)).build(); + } + + protected Injector injector() { + return Guice.createInjector(new SoftLayerParserModule(), new GsonModule() { + + @Override + protected void configure() { + bind(DateAdapter.class).to(Iso8601DateAdapter.class); + super.configure(); + } + + }); + } + +} diff --git a/sandbox-providers/softlayer/src/test/resources/virtual_guest_bad_halted.json b/sandbox-providers/softlayer/src/test/resources/virtual_guest_bad_halted.json new file mode 100644 index 0000000000..923d4e7d56 --- /dev/null +++ b/sandbox-providers/softlayer/src/test/resources/virtual_guest_bad_halted.json @@ -0,0 +1,4 @@ +{"accountId":93750,"createDate":"2011-09-28T01:52:45-08:00","dedicatedAccountHostOnlyFlag":false,"domain":"jclouds.org","fullyQualifiedDomainName":"foo-ef4.jclouds.org","hostname":"foo-ef4","id":413348,"lastVerifiedDate":null,"maxCpu":null,"maxCpuUnits":"CORE","maxMemory":256,"metricPollDate":null,"modifyDate":null,"privateNetworkOnlyFlag":false,"startCpus":null,"statusId":1001,"globalIdentifier":"9a8b20f0-a758-4c1f-b65b-0e63b791009f","managedResourceFlag":false,"networkVlans":[],"powerState":{ + "keyName":"HALTED", + "name":"Halted" +}} diff --git a/sandbox-providers/softlayer/src/test/resources/virtual_guest_good_halted.json b/sandbox-providers/softlayer/src/test/resources/virtual_guest_good_halted.json new file mode 100644 index 0000000000..2311387011 --- /dev/null +++ b/sandbox-providers/softlayer/src/test/resources/virtual_guest_good_halted.json @@ -0,0 +1,117 @@ +{"accountId":93750,"createDate":"2011-10-01T11:47:35-08:00","dedicatedAccountHostOnlyFlag":true,"domain":"me.org","fullyQualifiedDomainName":"node1703810489.me.org","hostname":"node1703810489","id":416700,"lastVerifiedDate":null,"maxCpu":1,"maxCpuUnits":"CORE","maxMemory":1024,"metricPollDate":"2011-10-02T02:32:00-08:00","modifyDate":"2011-10-02T03:19:43-08:00","privateNetworkOnlyFlag":false,"startCpus":1,"statusId":1001,"uuid":"02ddbbba-9225-3d54-6de5-fc603b309dd8","billingItem":{ + "cancellationDate":null, + "categoryCode":"guest_core", + "createDate":"2011-10-01T11:48:10-08:00", + "currentHourlyCharge":"0", + "cycleStartDate":"2011-10-01T11:58:26-08:00", + "description":"Private 1 x 2.0 GHz Core", + "domainName":"me.org", + "hostName":"node1703810489", + "hourlyRecurringFee":"0", + "hoursUsed":"16", + "id":7184019, + "laborFee":"0", + "laborFeeTaxRate":"0", + "lastBillDate":"2011-10-01T11:58:26-08:00", + "modifyDate":"2011-10-01T11:58:26-08:00", + "nextBillDate":"2011-10-17T21:00:00-08:00", + "oneTimeFee":"0", + "oneTimeFeeTaxRate":"0", + "orderItemId":8021579, + "parentId":null, + "recurringFee":"0", + "recurringFeeTaxRate":"0", + "recurringMonths":1, + "serviceProviderId":1, + "setupFee":"0", + "setupFeeTaxRate":"0", + "resourceTableId":416700 +},"datacenter":{ + "id":3, + "longName":"Dallas", + "name":"dal01" +},"globalIdentifier":"0ea2db7f-800d-479a-88e0-8e276e500b80","managedResourceFlag":false,"networkVlans":[ + { + "accountId":93750, + "id":144615, + "modifyDate":"2011-09-30T11:35:27-08:00", + "networkVrfId":null, + "primarySubnetId":171267, + "vlanNumber":1673 + }, + { + "accountId":93750, + "id":144616, + "modifyDate":"2011-09-30T11:35:30-08:00", + "networkVrfId":null, + "primarySubnetId":329652, + "vlanNumber":1622 + } +],"operatingSystem":{ + "hardwareId":null, + "id":913824, + "manufacturerLicenseInstance":"", + "passwords":[ + { + "createDate":"2011-10-01T11:48:52-08:00", + "id":729122, + "modifyDate":"2011-10-01T11:48:52-08:00", + "password":"KnJqhC2l", + "port":null, + "softwareId":913824, + "username":"root", + "software":{ + "hardwareId":null, + "id":913824, + "manufacturerLicenseInstance":"", + "passwords":[ + { + "createDate":"2011-10-01T11:48:52-08:00", + "id":729122, + "modifyDate":"2011-10-01T11:48:52-08:00", + "password":"KnJqhC2l", + "port":null, + "softwareId":913824, + "username":"root", + "software":null + } + ], + "softwareLicense":{ + "id":427, + "softwareDescriptionId":408, + "softwareDescription":{ + "controlPanel":0, + "id":408, + "manufacturer":"Ubuntu", + "name":"Ubuntu ", + "operatingSystem":1, + "requiredUser":"root", + "upgradeSwDescId":null, + "version":"8.04-64 Minimal for CCI", + "virtualLicense":0, + "virtualizationPlatform":0 + } + } + } + } + ], + "softwareLicense":{ + "id":427, + "softwareDescriptionId":408, + "softwareDescription":{ + "controlPanel":0, + "id":408, + "manufacturer":"Ubuntu", + "name":"Ubuntu ", + "operatingSystem":1, + "requiredUser":"root", + "upgradeSwDescId":null, + "version":"8.04-64 Minimal for CCI", + "virtualLicense":0, + "virtualizationPlatform":0 + } + } +},"powerState":{ + "keyName":"HALTED", + "name":"Halted" +},"primaryBackendIpAddress":"10.37.102.195","primaryIpAddress":"173.192.29.187"} diff --git a/sandbox-providers/softlayer/src/test/resources/virtual_guest_no_password.json b/sandbox-providers/softlayer/src/test/resources/virtual_guest_no_password.json new file mode 100644 index 0000000000..d4c234173a --- /dev/null +++ b/sandbox-providers/softlayer/src/test/resources/virtual_guest_no_password.json @@ -0,0 +1,74 @@ +{"accountId":93750,"createDate":"2011-10-02T03:24:43-08:00","dedicatedAccountHostOnlyFlag":true,"domain":"me.org","fullyQualifiedDomainName":"node1000360500.me.org","hostname":"node1000360500","id":416788,"lastVerifiedDate":null,"maxCpu":1,"maxCpuUnits":"CORE","maxMemory":1024,"metricPollDate":null,"modifyDate":"2011-10-02T03:25:33-08:00","privateNetworkOnlyFlag":false,"startCpus":1,"statusId":1001,"uuid":"96fe22ad-8182-924d-ce51-a037e477dd83","billingItem":{ + "cancellationDate":null, + "categoryCode":"guest_core", + "createDate":"2011-10-02T03:25:12-08:00", + "currentHourlyCharge":"0", + "cycleStartDate":"2011-10-02T03:25:12-08:00", + "description":"Private 1 x 2.0 GHz Core", + "domainName":"me.org", + "hostName":"node1000360500", + "hourlyRecurringFee":"0", + "hoursUsed":"1", + "id":7185261, + "laborFee":"0", + "laborFeeTaxRate":"0", + "lastBillDate":"2011-10-02T03:25:12-08:00", + "modifyDate":"2011-10-02T03:25:51-08:00", + "nextBillDate":"2011-10-17T21:00:00-08:00", + "oneTimeFee":"0", + "oneTimeFeeTaxRate":"0", + "orderItemId":8023216, + "parentId":null, + "recurringFee":"0", + "recurringFeeTaxRate":"0", + "recurringMonths":1, + "serviceProviderId":1, + "setupFee":"0", + "setupFeeTaxRate":"0", + "resourceTableId":416788 +},"datacenter":{ + "id":3, + "longName":"Dallas", + "name":"dal01" +},"globalIdentifier":"0a07b4fc-2b3c-4053-9220-55992de14d21","managedResourceFlag":false,"networkVlans":[ + { + "accountId":93750, + "id":144615, + "modifyDate":"2011-09-30T11:35:27-08:00", + "networkVrfId":null, + "primarySubnetId":171267, + "vlanNumber":1673 + }, + { + "accountId":93750, + "id":144616, + "modifyDate":"2011-09-30T11:35:30-08:00", + "networkVrfId":null, + "primarySubnetId":329652, + "vlanNumber":1622 + } +],"operatingSystem":{ + "hardwareId":null, + "id":913960, + "manufacturerLicenseInstance":"", + "passwords":[], + "softwareLicense":{ + "id":427, + "softwareDescriptionId":408, + "softwareDescription":{ + "controlPanel":0, + "id":408, + "manufacturer":"Ubuntu", + "name":"Ubuntu ", + "operatingSystem":1, + "requiredUser":"root", + "upgradeSwDescId":null, + "version":"8.04-64 Minimal for CCI", + "virtualLicense":0, + "virtualizationPlatform":0 + } + } +},"powerState":{ + "keyName":"HALTED", + "name":"Halted" +},"primaryBackendIpAddress":"10.37.102.194","primaryIpAddress":"173.192.29.186"} diff --git a/sandbox-providers/softlayer/src/test/resources/virtual_guest_paused.json b/sandbox-providers/softlayer/src/test/resources/virtual_guest_paused.json new file mode 100644 index 0000000000..15d1667194 --- /dev/null +++ b/sandbox-providers/softlayer/src/test/resources/virtual_guest_paused.json @@ -0,0 +1,117 @@ +{"accountId":93750,"createDate":"2011-10-01T11:47:35-08:00","dedicatedAccountHostOnlyFlag":true,"domain":"me.org","fullyQualifiedDomainName":"node1703810489.me.org","hostname":"node1703810489","id":416700,"lastVerifiedDate":null,"maxCpu":1,"maxCpuUnits":"CORE","maxMemory":1024,"metricPollDate":"2011-10-02T02:32:00-08:00","modifyDate":"2011-10-02T03:18:12-08:00","privateNetworkOnlyFlag":false,"startCpus":1,"statusId":1001,"uuid":"02ddbbba-9225-3d54-6de5-fc603b309dd8","billingItem":{ + "cancellationDate":null, + "categoryCode":"guest_core", + "createDate":"2011-10-01T11:48:10-08:00", + "currentHourlyCharge":"0", + "cycleStartDate":"2011-10-01T11:58:26-08:00", + "description":"Private 1 x 2.0 GHz Core", + "domainName":"me.org", + "hostName":"node1703810489", + "hourlyRecurringFee":"0", + "hoursUsed":"16", + "id":7184019, + "laborFee":"0", + "laborFeeTaxRate":"0", + "lastBillDate":"2011-10-01T11:58:26-08:00", + "modifyDate":"2011-10-01T11:58:26-08:00", + "nextBillDate":"2011-10-17T21:00:00-08:00", + "oneTimeFee":"0", + "oneTimeFeeTaxRate":"0", + "orderItemId":8021579, + "parentId":null, + "recurringFee":"0", + "recurringFeeTaxRate":"0", + "recurringMonths":1, + "serviceProviderId":1, + "setupFee":"0", + "setupFeeTaxRate":"0", + "resourceTableId":416700 +},"datacenter":{ + "id":3, + "longName":"Dallas", + "name":"dal01" +},"globalIdentifier":"0ea2db7f-800d-479a-88e0-8e276e500b80","managedResourceFlag":false,"networkVlans":[ + { + "accountId":93750, + "id":144615, + "modifyDate":"2011-09-30T11:35:27-08:00", + "networkVrfId":null, + "primarySubnetId":171267, + "vlanNumber":1673 + }, + { + "accountId":93750, + "id":144616, + "modifyDate":"2011-09-30T11:35:30-08:00", + "networkVrfId":null, + "primarySubnetId":329652, + "vlanNumber":1622 + } +],"operatingSystem":{ + "hardwareId":null, + "id":913824, + "manufacturerLicenseInstance":"", + "passwords":[ + { + "createDate":"2011-10-01T11:48:52-08:00", + "id":729122, + "modifyDate":"2011-10-01T11:48:52-08:00", + "password":"KnJqhC2l", + "port":null, + "softwareId":913824, + "username":"root", + "software":{ + "hardwareId":null, + "id":913824, + "manufacturerLicenseInstance":"", + "passwords":[ + { + "createDate":"2011-10-01T11:48:52-08:00", + "id":729122, + "modifyDate":"2011-10-01T11:48:52-08:00", + "password":"KnJqhC2l", + "port":null, + "softwareId":913824, + "username":"root", + "software":null + } + ], + "softwareLicense":{ + "id":427, + "softwareDescriptionId":408, + "softwareDescription":{ + "controlPanel":0, + "id":408, + "manufacturer":"Ubuntu", + "name":"Ubuntu ", + "operatingSystem":1, + "requiredUser":"root", + "upgradeSwDescId":null, + "version":"8.04-64 Minimal for CCI", + "virtualLicense":0, + "virtualizationPlatform":0 + } + } + } + } + ], + "softwareLicense":{ + "id":427, + "softwareDescriptionId":408, + "softwareDescription":{ + "controlPanel":0, + "id":408, + "manufacturer":"Ubuntu", + "name":"Ubuntu ", + "operatingSystem":1, + "requiredUser":"root", + "upgradeSwDescId":null, + "version":"8.04-64 Minimal for CCI", + "virtualLicense":0, + "virtualizationPlatform":0 + } + } +},"powerState":{ + "keyName":"PAUSED", + "name":"Paused" +},"primaryBackendIpAddress":"10.37.102.195","primaryIpAddress":"173.192.29.187"} diff --git a/sandbox-providers/softlayer/src/test/resources/virtual_guest_running.json b/sandbox-providers/softlayer/src/test/resources/virtual_guest_running.json new file mode 100644 index 0000000000..39731bc3c9 --- /dev/null +++ b/sandbox-providers/softlayer/src/test/resources/virtual_guest_running.json @@ -0,0 +1,117 @@ +{"accountId":93750,"createDate":"2011-10-01T11:47:35-08:00","dedicatedAccountHostOnlyFlag":true,"domain":"me.org","fullyQualifiedDomainName":"node1703810489.me.org","hostname":"node1703810489","id":416700,"lastVerifiedDate":null,"maxCpu":1,"maxCpuUnits":"CORE","maxMemory":1024,"metricPollDate":"2011-10-02T02:32:00-08:00","modifyDate":"2011-10-02T02:32:40-08:00","privateNetworkOnlyFlag":false,"startCpus":1,"statusId":1001,"uuid":"02ddbbba-9225-3d54-6de5-fc603b309dd8","billingItem":{ + "cancellationDate":null, + "categoryCode":"guest_core", + "createDate":"2011-10-01T11:48:10-08:00", + "currentHourlyCharge":"0", + "cycleStartDate":"2011-10-01T11:58:26-08:00", + "description":"Private 1 x 2.0 GHz Core", + "domainName":"me.org", + "hostName":"node1703810489", + "hourlyRecurringFee":"0", + "hoursUsed":"16", + "id":7184019, + "laborFee":"0", + "laborFeeTaxRate":"0", + "lastBillDate":"2011-10-01T11:58:26-08:00", + "modifyDate":"2011-10-01T11:58:26-08:00", + "nextBillDate":"2011-10-17T21:00:00-08:00", + "oneTimeFee":"0", + "oneTimeFeeTaxRate":"0", + "orderItemId":8021579, + "parentId":null, + "recurringFee":"0", + "recurringFeeTaxRate":"0", + "recurringMonths":1, + "serviceProviderId":1, + "setupFee":"0", + "setupFeeTaxRate":"0", + "resourceTableId":416700 +},"datacenter":{ + "id":3, + "longName":"Dallas", + "name":"dal01" +},"globalIdentifier":"0ea2db7f-800d-479a-88e0-8e276e500b80","managedResourceFlag":false,"networkVlans":[ + { + "accountId":93750, + "id":144615, + "modifyDate":"2011-09-30T11:35:27-08:00", + "networkVrfId":null, + "primarySubnetId":171267, + "vlanNumber":1673 + }, + { + "accountId":93750, + "id":144616, + "modifyDate":"2011-09-30T11:35:30-08:00", + "networkVrfId":null, + "primarySubnetId":329652, + "vlanNumber":1622 + } +],"operatingSystem":{ + "hardwareId":null, + "id":913824, + "manufacturerLicenseInstance":"", + "passwords":[ + { + "createDate":"2011-10-01T11:48:52-08:00", + "id":729122, + "modifyDate":"2011-10-01T11:48:52-08:00", + "password":"KnJqhC2l", + "port":null, + "softwareId":913824, + "username":"root", + "software":{ + "hardwareId":null, + "id":913824, + "manufacturerLicenseInstance":"", + "passwords":[ + { + "createDate":"2011-10-01T11:48:52-08:00", + "id":729122, + "modifyDate":"2011-10-01T11:48:52-08:00", + "password":"KnJqhC2l", + "port":null, + "softwareId":913824, + "username":"root", + "software":null + } + ], + "softwareLicense":{ + "id":427, + "softwareDescriptionId":408, + "softwareDescription":{ + "controlPanel":0, + "id":408, + "manufacturer":"Ubuntu", + "name":"Ubuntu ", + "operatingSystem":1, + "requiredUser":"root", + "upgradeSwDescId":null, + "version":"8.04-64 Minimal for CCI", + "virtualLicense":0, + "virtualizationPlatform":0 + } + } + } + } + ], + "softwareLicense":{ + "id":427, + "softwareDescriptionId":408, + "softwareDescription":{ + "controlPanel":0, + "id":408, + "manufacturer":"Ubuntu", + "name":"Ubuntu ", + "operatingSystem":1, + "requiredUser":"root", + "upgradeSwDescId":null, + "version":"8.04-64 Minimal for CCI", + "virtualLicense":0, + "virtualizationPlatform":0 + } + } +},"powerState":{ + "keyName":"RUNNING", + "name":"Running" +},"primaryBackendIpAddress":"10.37.102.195","primaryIpAddress":"173.192.29.187"}