added vm feature to savvis

This commit is contained in:
Adrian Cole 2011-03-23 17:50:57 -07:00
parent 26a3a2f9de
commit 208fb69af4
25 changed files with 1036 additions and 97 deletions

View File

@ -56,6 +56,8 @@
<test.savvis-symphonyvpdc.apiversion>0.8</test.savvis-symphonyvpdc.apiversion>
<test.savvis-symphonyvpdc.identity>FIXME</test.savvis-symphonyvpdc.identity>
<test.savvis-symphonyvpdc.credential>FIXME</test.savvis-symphonyvpdc.credential>
<test.savvis-symphonyvpdc.loginUser>FIXME</test.savvis-symphonyvpdc.loginUser>
<test.savvis-symphonyvpdc.loginPassword>FIXME</test.savvis-symphonyvpdc.loginPassword>
</properties>
<dependencies>
<dependency>
@ -100,6 +102,11 @@
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jamesmurty.utils</groupId>
<artifactId>java-xmlbuilder</artifactId>
<version>0.3</version>
</dependency>
</dependencies>
<profiles>
<profile>
@ -134,6 +141,14 @@
<name>test.savvis-symphonyvpdc.credential</name>
<value>${test.savvis-symphonyvpdc.credential}</value>
</property>
<property>
<name>test.savvis-symphonyvpdc.loginUser</name>
<value>${test.savvis-symphonyvpdc.loginUser}</value>
</property>
<property>
<name>test.savvis-symphonyvpdc.loginPassword</name>
<value>${test.savvis-symphonyvpdc.loginPassword}</value>
</property>
<property>
<name>jclouds.compute.blacklist-nodes</name>
<value>${jclouds.compute.blacklist-nodes}</value>

View File

@ -25,6 +25,7 @@ import org.jclouds.compute.domain.CIMOperatingSystem;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.savvis.vpdc.domain.Resource;
import org.jclouds.savvis.vpdc.features.BrowsingAsyncClient;
import org.jclouds.savvis.vpdc.features.VMAsyncClient;
import org.jclouds.savvis.vpdc.internal.Org;
import com.google.inject.Provides;
@ -45,6 +46,12 @@ public interface VPDCAsyncClient {
@Delegate
BrowsingAsyncClient getBrowsingClient();
/**
* Provides asynchronous access to VM Operation features.
*/
@Delegate
VMAsyncClient getVMClient();
/**
*
* @return a listing of all orgs that the current user has access to.
@ -54,8 +61,8 @@ public interface VPDCAsyncClient {
Set<Resource> listOrgs();
/**
* predefined by default in the classpath resource {@code
* /savvis-symphonyvpdc/predefined_operatingsystems.json}
* predefined by default in the classpath resource
* {@code /savvis-symphonyvpdc/predefined_operatingsystems.json}
*
* @return the operating systems that are predefined in the provider
* @see <a href="https://api.sandbox.symphonyvpdc.savvis.net/doc/spec/api/addSingleVM.html" />

View File

@ -27,6 +27,7 @@ import org.jclouds.concurrent.Timeout;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.savvis.vpdc.domain.Resource;
import org.jclouds.savvis.vpdc.features.BrowsingClient;
import org.jclouds.savvis.vpdc.features.VMClient;
/**
* Provides synchronous access to VPDC.
@ -45,6 +46,12 @@ public interface VPDCClient {
@Delegate
BrowsingClient getBrowsingClient();
/**
* Provides synchronous access to VM Operation features.
*/
@Delegate
VMClient getVMClient();
/**
*
* @return a listing of all orgs that the current user has access to.
@ -52,8 +59,8 @@ public interface VPDCClient {
Set<Resource> listOrgs();
/**
* predefined by default in the classpath resource {@code
* /savvis-symphonyvpdc/predefined_operatingsystems.json}
* predefined by default in the classpath resource
* {@code /savvis-symphonyvpdc/predefined_operatingsystems.json}
*
* @return the operating systems that are predefined in the provider
* @see <a href="https://api.sandbox.symphonyvpdc.savvis.net/doc/spec/api/addSingleVM.html" />

View File

@ -0,0 +1,201 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.savvis.vpdc.binders;
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 java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import javax.inject.Singleton;
import javax.ws.rs.core.MediaType;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import org.jclouds.cim.ResourceAllocationSettingData.ResourceType;
import org.jclouds.compute.domain.CIMOperatingSystem;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.MapBinder;
import org.jclouds.rest.binders.BindToStringPayload;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.savvis.vpdc.domain.VMSpec;
import com.jamesmurty.utils.XMLBuilder;
/**
*
* @author Adrian Cole
*
*/
@Singleton
public class BindVMSpecToXmlPayload extends BindToStringPayload implements MapBinder {
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object toBind) {
throw new IllegalStateException("BindVMSpecToXmlPayload needs parameters");
}
protected VMSpec findSpecInArgsOrNull(GeneratedHttpRequest<?> gRequest) {
for (Object arg : gRequest.getArgs()) {
if (arg instanceof VMSpec) {
return (VMSpec) arg;
} else if (arg instanceof VMSpec[]) {
VMSpec[] configuration = (VMSpec[]) arg;
return (configuration.length > 0) ? configuration[0] : null;
}
}
return null;
}
@Override
public <R extends HttpRequest> R bindToRequest(R request, Map<String, String> postParams) {
checkArgument(checkNotNull(request, "request") instanceof GeneratedHttpRequest<?>,
"this binder is only valid for GeneratedHttpRequests!");
GeneratedHttpRequest<?> gRequest = (GeneratedHttpRequest<?>) request;
checkState(gRequest.getArgs() != null, "args should be initialized at this point");
request = super.bindToRequest(request,
generateXml(findSpecInArgsOrNull(gRequest), postParams.get("name"), postParams.get("networkName")));
request.getPayload().getContentMetadata().setContentType(MediaType.APPLICATION_XML);
return request;
}
public String generateXml(VMSpec spec, String name, String networkName) {
checkNotNull(spec, "VMSpec");
checkNotNull(name, "name");
checkNotNull(networkName, "networkName");
try {
XMLBuilder rootBuilder = buildRootForName(name);
addOperatingSystemSection(rootBuilder, spec.getOperatingSystem());
addVirtualHardwareSection(rootBuilder, name, networkName, spec);
Properties outputProperties = new Properties();
outputProperties.put(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes");
return rootBuilder.asString(outputProperties);
} catch (Exception e) {
return null;
}
}
void addVirtualHardwareSection(XMLBuilder rootBuilder, String name, String networkName, VMSpec spec) {
XMLBuilder virtualHardwareSectionBuilder = rootBuilder.e("ovf:VirtualHardwareSection");
virtualHardwareSectionBuilder.e("ovf:Info").t("Virtual Hardware");
addSystem(virtualHardwareSectionBuilder, name);
addItems(virtualHardwareSectionBuilder, spec, networkName);
}
void addItems(XMLBuilder virtualHardwareSectionBuilder, VMSpec spec, String networkName) {
//todo make this work with fractional, which I think means setting speed to half
addCPU(virtualHardwareSectionBuilder, (int)spec.getProcessorCount());
addMemory(virtualHardwareSectionBuilder, spec.getMemoryInGig());
addNetwork(virtualHardwareSectionBuilder, networkName);
addDisks(virtualHardwareSectionBuilder, spec);
}
private void addSystem(XMLBuilder virtualHardwareSectionBuilder, String name) {
XMLBuilder systemBuilder = virtualHardwareSectionBuilder.e("ovf:System");
systemBuilder.e("vssd:Description").t("Virtual Hardware Family");
systemBuilder.e("vssd:ElementName").t(name);
systemBuilder.e("vssd:InstanceID").t("1");
systemBuilder.e("vssd:VirtualSystemIdentifier").t(name);
}
private void addOperatingSystemSection(XMLBuilder rootBuilder, CIMOperatingSystem operatingSystem) {
XMLBuilder sectionBuilder = rootBuilder.e("ovf:OperatingSystemSection").a("ovf:id",
operatingSystem.getOsType().getCode() + "");
sectionBuilder.e("ovf:Info").t("Specifies the operating system installed");
sectionBuilder.e("ovf:Description").t(operatingSystem.getDescription());
}
private void addCPU(XMLBuilder sectionBuilder, int processorCount) {
XMLBuilder cpuBuilder = sectionBuilder.e("ovf:Item");
cpuBuilder.e("rasd:AllocationUnits").t("3 GHz");
cpuBuilder.e("rasd:Description").t("Number of Virtual CPUs");
cpuBuilder.e("rasd:ElementName").t(processorCount + " CPU");
cpuBuilder.e("rasd:InstanceID").t("1");
cpuBuilder.e("rasd:ResourceType").t(ResourceType.PROCESSOR.value());
cpuBuilder.e("rasd:VirtualQuantity").t(processorCount + "");
}
private void addMemory(XMLBuilder sectionBuilder, int memoryInGig) {
XMLBuilder memoryBuilder = sectionBuilder.e("ovf:Item");
memoryBuilder.e("rasd:AllocationUnits").t("Gigabytes");
memoryBuilder.e("rasd:Description").t("Memory Size");
memoryBuilder.e("rasd:ElementName").t("Memory");
memoryBuilder.e("rasd:InstanceID").t("2");
memoryBuilder.e("rasd:ResourceType").t(ResourceType.MEMORY.value());
memoryBuilder.e("rasd:VirtualQuantity").t(memoryInGig + "");
}
private void addNetwork(XMLBuilder sectionBuilder, String networkName) {
XMLBuilder networkBuilder = sectionBuilder.e("ovf:Item");
networkBuilder.e("rasd:Caption").t("false");
networkBuilder.e("rasd:Connection").t(networkName);
networkBuilder.e("rasd:ElementName").t("Network");
networkBuilder.e("rasd:InstanceID").t("3");
networkBuilder.e("rasd:ResourceType").t(ResourceType.ETHERNET_ADAPTER.value());
networkBuilder.e("rasd:VirtualQuantity").t("1");
}
private void addDisks(XMLBuilder sectionBuilder, VMSpec spec) {
XMLBuilder bootDiskBuilder = sectionBuilder.e("ovf:Item");
bootDiskBuilder.e("rasd:AllocationUnits").t("Gigabytes");
bootDiskBuilder.e("rasd:Caption").t("");
bootDiskBuilder.e("rasd:Description").t("Hard Disk");
bootDiskBuilder.e("rasd:ElementName").t(spec.getBootDeviceName());
bootDiskBuilder.e("rasd:HostResource").t("boot");
bootDiskBuilder.e("rasd:InstanceID").t("4");
bootDiskBuilder.e("rasd:ResourceType").t(ResourceType.BASE_PARTITIONABLE_UNIT.value());
bootDiskBuilder.e("rasd:VirtualQuantity").t(spec.getBootDiskSize() + "");
int instanceId = 5;
for (Entry<String, Integer> dataDisk : spec.getDataDiskDeviceNameToSizeInGig().entrySet()) {
XMLBuilder dataDiskBuilder = sectionBuilder.e("ovf:Item");
dataDiskBuilder.e("rasd:AllocationUnits").t("Gigabytes");
dataDiskBuilder.e("rasd:Caption").t("");
dataDiskBuilder.e("rasd:Description").t("Hard Disk");
dataDiskBuilder.e("rasd:ElementName").t(dataDisk.getKey());
dataDiskBuilder.e("rasd:HostResource").t("data");
dataDiskBuilder.e("rasd:InstanceID").t("" + instanceId++);
dataDiskBuilder.e("rasd:ResourceType").t(ResourceType.PARTITIONABLE_UNIT.value());
dataDiskBuilder.e("rasd:VirtualQuantity").t(dataDisk.getValue() + "");
}
}
protected XMLBuilder buildRootForName(String name) throws ParserConfigurationException, FactoryConfigurationError {
XMLBuilder rootBuilder = XMLBuilder.create("vApp:VApp")
.a("xmlns:common", "http://schemas.dmtf.org/wbem/wscim/1/common")
.a("xmlns:vApp", "http://www.vmware.com/vcloud/v0.8")
.a("xmlns:rasd", "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData")
.a("xmlns:vssd", "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData")
.a("xmlns:ovf", "http://schemas.dmtf.org/ovf/envelope/1").a("name", name)
.a("type", "application/vnd.vmware.vcloud.vApp+xml").a("href", "");
return rootBuilder;
}
protected String ifNullDefaultTo(String value, String defaultValue) {
return value != null ? value : checkNotNull(defaultValue, "defaultValue");
}
}

View File

@ -25,7 +25,7 @@ import javax.inject.Singleton;
import org.jclouds.compute.config.BaseComputeServiceContextModule;
import org.jclouds.compute.domain.NodeState;
import org.jclouds.savvis.vpdc.domain.VApp;
import org.jclouds.savvis.vpdc.domain.VM;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
@ -38,15 +38,15 @@ import com.google.inject.Provides;
public class VPDCComputeServiceContextModule extends BaseComputeServiceContextModule {
@VisibleForTesting
public static final Map<VApp.Status, NodeState> VAPPSTATUS_TO_NODESTATE = ImmutableMap
.<VApp.Status, NodeState> builder().put(VApp.Status.OFF, NodeState.SUSPENDED)
.put(VApp.Status.ON, NodeState.RUNNING).put(VApp.Status.RESOLVED, NodeState.PENDING)
.put(VApp.Status.UNRECOGNIZED, NodeState.UNRECOGNIZED).put(VApp.Status.UNKNOWN, NodeState.UNRECOGNIZED)
.put(VApp.Status.SUSPENDED, NodeState.SUSPENDED).put(VApp.Status.UNRESOLVED, NodeState.PENDING).build();
public static final Map<VM.Status, NodeState> VAPPSTATUS_TO_NODESTATE = ImmutableMap
.<VM.Status, NodeState> builder().put(VM.Status.OFF, NodeState.SUSPENDED)
.put(VM.Status.ON, NodeState.RUNNING).put(VM.Status.RESOLVED, NodeState.PENDING)
.put(VM.Status.UNRECOGNIZED, NodeState.UNRECOGNIZED).put(VM.Status.UNKNOWN, NodeState.UNRECOGNIZED)
.put(VM.Status.SUSPENDED, NodeState.SUSPENDED).put(VM.Status.UNRESOLVED, NodeState.PENDING).build();
@Singleton
@Provides
protected Map<VApp.Status, NodeState> provideVAppStatusToNodeState() {
protected Map<VM.Status, NodeState> provideVAppStatusToNodeState() {
return VAPPSTATUS_TO_NODESTATE;
}

View File

@ -53,6 +53,8 @@ import org.jclouds.savvis.vpdc.domain.Resource;
import org.jclouds.savvis.vpdc.domain.internal.VCloudSession;
import org.jclouds.savvis.vpdc.features.BrowsingAsyncClient;
import org.jclouds.savvis.vpdc.features.BrowsingClient;
import org.jclouds.savvis.vpdc.features.VMAsyncClient;
import org.jclouds.savvis.vpdc.features.VMClient;
import org.jclouds.savvis.vpdc.handlers.VPDCErrorHandler;
import org.jclouds.savvis.vpdc.internal.LoginAsyncClient;
import org.jclouds.savvis.vpdc.internal.VCloudToken;
@ -89,7 +91,7 @@ public class VPDCRestClientModule extends RestClientModule<VPDCClient, VPDCAsync
@org.jclouds.savvis.vpdc.internal.Org
@Singleton
protected Set<org.jclouds.savvis.vpdc.domain.Resource> provideOrgs(Supplier<VCloudSession> cache,
@Named(PROPERTY_IDENTITY) String user) {
@Named(PROPERTY_IDENTITY) String user) {
VCloudSession discovery = cache.get();
checkState(discovery.getOrgs().size() > 0, "No orgs present for user: " + user);
return discovery.getOrgs();
@ -107,13 +109,14 @@ public class VPDCRestClientModule extends RestClientModule<VPDCClient, VPDCAsync
@Provides
@Singleton
protected Predicate<String> successTester(Injector injector,
@Named(PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED) long completed) {
@Named(PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED) long completed) {
return new RetryablePredicate<String>(injector.getInstance(TaskSuccess.class), completed);
}
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()//
.put(BrowsingClient.class, BrowsingAsyncClient.class)//
.build();
.put(BrowsingClient.class, BrowsingAsyncClient.class)//
.put(VMClient.class, VMAsyncClient.class)//
.build();
public VPDCRestClientModule() {
super(VPDCClient.class, VPDCAsyncClient.class, DELEGATE_MAP);
@ -122,31 +125,33 @@ public class VPDCRestClientModule extends RestClientModule<VPDCClient, VPDCAsync
@Singleton
@Provides
protected Set<CIMOperatingSystem> provideOperatingSystems(Json json, @Provider String providerName)
throws IOException {
return json.fromJson(Strings2.toStringAndClose(getClass().getResourceAsStream(
"/" + providerName + "/predefined_operatingsystems.json")), new TypeLiteral<Set<CIMOperatingSystem>>() {
}.getType());
throws IOException {
return json.fromJson(
Strings2.toStringAndClose(getClass().getResourceAsStream(
"/" + providerName + "/predefined_operatingsystems.json")),
new TypeLiteral<Set<CIMOperatingSystem>>() {
}.getType());
}
@Provides
@Singleton
protected Supplier<VCloudSession> provideVCloudTokenCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds,
final LoginAsyncClient login) {
final LoginAsyncClient login) {
return new MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<VCloudSession>(authException, seconds,
new Supplier<VCloudSession>() {
new Supplier<VCloudSession>() {
@Override
public VCloudSession get() {
try {
return login.login().get(10, TimeUnit.SECONDS);
} catch (Exception e) {
propagate(e);
assert false : e;
return null;
}
@Override
public VCloudSession get() {
try {
return login.login().get(10, TimeUnit.SECONDS);
} catch (Exception e) {
propagate(e);
assert false : e;
return null;
}
}
});
});
}
@Override

View File

@ -18,7 +18,7 @@ import com.google.common.collect.Sets;
*
* @author Adrian Cole
*/
public class VApp extends Resource {
public class VM extends Resource {
/**
* Objects such as vAppTemplate, vApp, and Vm have a status attribute whose value indicates the
* state of the object. Status for an object, such as a vAppTemplate or vApp, whose Children (Vm
@ -161,12 +161,12 @@ public class VApp extends Resource {
}
@Override
public VApp build() {
return new VApp(id, name, type, href, status, ipAddress, osType, osDescripton, networkSection,
public VM build() {
return new VM(id, name, type, href, status, ipAddress, osType, osDescripton, networkSection,
resourceAllocations);
}
public static Builder fromVApp(VApp in) {
public static Builder fromVApp(VM in) {
return new Builder().id(in.getId()).name(in.getName()).type(in.getType()).href(in.getHref())
.status(in.getStatus()).ipAddress(in.getIpAddress()).osType(in.getOsType())
.networkSection(in.getNetworkSection()).resourceAllocations(in.getResourceAllocations())
@ -202,7 +202,7 @@ public class VApp extends Resource {
private final NetworkSection networkSection;
private final Set<ResourceAllocationSettingData> resourceAllocations;
public VApp(String id, String name, String type, URI href, Status status, String ipAddress, Integer osType,
public VM(String id, String name, String type, URI href, Status status, String ipAddress, Integer osType,
String osDescripton, NetworkSection networkSection, Set<ResourceAllocationSettingData> resourceAllocations) {
super(id, name, type, href);
this.status = status;

View File

@ -0,0 +1,214 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.savvis.vpdc.domain;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import org.jclouds.compute.domain.CIMOperatingSystem;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
/**
* A specification to launch a virtual machine
*
* @author Adrian Cole
*/
public class VMSpec {
public static Builder builder() {
return new Builder();
}
public static class Builder {
private CIMOperatingSystem operatingSystem;
// TODO docs suggest fractions are possible, but xml isn't accepted on add
private float processorCount = 1f;
private int memoryInGig = 1;
private String bootDeviceName = "/";
// TODO doesn't seem to be changeable
private int bootDriveSize = 25;
private Map<String, Integer> dataDriveDeviceNameToSizeInGig = Maps.newLinkedHashMap();
public Builder operatingSystem(CIMOperatingSystem operatingSystem) {
this.operatingSystem = checkNotNull(operatingSystem, "operatingSystem");
return this;
}
public Builder memoryInGig(int memoryInGig) {
checkArgument(memoryInGig > 0, "memoryInGig must be positive");
this.memoryInGig = memoryInGig;
return this;
}
public Builder processorCount(float processorCount) {
checkProcessorCount(processorCount);
this.processorCount = processorCount;
return this;
}
public Builder bootDeviceName(String bootDeviceName) {
this.bootDeviceName = checkNotNull(bootDeviceName, "bootDeviceName");
return this;
}
public Builder bootDiskSize(int bootDriveSize) {
checkArgument(bootDriveSize > 0, "bootDriveSize must be positive");
this.bootDriveSize = bootDriveSize;
return this;
}
public Builder addDataDrive(String dataDriveDeviceName, int sizeInGig) {
checkArgument(sizeInGig > 0, "sizeInGig must be positive");
this.dataDriveDeviceNameToSizeInGig.put(checkNotNull(dataDriveDeviceName, "dataDriveDeviceName"), sizeInGig);
return this;
}
public Builder addDataDrives(Map<String, Integer> dataDriveDeviceNameToSizeInGig) {
this.dataDriveDeviceNameToSizeInGig = ImmutableMap.copyOf(checkNotNull(dataDriveDeviceNameToSizeInGig,
"dataDriveDeviceNameToSizeInGig"));
return this;
}
public VMSpec build() {
return new VMSpec(operatingSystem, processorCount, memoryInGig, bootDeviceName, bootDriveSize,
dataDriveDeviceNameToSizeInGig);
}
public static Builder fromVMSpec(VMSpec in) {
return new Builder().operatingSystem(in.getOperatingSystem()).memoryInGig(in.getMemoryInGig())
.bootDeviceName(in.getBootDeviceName()).bootDiskSize(in.getBootDiskSize())
.addDataDrives(in.getDataDiskDeviceNameToSizeInGig()).processorCount(in.getProcessorCount());
}
}
static void checkProcessorCount(float processorCount) {
checkArgument(processorCount > 0, "processorCount must be positive and an increment of 0.5");
checkArgument(processorCount % .5 == 0, "processorCount must be an increment of 0.5");
}
private final CIMOperatingSystem operatingSystem;
private final float processorCount;
private final int memoryInGig;
private final String bootDeviceName;
private final int bootDriveSize;
private final Map<String, Integer> dataDriveDeviceNameToSizeInGig;
protected VMSpec(CIMOperatingSystem operatingSystem, float processorCount, int memoryInGig, String bootDeviceName,
int bootDriveSize, Map<String, Integer> dataDriveDeviceNameToSizeInGig) {
this.operatingSystem = checkNotNull(operatingSystem, "operatingSystem not specified");
checkProcessorCount(processorCount);
this.processorCount = processorCount;
checkArgument(memoryInGig > 0, "memoryInGig must be positive");
this.memoryInGig = memoryInGig;
this.bootDeviceName = checkNotNull(bootDeviceName, "bootDeviceName name not specified");
checkArgument(bootDriveSize > 0, "bootDriveSize must be positive");
this.bootDriveSize = bootDriveSize;
this.dataDriveDeviceNameToSizeInGig = ImmutableMap.copyOf(checkNotNull(dataDriveDeviceNameToSizeInGig,
"dataDriveDeviceNameToSizeInGig"));
}
public CIMOperatingSystem getOperatingSystem() {
return operatingSystem;
}
public float getProcessorCount() {
return processorCount;
}
public int getMemoryInGig() {
return memoryInGig;
}
public Builder toBuilder() {
return Builder.fromVMSpec(this);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((bootDeviceName == null) ? 0 : bootDeviceName.hashCode());
result = prime * result + bootDriveSize;
result = prime * result
+ ((dataDriveDeviceNameToSizeInGig == null) ? 0 : dataDriveDeviceNameToSizeInGig.hashCode());
result = prime * result + memoryInGig;
result = prime * result + ((operatingSystem == null) ? 0 : operatingSystem.hashCode());
result = prime * result + Float.floatToIntBits(processorCount);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
VMSpec other = (VMSpec) obj;
if (bootDeviceName == null) {
if (other.bootDeviceName != null)
return false;
} else if (!bootDeviceName.equals(other.bootDeviceName))
return false;
if (bootDriveSize != other.bootDriveSize)
return false;
if (dataDriveDeviceNameToSizeInGig == null) {
if (other.dataDriveDeviceNameToSizeInGig != null)
return false;
} else if (!dataDriveDeviceNameToSizeInGig.equals(other.dataDriveDeviceNameToSizeInGig))
return false;
if (memoryInGig != other.memoryInGig)
return false;
if (operatingSystem == null) {
if (other.operatingSystem != null)
return false;
} else if (!operatingSystem.equals(other.operatingSystem))
return false;
if (Float.floatToIntBits(processorCount) != Float.floatToIntBits(other.processorCount))
return false;
return true;
}
public String getBootDeviceName() {
return bootDeviceName;
}
public int getBootDiskSize() {
return bootDriveSize;
}
public Map<String, Integer> getDataDiskDeviceNameToSizeInGig() {
return dataDriveDeviceNameToSizeInGig;
}
@Override
public String toString() {
return "[operatingSystem=" + operatingSystem + ", processorCount=" + processorCount + ", memoryInGig="
+ memoryInGig + ", bootDeviceName=" + bootDeviceName + ", bootDriveSize=" + bootDriveSize
+ ", dataDriveDeviceNameToSizeInGig=" + dataDriveDeviceNameToSizeInGig + "]";
}
}

View File

@ -33,16 +33,16 @@ import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.savvis.vpdc.domain.Network;
import org.jclouds.savvis.vpdc.domain.Org;
import org.jclouds.savvis.vpdc.domain.Task;
import org.jclouds.savvis.vpdc.domain.VApp;
import org.jclouds.savvis.vpdc.domain.VM;
import org.jclouds.savvis.vpdc.domain.VDC;
import org.jclouds.savvis.vpdc.filters.SetVCloudTokenCookie;
import org.jclouds.savvis.vpdc.functions.DefaultOrgIfNull;
import org.jclouds.savvis.vpdc.options.BindGetVAppOptions;
import org.jclouds.savvis.vpdc.options.GetVAppOptions;
import org.jclouds.savvis.vpdc.options.BindGetVMOptions;
import org.jclouds.savvis.vpdc.options.GetVMOptions;
import org.jclouds.savvis.vpdc.xml.NetworkHandler;
import org.jclouds.savvis.vpdc.xml.OrgHandler;
import org.jclouds.savvis.vpdc.xml.TaskHandler;
import org.jclouds.savvis.vpdc.xml.VAppHandler;
import org.jclouds.savvis.vpdc.xml.VMHandler;
import org.jclouds.savvis.vpdc.xml.VDCHandler;
import com.google.common.util.concurrent.ListenableFuture;
@ -80,27 +80,27 @@ public interface BrowsingAsyncClient {
@PathParam("vpdcId") String vpdcId);
/**
* @see BrowsingClient#getNetworkInOrgAndVDC
* @see BrowsingClient#getNetworkInVDC
*/
@GET
@XMLResponseParser(NetworkHandler.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@Path("org/{billingSiteId}/vdc/{vpdcId}/network/{network-tier-name}")
ListenableFuture<Network> getNetworkInOrgAndVDC(
ListenableFuture<Network> getNetworkInVDC(
@PathParam("billingSiteId") @Nullable @ParamParser(DefaultOrgIfNull.class) String billingSiteId,
@PathParam("vpdcId") String vpdcId, @PathParam("network-tier-name") String networkTierName);
/**
* @see BrowsingClient#getVAppInOrgAndVDC
* @see BrowsingClient#getVMInVDC
*/
@GET
@XMLResponseParser(VAppHandler.class)
@XMLResponseParser(VMHandler.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
@Path("org/{billingSiteId}/vdc/{vpdcId}/vApp/{vAppId}")
ListenableFuture<VApp> getVAppInOrgAndVDC(
ListenableFuture<VM> getVMInVDC(
@PathParam("billingSiteId") @Nullable @ParamParser(DefaultOrgIfNull.class) String billingSiteId,
@PathParam("vpdcId") String vpdcId, @PathParam("vAppId") String vAppId,
@BinderParam(BindGetVAppOptions.class) GetVAppOptions... options);
@BinderParam(BindGetVMOptions.class) GetVMOptions... options);
/**
* @see BrowsingClient#getTask

View File

@ -27,9 +27,9 @@ import org.jclouds.concurrent.Timeout;
import org.jclouds.savvis.vpdc.domain.Network;
import org.jclouds.savvis.vpdc.domain.Org;
import org.jclouds.savvis.vpdc.domain.Task;
import org.jclouds.savvis.vpdc.domain.VApp;
import org.jclouds.savvis.vpdc.domain.VM;
import org.jclouds.savvis.vpdc.domain.VDC;
import org.jclouds.savvis.vpdc.options.GetVAppOptions;
import org.jclouds.savvis.vpdc.options.GetVMOptions;
/**
* Provides access to Symphony VPDC resources via their REST API.
@ -73,7 +73,7 @@ public interface BrowsingClient {
* @return network detail if it used any one deployed VM and NetworkConfigSection defines various
* network features such NAT Public IP, Gateway and Netmask, or null if not present
*/
Network getNetworkInOrgAndVDC(String billingSiteId, String vpdcId, String networkTierName);
Network getNetworkInVDC(String billingSiteId, String vpdcId, String networkTierName);
/**
* VAPP is a software solution, the API returns details of virtual machine configuration such as
@ -92,14 +92,14 @@ public interface BrowsingClient {
* machines, all of which are deployed, managed, and maintained as a unit, or null if not
* present
*/
VApp getVAppInOrgAndVDC(String billingSiteId, String vpdcId, String vAppId, GetVAppOptions... options);
VM getVMInVDC(String billingSiteId, String vpdcId, String vAppId, GetVMOptions... options);
/**
* Gets an existing task.
*
* @param taskId
* task id
* @return If the request is successful, caller could get the VApp/VMDK details as specified in
* @return If the request is successful, caller could get the VM/VMDK details as specified in
* the result element and if the request is not successful, caller would get empty
* VAPP/VMDK URL and respective validation (error) message.
*/

View File

@ -0,0 +1,78 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.savvis.vpdc.features;
import javax.annotation.Nullable;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.savvis.vpdc.binders.BindVMSpecToXmlPayload;
import org.jclouds.savvis.vpdc.domain.Task;
import org.jclouds.savvis.vpdc.domain.VMSpec;
import org.jclouds.savvis.vpdc.filters.SetVCloudTokenCookie;
import org.jclouds.savvis.vpdc.functions.DefaultOrgIfNull;
import org.jclouds.savvis.vpdc.xml.TaskHandler;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides access to Symphony VPDC resources via their REST API.
* <p/>
*
* @see <a href="https://api.sandbox.symphonyvpdc.savvis.net/doc/spec/api/index.html" />
* @author Adrian Cole
*/
@RequestFilters(SetVCloudTokenCookie.class)
@Path("v{jclouds.api-version}")
public interface VMAsyncClient {
/**
* @see VMClient#addVMIntoVDC
*/
@GET
@XMLResponseParser(TaskHandler.class)
@Path("org/{billingSiteId}/vdc/{vpdcId}/vApp/")
@MapBinder(BindVMSpecToXmlPayload.class)
ListenableFuture<Task> addVMIntoVDC(
@PathParam("billingSiteId") @Nullable @ParamParser(DefaultOrgIfNull.class) String billingSiteId,
@PathParam("vpdcId") String vpdcId, @PayloadParam("networkName") String networkTierName,
@PayloadParam("name") String vAppName, VMSpec spec);
/**
* @see VMClient#removeVMFromVDC
*/
@DELETE
@XMLResponseParser(TaskHandler.class)
@Path("org/{billingSiteId}/vdc/{vpdcId}/vApp/{vAppId}")
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Task> removeVMFromVDC(
@PathParam("billingSiteId") @Nullable @ParamParser(DefaultOrgIfNull.class) String billingSiteId,
@PathParam("vpdcId") String vpdcId, @PathParam("vAppId") String vAppId);
}

View File

@ -0,0 +1,72 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.savvis.vpdc.features;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
import org.jclouds.savvis.vpdc.domain.Task;
import org.jclouds.savvis.vpdc.domain.VMSpec;
/**
* Provides access to Symphony VPDC resources via their REST API.
* <p/>
*
* @see <a href="https://api.sandbox.symphonyvpdc.savvis.net/doc/spec/api/" />
* @author Adrian Cole
*/
@Timeout(duration = 300, timeUnit = TimeUnit.SECONDS)
public interface VMClient {
/**
* Add/Deploy new VM into VDC
*
* @param billingSiteId
* billing site Id, or null for default
* @param vpdcId
* vpdc Id
* @param networkTierName
* network tier name
* @param spec
* how to
*
* @return VM in progress
*/
Task addVMIntoVDC(String billingSiteId, String vpdcId, String networkTierName, String name, VMSpec spec);
/**
* Remove a VM
* <p/>
* <h4>Pre-conditions:</h4>
*
* <ul>
* <li>No snapshot has been created for the VM.</li>
* <li>For Balanced profile, the VM must not be associated with any firewall rule and/or included
* in a load balancing pool.</li>
* </ul>
*
* @param billingSiteId
* @param vpdcId
* @param vAppId
* @return
*/
Task removeVMFromVDC(String billingSiteId, String vpdcId, String vAppId);
}

View File

@ -15,19 +15,19 @@ import org.jclouds.rest.Binder;
* @author Adrian Cole
*/
@Singleton
public class BindGetVAppOptions implements Binder {
public class BindGetVMOptions implements Binder {
private final Provider<UriBuilder> uriBuilder;
@Inject
public BindGetVAppOptions(Provider<UriBuilder> uriBuilder) {
public BindGetVMOptions(Provider<UriBuilder> uriBuilder) {
this.uriBuilder = uriBuilder;
}
@SuppressWarnings("unchecked")
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
checkArgument(input instanceof GetVAppOptions[], "this binder is only valid for GetVAppOptions!");
GetVAppOptions[] options = GetVAppOptions[].class.cast(input);
checkArgument(input instanceof GetVMOptions[], "this binder is only valid for GetVAppOptions!");
GetVMOptions[] options = GetVMOptions[].class.cast(input);
if (options.length > 0 && options[0].isWithPowerState())
return (R) request.toBuilder().endpoint(
uriBuilder.get().uri(request.getEndpoint()).path("withpowerstate").build()).build();

View File

@ -30,21 +30,21 @@ package org.jclouds.savvis.vpdc.options;
* import static org.jclouds.savvis.vpdc.options.GetVAppOptions.Builder.*
* <p/>
*
* vApp = context.getApi().getBrowsingClient().getVAppInOrgAndVDC(orgId, vdcId, vAppId, withPowerState());
* vApp = context.getApi().getBrowsingClient().getVAppInVDC(orgId, vdcId, vAppId, withPowerState());
* <code>
*
* @author Adrian Cole
* @see <a href= "https://api.sandbox.symphonyvpdc.savvis.net/doc/spec/api/getVAppPowerState.html"
* />
*/
public class GetVAppOptions {
public static final GetVAppOptions NONE = new GetVAppOptions();
public class GetVMOptions {
public static final GetVMOptions NONE = new GetVMOptions();
private boolean withPowerState;
/**
* The VM State is the real time state.
*/
public GetVAppOptions withPowerState() {
public GetVMOptions withPowerState() {
this.withPowerState = true;
return this;
}
@ -56,10 +56,10 @@ public class GetVAppOptions {
public static class Builder {
/**
* @see GetVAppOptions#withPowerState()
* @see GetVMOptions#withPowerState()
*/
public static GetVAppOptions withPowerState() {
GetVAppOptions options = new GetVAppOptions();
public static GetVMOptions withPowerState() {
GetVMOptions options = new GetVMOptions();
return options.withPowerState();
}

View File

@ -29,7 +29,7 @@ import org.jclouds.cim.xml.ResourceAllocationSettingDataHandler;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.ovf.xml.NetworkSectionHandler;
import org.jclouds.savvis.vpdc.domain.Resource;
import org.jclouds.savvis.vpdc.domain.VApp;
import org.jclouds.savvis.vpdc.domain.VM;
import org.jclouds.savvis.vpdc.util.Utils;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
@ -39,25 +39,25 @@ import com.google.common.collect.ImmutableMap;
/**
* @author Kedar Dave
*/
public class VAppHandler extends ParseSax.HandlerWithResult<VApp> {
public class VMHandler extends ParseSax.HandlerWithResult<VM> {
protected StringBuilder currentText = new StringBuilder();
private final NetworkSectionHandler networkSectionHandler;
private final ResourceAllocationSettingDataHandler allocationHandler;
@Inject
public VAppHandler(NetworkSectionHandler networkSectionHandler, ResourceAllocationSettingDataHandler allocationHandler) {
public VMHandler(NetworkSectionHandler networkSectionHandler, ResourceAllocationSettingDataHandler allocationHandler) {
this.networkSectionHandler = networkSectionHandler;
this.allocationHandler = allocationHandler;
}
private VApp.Builder builder = VApp.builder();
private VM.Builder builder = VM.builder();
protected boolean inOs;
public VApp getResult() {
public VM getResult() {
try {
return builder.build();
} finally {
builder = VApp.builder();
builder = VM.builder();
}
}
@ -70,7 +70,7 @@ public class VAppHandler extends ParseSax.HandlerWithResult<VApp> {
.put("href", getRequest().getEndpoint().toASCIIString()).build();
Resource vApp = newResource(attributes);
builder.name(vApp.getName()).type(vApp.getType()).id(vApp.getId()).href(vApp.getHref());
builder.status(VApp.Status.fromValue(attributes.get("status")));
builder.status(VM.Status.fromValue(attributes.get("status")));
} else if (qName.endsWith("OperatingSystemSection")) {
inOs = true;
if (attributes.containsKey("id"))

View File

@ -16,7 +16,7 @@
"osType": "RHEL"
},
{
"family": "RHEL_64",
"family": "RHEL",
"name": "rhel5_64Guest",
"version": "5",
"description": "Red Hat Enterprise Linux 5.x 64bit",

View File

@ -45,6 +45,7 @@ public class VPDCAsyncClientTest extends BaseVPDCAsyncClientTest<VPDCAsyncClient
public void testSync() {
assert syncClient.getBrowsingClient() != null;
assert syncClient.getVMClient() != null;
assertEquals(syncClient.listOrgs().size(), 1);
assertEquals(syncClient.listPredefinedOperatingSystems().size(), 3);
@ -52,6 +53,7 @@ public class VPDCAsyncClientTest extends BaseVPDCAsyncClientTest<VPDCAsyncClient
public void testAsync() {
assert asyncClient.getBrowsingClient() != null;
assert asyncClient.getVMClient() != null;
assertEquals(asyncClient.listOrgs().size(), 1);
assertEquals(asyncClient.listPredefinedOperatingSystems().size(), 3);

View File

@ -0,0 +1,66 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.savvis.vpdc.binders;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.util.Set;
import org.jclouds.cim.OSType;
import org.jclouds.compute.domain.CIMOperatingSystem;
import org.jclouds.savvis.vpdc.domain.VMSpec;
import org.jclouds.util.Strings2;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.gson.Gson;
import com.google.inject.TypeLiteral;
/**
* Tests behavior of {@code BindVMSpecToXmlPayload}
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class BindVMSpecToXmlPayloadTest {
public void test() throws IOException {
CIMOperatingSystem os = Iterables.find(new Gson().<Set<CIMOperatingSystem>> fromJson(
Strings2.toStringAndClose(getClass().getResourceAsStream(
"/savvis-symphonyvpdc/predefined_operatingsystems.json")),
new TypeLiteral<Set<CIMOperatingSystem>>() {
}.getType()), new Predicate<CIMOperatingSystem>() {
@Override
public boolean apply(CIMOperatingSystem arg0) {
return arg0.getOsType() == OSType.RHEL_64;
}
});
String expected = Strings2.toStringAndClose(getClass().getResourceAsStream("/vm-default.xml"));
VMSpec spec = VMSpec.builder().operatingSystem(os).build();
assertEquals(new BindVMSpecToXmlPayload().generateXml(spec, "DemoHost-1", "VM Tier01"), expected);
}
}

View File

@ -28,12 +28,16 @@ import org.jclouds.rest.RestContext;
import org.jclouds.rest.RestContextFactory;
import org.jclouds.savvis.vpdc.VPDCAsyncClient;
import org.jclouds.savvis.vpdc.VPDCClient;
import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
/**
* Tests behavior of {@code VPDCClient}
@ -49,11 +53,12 @@ public class BaseVPDCClientLiveTest {
protected String credential;
protected String endpoint;
protected String apiversion;
protected Injector injector;
protected void setupCredentials() {
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity");
credential = checkNotNull(System.getProperty("test." + provider + ".credential"), "test." + provider
+ ".credential");
+ ".credential");
endpoint = System.getProperty("test." + provider + ".endpoint");
apiversion = System.getProperty("test." + provider + ".apiversion");
}
@ -73,8 +78,13 @@ public class BaseVPDCClientLiveTest {
public void setupClient() {
setupCredentials();
Properties overrides = setupProperties();
context = new RestContextFactory().createContext(provider, ImmutableSet.<Module> of(new Log4JLoggingModule()),
overrides);
// context = new RestContextFactory().createContext(provider, ImmutableSet.<Module> of(new
// Log4JLoggingModule()),
// overrides);
injector = new RestContextFactory().createContextBuilder(provider,
ImmutableSet.<Module> of(new Log4JLoggingModule(), new JschSshClientModule()), overrides).buildInjector();
context = injector.getInstance(Key.get(new TypeLiteral<RestContext<VPDCClient, VPDCAsyncClient>>() {
}));
}
@AfterGroups(groups = "live")

View File

@ -26,11 +26,11 @@ import org.jclouds.http.HttpRequest;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.savvis.vpdc.options.GetVAppOptions;
import org.jclouds.savvis.vpdc.options.GetVMOptions;
import org.jclouds.savvis.vpdc.xml.NetworkHandler;
import org.jclouds.savvis.vpdc.xml.OrgHandler;
import org.jclouds.savvis.vpdc.xml.TaskHandler;
import org.jclouds.savvis.vpdc.xml.VAppHandler;
import org.jclouds.savvis.vpdc.xml.VMHandler;
import org.jclouds.savvis.vpdc.xml.VDCHandler;
import org.testng.annotations.Test;
@ -105,7 +105,7 @@ public class BrowsingAsyncClientTest extends BaseVPDCAsyncClientTest<BrowsingAsy
}
public void testNetwork() throws SecurityException, NoSuchMethodException, IOException {
Method method = BrowsingAsyncClient.class.getMethod("getNetworkInOrgAndVDC", String.class, String.class,
Method method = BrowsingAsyncClient.class.getMethod("getNetworkInVDC", String.class, String.class,
String.class);
HttpRequest request = processor.createRequest(method, "11", "22", "VM-Tier01");
@ -122,7 +122,7 @@ public class BrowsingAsyncClientTest extends BaseVPDCAsyncClientTest<BrowsingAsy
}
public void testNetworkWhenOrgNull() throws SecurityException, NoSuchMethodException, IOException {
Method method = BrowsingAsyncClient.class.getMethod("getNetworkInOrgAndVDC", String.class, String.class,
Method method = BrowsingAsyncClient.class.getMethod("getNetworkInVDC", String.class, String.class,
String.class);
HttpRequest request = processor.createRequest(method, (String) null, "22", "VM-Tier01");
@ -138,9 +138,9 @@ public class BrowsingAsyncClientTest extends BaseVPDCAsyncClientTest<BrowsingAsy
checkFilters(request);
}
public void testVApp() throws SecurityException, NoSuchMethodException, IOException {
Method method = BrowsingAsyncClient.class.getMethod("getVAppInOrgAndVDC", String.class, String.class,
String.class, GetVAppOptions[].class);
public void testVM() throws SecurityException, NoSuchMethodException, IOException {
Method method = BrowsingAsyncClient.class.getMethod("getVMInVDC", String.class, String.class,
String.class, GetVMOptions[].class);
HttpRequest request = processor.createRequest(method, "11", "22", "VM-Tier01");
assertRequestLineEquals(request,
@ -149,16 +149,16 @@ public class BrowsingAsyncClientTest extends BaseVPDCAsyncClientTest<BrowsingAsy
assertPayloadEquals(request, null, null, false);
assertResponseParserClassEquals(method, request, ParseSax.class);
assertSaxResponseParserClassEquals(method, VAppHandler.class);
assertSaxResponseParserClassEquals(method, VMHandler.class);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(request);
}
public void testVAppWithPowerState() throws SecurityException, NoSuchMethodException, IOException {
Method method = BrowsingAsyncClient.class.getMethod("getVAppInOrgAndVDC", String.class, String.class,
String.class, GetVAppOptions[].class);
HttpRequest request = processor.createRequest(method, "11", "22", "VM-Tier01", GetVAppOptions.Builder
public void testVMWithPowerState() throws SecurityException, NoSuchMethodException, IOException {
Method method = BrowsingAsyncClient.class.getMethod("getVMInVDC", String.class, String.class,
String.class, GetVMOptions[].class);
HttpRequest request = processor.createRequest(method, "11", "22", "VM-Tier01", GetVMOptions.Builder
.withPowerState());
assertRequestLineEquals(request,
@ -167,15 +167,15 @@ public class BrowsingAsyncClientTest extends BaseVPDCAsyncClientTest<BrowsingAsy
assertPayloadEquals(request, null, null, false);
assertResponseParserClassEquals(method, request, ParseSax.class);
assertSaxResponseParserClassEquals(method, VAppHandler.class);
assertSaxResponseParserClassEquals(method, VMHandler.class);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(request);
}
public void testVAppWhenOrgNull() throws SecurityException, NoSuchMethodException, IOException {
Method method = BrowsingAsyncClient.class.getMethod("getVAppInOrgAndVDC", String.class, String.class,
String.class, GetVAppOptions[].class);
public void testVMWhenOrgNull() throws SecurityException, NoSuchMethodException, IOException {
Method method = BrowsingAsyncClient.class.getMethod("getVMInVDC", String.class, String.class,
String.class, GetVMOptions[].class);
HttpRequest request = processor.createRequest(method, (String) null, "22", "VM-Tier01");
assertRequestLineEquals(request,
@ -184,7 +184,7 @@ public class BrowsingAsyncClientTest extends BaseVPDCAsyncClientTest<BrowsingAsy
assertPayloadEquals(request, null, null, false);
assertResponseParserClassEquals(method, request, ParseSax.class);
assertSaxResponseParserClassEquals(method, VAppHandler.class);
assertSaxResponseParserClassEquals(method, VMHandler.class);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(request);

View File

@ -19,14 +19,14 @@
package org.jclouds.savvis.vpdc.features;
import static org.jclouds.savvis.vpdc.options.GetVAppOptions.Builder.withPowerState;
import static org.jclouds.savvis.vpdc.options.GetVMOptions.Builder.withPowerState;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import org.jclouds.savvis.vpdc.domain.Network;
import org.jclouds.savvis.vpdc.domain.Org;
import org.jclouds.savvis.vpdc.domain.Resource;
import org.jclouds.savvis.vpdc.domain.VApp;
import org.jclouds.savvis.vpdc.domain.VM;
import org.jclouds.savvis.vpdc.domain.VDC;
import org.jclouds.savvis.vpdc.reference.VCloudMediaType;
import org.testng.annotations.BeforeGroups;
@ -92,7 +92,7 @@ public class BrowsingClientLiveTest extends BaseVPDCClientLiveTest {
for (Resource vdc : org.getVDCs()) {
VDC VDC = client.getVDCInOrg(org.getId(), vdc.getId());
for (Resource vApp : VDC.getAvailableNetworks()) {
Network response = client.getNetworkInOrgAndVDC(org.getId(), vdc.getId(), vApp.getId());
Network response = client.getNetworkInVDC(org.getId(), vdc.getId(), vApp.getId());
assertNotNull(response);
assertNotNull(response.getId());
assertNotNull(response.getHref());
@ -101,7 +101,7 @@ public class BrowsingClientLiveTest extends BaseVPDCClientLiveTest {
assertNotNull(response.getNetmask());
assertNotNull(response.getGateway());
assertNotNull(response.getInternalToExternalNATRules());
assertEquals(client.getNetworkInOrgAndVDC(org.getId(), vdc.getId(), response.getId()).toString(),
assertEquals(client.getNetworkInVDC(org.getId(), vdc.getId(), response.getId()).toString(),
response.toString());
}
}
@ -109,7 +109,7 @@ public class BrowsingClientLiveTest extends BaseVPDCClientLiveTest {
}
@Test
public void testVApp() throws Exception {
public void testVM() throws Exception {
for (Resource org1 : context.getApi().listOrgs()) {
Org org = client.getOrg(org1.getId());
for (Resource vdc : org.getVDCs()) {
@ -122,7 +122,7 @@ public class BrowsingClientLiveTest extends BaseVPDCClientLiveTest {
}
})) {
VApp response = client.getVAppInOrgAndVDC(org.getId(), vdc.getId(), vApp.getId());
VM response = client.getVMInVDC(org.getId(), vdc.getId(), vApp.getId());
assertNotNull(response);
assertNotNull(response.getId());
assertNotNull(response.getHref());
@ -135,7 +135,7 @@ public class BrowsingClientLiveTest extends BaseVPDCClientLiveTest {
assertNotNull(response.getNetworkSection());
assertNotNull(response.getResourceAllocations());
// power state is the only thing that should change
assertEquals(client.getVAppInOrgAndVDC(org.getId(), vdc.getId(), response.getId(), withPowerState())
assertEquals(client.getVMInVDC(org.getId(), vdc.getId(), response.getId(), withPowerState())
.toString().replaceFirst("status=[A-Z]+", ""), response.toString().replaceFirst(
"status=[A-Z]+", ""));
}

View File

@ -0,0 +1,103 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.savvis.vpdc.features;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Set;
import org.jclouds.cim.OSType;
import org.jclouds.compute.domain.CIMOperatingSystem;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.savvis.vpdc.domain.VMSpec;
import org.jclouds.savvis.vpdc.xml.TaskHandler;
import org.jclouds.util.Strings2;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
/**
* Tests annotation parsing of {@code VMAsyncClient}
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class VMAsyncClientTest extends BaseVPDCAsyncClientTest<VMAsyncClient> {
public void testAddVMIntoVDC() throws SecurityException, NoSuchMethodException, IOException {
Method method = VMAsyncClient.class.getMethod("addVMIntoVDC", String.class, String.class, String.class,
String.class, VMSpec.class);
CIMOperatingSystem os = Iterables.find(injector.getInstance(Key.get(new TypeLiteral<Set<CIMOperatingSystem>>() {
})), new Predicate<CIMOperatingSystem>() {
@Override
public boolean apply(CIMOperatingSystem arg0) {
return arg0.getOsType() == OSType.RHEL_64;
}
});
HttpRequest request = processor.createRequest(method, "11", "22", "VM Tier01", "DemoHost-1", VMSpec.builder()
.operatingSystem(os).build());
assertRequestLineEquals(request,
"GET https://api.symphonyvpdc.savvis.net/rest/api/v0.8/org/11/vdc/22/vApp/ HTTP/1.1");
assertNonPayloadHeadersEqual(request, "");
assertPayloadEquals(request, Strings2.toStringAndClose(getClass().getResourceAsStream("/vm-default.xml")),
"application/xml", false);
assertResponseParserClassEquals(method, request, ParseSax.class);
assertSaxResponseParserClassEquals(method, TaskHandler.class);
assertExceptionParserClassEquals(method, MapHttp4xxCodesToExceptions.class);
checkFilters(request);
}
public void testRemoveVM() throws SecurityException, NoSuchMethodException, IOException {
Method method = VMAsyncClient.class.getMethod("removeVMFromVDC", String.class, String.class, String.class);
HttpRequest request = processor.createRequest(method, "11", "22", "VM-Tier01");
assertRequestLineEquals(request,
"DELETE https://api.symphonyvpdc.savvis.net/rest/api/v0.8/org/11/vdc/22/vApp/VM-Tier01 HTTP/1.1");
assertNonPayloadHeadersEqual(request, "");
assertPayloadEquals(request, null, null, false);
assertResponseParserClassEquals(method, request, ParseSax.class);
assertSaxResponseParserClassEquals(method, TaskHandler.class);
assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class);
checkFilters(request);
}
@Override
protected TypeLiteral<RestAnnotationProcessor<VMAsyncClient>> createTypeLiteral() {
return new TypeLiteral<RestAnnotationProcessor<VMAsyncClient>>() {
};
}
}

View File

@ -0,0 +1,140 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed 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.savvis.vpdc.features;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.testng.Assert.assertEquals;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.jclouds.cim.OSType;
import org.jclouds.compute.domain.CIMOperatingSystem;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.domain.Credentials;
import org.jclouds.net.IPSocket;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.predicates.SocketOpen;
import org.jclouds.savvis.vpdc.domain.Task;
import org.jclouds.savvis.vpdc.domain.VM;
import org.jclouds.savvis.vpdc.domain.VMSpec;
import org.jclouds.savvis.vpdc.predicates.TaskSuccess;
import org.jclouds.ssh.SshClient;
import org.jclouds.ssh.SshClient.Factory;
import org.jclouds.util.InetAddresses2;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.net.HostSpecifier;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
@Test(groups = "live")
public class VMClientLiveTest extends BaseVPDCClientLiveTest {
private VMClient client;
private Factory sshFactory;
private VM vm;
private RetryablePredicate<IPSocket> socketTester;
private RetryablePredicate<String> taskTester;
private String username = checkNotNull(System.getProperty("test." + provider + ".loginUser"), "test." + provider
+ ".loginUser");
private String password = checkNotNull(System.getProperty("test." + provider + ".loginPassword"), "test." + provider
+ ".loginPassword");
@Override
@BeforeGroups(groups = { "live" })
public void setupClient() {
super.setupClient();
client = context.getApi().getVMClient();
sshFactory = injector.getInstance(SshClient.Factory.class);
socketTester = new RetryablePredicate<IPSocket>(injector.getInstance(SocketOpen.class), 130, 10, TimeUnit.SECONDS);// make
taskTester = new RetryablePredicate<String>(injector.getInstance(TaskSuccess.class), 650, 10, TimeUnit.SECONDS);
}
protected String prefix = System.getProperty("user.name");
private String billingSiteId;
private String vpdcId;
public void testCreateVirtualMachine() throws Exception {
billingSiteId = context.getApi().getBrowsingClient().getOrg(null).getId();// default
vpdcId = Iterables.get(context.getApi().getBrowsingClient().getOrg(billingSiteId).getVDCs(), 0).getId();
String networkTierName = Iterables.get(
context.getApi().getBrowsingClient().getVDCInOrg(billingSiteId, vpdcId).getAvailableNetworks(), 0)
.getName();
String name = prefix;
CIMOperatingSystem os = Iterables.find(injector.getInstance(Key.get(new TypeLiteral<Set<CIMOperatingSystem>>() {
})), new Predicate<CIMOperatingSystem>() {
@Override
public boolean apply(CIMOperatingSystem arg0) {
return arg0.getOsType() == OSType.RHEL_64;
}
});
System.out.printf("vpdcId %s, networkName %s, name %s, os %s%n", vpdcId, networkTierName, name, os);
Task task = client.addVMIntoVDC(billingSiteId, vpdcId, networkTierName, name, VMSpec.builder()
.operatingSystem(os).build());
assert this.taskTester.apply(task.getId());
vm = context.getApi().getBrowsingClient().getVMInVDC(billingSiteId, vpdcId, task.getOwner().getId());
conditionallyCheckSSH();
}
private void conditionallyCheckSSH() {
assert HostSpecifier.isValid(vm.getIpAddress());
if (!InetAddresses2.isPrivateIPAddress(vm.getIpAddress())) {
// not sure if the network is public or not, so we have to test
IPSocket socket = new IPSocket(vm.getIpAddress(), 22);
System.err.printf("testing socket %s%n", socket);
System.err.printf("testing ssh %s%n", socket);
checkSSH(socket);
} else {
System.err.printf("skipping ssh %s, as private%n", vm.getIpAddress());
}
}
protected void checkSSH(IPSocket socket) {
socketTester.apply(socket);
SshClient client = sshFactory.create(socket, new Credentials(username, password));
try {
client.connect();
ExecResponse exec = client.exec("echo hello");
System.out.println(exec);
assertEquals(exec.getOutput().trim(), "hello");
} finally {
if (client != null)
client.disconnect();
}
}
@AfterGroups(groups = "live")
protected void tearDown() {
if (vm != null) {
assert taskTester.apply(client.removeVMFromVDC(billingSiteId, vpdcId, vm.getId()).getId()) : vm;
}
super.tearDown();
}
}

View File

@ -0,0 +1 @@
<vApp:VApp xmlns:vApp="http://www.vmware.com/vcloud/v0.8" xmlns:common="http://schemas.dmtf.org/wbem/wscim/1/common" xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1" xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" href="" name="DemoHost-1" type="application/vnd.vmware.vcloud.vApp+xml"><ovf:OperatingSystemSection ovf:id="80"><ovf:Info>Specifies the operating system installed</ovf:Info><ovf:Description>Red Hat Enterprise Linux 5.x 64bit</ovf:Description></ovf:OperatingSystemSection><ovf:VirtualHardwareSection><ovf:Info>Virtual Hardware</ovf:Info><ovf:System><vssd:Description>Virtual Hardware Family</vssd:Description><vssd:ElementName>DemoHost-1</vssd:ElementName><vssd:InstanceID>1</vssd:InstanceID><vssd:VirtualSystemIdentifier>DemoHost-1</vssd:VirtualSystemIdentifier></ovf:System><ovf:Item><rasd:AllocationUnits>3 GHz</rasd:AllocationUnits><rasd:Description>Number of Virtual CPUs</rasd:Description><rasd:ElementName>1 CPU</rasd:ElementName><rasd:InstanceID>1</rasd:InstanceID><rasd:ResourceType>3</rasd:ResourceType><rasd:VirtualQuantity>1</rasd:VirtualQuantity></ovf:Item><ovf:Item><rasd:AllocationUnits>Gigabytes</rasd:AllocationUnits><rasd:Description>Memory Size</rasd:Description><rasd:ElementName>Memory</rasd:ElementName><rasd:InstanceID>2</rasd:InstanceID><rasd:ResourceType>4</rasd:ResourceType><rasd:VirtualQuantity>1</rasd:VirtualQuantity></ovf:Item><ovf:Item><rasd:Caption>false</rasd:Caption><rasd:Connection>VM Tier01</rasd:Connection><rasd:ElementName>Network</rasd:ElementName><rasd:InstanceID>3</rasd:InstanceID><rasd:ResourceType>10</rasd:ResourceType><rasd:VirtualQuantity>1</rasd:VirtualQuantity></ovf:Item><ovf:Item><rasd:AllocationUnits>Gigabytes</rasd:AllocationUnits><rasd:Caption/><rasd:Description>Hard Disk</rasd:Description><rasd:ElementName>/</rasd:ElementName><rasd:HostResource>boot</rasd:HostResource><rasd:InstanceID>4</rasd:InstanceID><rasd:ResourceType>27</rasd:ResourceType><rasd:VirtualQuantity>10</rasd:VirtualQuantity></ovf:Item></ovf:VirtualHardwareSection></vApp:VApp>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<vApp:Network xmlns:common="http://schemas.dmtf.org/wbem/wscim/1/common" xmlns:vApp="http://www.vmware.com/vcloud/v0.8"
xmlns:rasd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData"
xmlns:vssd="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData"
xmlns:ovf="http://schemas.dmtf.org/ovf/envelope/1" name="VM Tier01"
type="application/vnd.vmware.vcloud.network+xml">
<vApp:Configuration>
<vApp:Gateway>1.1.1.1</vApp:Gateway>
<vApp:Netmask>2.2.2.2</vApp:Netmask>
</vApp:Configuration>
<vApp:Features>
<vApp:FenceMode>allowInOut</vApp:FenceMode>
<vApp:Nat>
<vApp:NatRule internalIP="3.3.3.3" externalIP="4.4.4.4"/>
<vApp:NatRule internalIP="3.3.3.4" externalIP="4.4.4.5"/>
</vApp:Nat>
</vApp:Features>
</vApp:Network>