From da29745ac2a9c9794ae53448b92ca23ee4287b31 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Tue, 22 Mar 2011 02:07:46 -0700 Subject: [PATCH 1/3] fixed OVF where we didn't match relationships in spec --- .../org/jclouds/vcloud/VCloudAsyncClient.java | 8 +- .../java/org/jclouds/vcloud/VCloudClient.java | 4 +- .../functions/HardwareForVAppTemplate.java | 10 +- .../functions/ImageForVAppTemplate.java | 4 +- .../ovf/VCloudVirtualHardwareSection.java | 5 +- .../xml/VCloudVirtualHardwareHandler.java | 2 +- .../jclouds/vcloud/VCloudAsyncClientTest.java | 4 +- .../java/org/jclouds/cim/SettingData.java | 12 +- .../compute/domain/CIMOperatingSystem.java | 6 +- .../java/org/jclouds/ovf/Configuration.java | 120 +++++++++ .../jclouds/ovf/DeploymentOptionSection.java | 144 +++++++++++ .../src/main/java/org/jclouds/ovf/Disk.java | 237 ++++++++++++++++++ .../java/org/jclouds/ovf/DiskSection.java | 153 +++++++++++ .../main/java/org/jclouds/ovf/Envelope.java | 205 +++++++++++++++ .../main/java/org/jclouds/ovf/Network.java | 38 ++- .../java/org/jclouds/ovf/NetworkSection.java | 87 ++++++- .../jclouds/ovf/OperatingSystemSection.java | 60 +++-- .../ovf/{OvfEnvelope.java => Section.java} | 62 +++-- .../jclouds/ovf/VirtualHardwareSection.java | 164 ++++++++++-- .../java/org/jclouds/ovf/VirtualSystem.java | 178 +++++++++---- .../xml/DeploymentOptionSectionHandler.java | 72 ++++++ .../jclouds/ovf/xml/DiskSectionHandler.java | 93 +++++++ .../org/jclouds/ovf/xml/EnvelopeHandler.java | 162 ++++++++++++ .../ovf/xml/NetworkSectionHandler.java | 44 ++-- .../xml/OperatingSystemSectionHandler.java | 34 +-- .../jclouds/ovf/xml/OvfEnvelopeHandler.java | 87 ------- .../org/jclouds/ovf/xml/SectionHandler.java | 76 ++++++ .../xml/VirtualHardwareSectionHandler.java | 61 ++--- .../jclouds/ovf/xml/VirtualSystemHandler.java | 122 ++++----- .../VirtualSystemSettingDataHandlerTest.java | 4 +- .../ovf/xml/DiskSectionHandlerTest.java | 61 +++++ ...dlerTest.java => EnvelopeHandlerTest.java} | 11 +- .../ovf/xml/NetworkSectionHandlerTest.java | 58 +++++ .../OperatingSystemSectionHandlerTest.java | 53 ++++ compute/src/test/resources/disksection.xml | 10 + compute/src/test/resources/networksection.xml | 11 + .../test/resources/operatingsystemsection.xml | 4 + ...rityGroupsAsNeededAndReturnRunOptions.java | 2 +- .../SavvisOperatingSystemSpecification.java | 209 --------------- .../savvis/vpdc/domain/vapp/Network.java | 19 ++ 40 files changed, 2109 insertions(+), 587 deletions(-) create mode 100644 compute/src/main/java/org/jclouds/ovf/Configuration.java create mode 100644 compute/src/main/java/org/jclouds/ovf/DeploymentOptionSection.java create mode 100644 compute/src/main/java/org/jclouds/ovf/Disk.java create mode 100644 compute/src/main/java/org/jclouds/ovf/DiskSection.java create mode 100644 compute/src/main/java/org/jclouds/ovf/Envelope.java rename compute/src/main/java/org/jclouds/ovf/{OvfEnvelope.java => Section.java} (52%) create mode 100644 compute/src/main/java/org/jclouds/ovf/xml/DeploymentOptionSectionHandler.java create mode 100644 compute/src/main/java/org/jclouds/ovf/xml/DiskSectionHandler.java create mode 100644 compute/src/main/java/org/jclouds/ovf/xml/EnvelopeHandler.java delete mode 100644 compute/src/main/java/org/jclouds/ovf/xml/OvfEnvelopeHandler.java create mode 100644 compute/src/main/java/org/jclouds/ovf/xml/SectionHandler.java create mode 100644 compute/src/test/java/org/jclouds/ovf/xml/DiskSectionHandlerTest.java rename compute/src/test/java/org/jclouds/ovf/xml/{OvfEnvelopeHandlerTest.java => EnvelopeHandlerTest.java} (83%) create mode 100644 compute/src/test/java/org/jclouds/ovf/xml/NetworkSectionHandlerTest.java create mode 100644 compute/src/test/java/org/jclouds/ovf/xml/OperatingSystemSectionHandlerTest.java create mode 100644 compute/src/test/resources/disksection.xml create mode 100644 compute/src/test/resources/networksection.xml create mode 100644 compute/src/test/resources/operatingsystemsection.xml delete mode 100644 sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/domain/SavvisOperatingSystemSpecification.java diff --git a/apis/vcloud/src/main/java/org/jclouds/vcloud/VCloudAsyncClient.java b/apis/vcloud/src/main/java/org/jclouds/vcloud/VCloudAsyncClient.java index b3f8b3b77d..b163b3e79c 100644 --- a/apis/vcloud/src/main/java/org/jclouds/vcloud/VCloudAsyncClient.java +++ b/apis/vcloud/src/main/java/org/jclouds/vcloud/VCloudAsyncClient.java @@ -42,8 +42,8 @@ import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; -import org.jclouds.ovf.OvfEnvelope; -import org.jclouds.ovf.xml.OvfEnvelopeHandler; +import org.jclouds.ovf.Envelope; +import org.jclouds.ovf.xml.EnvelopeHandler; import org.jclouds.predicates.validators.DnsNameValidator; import org.jclouds.rest.annotations.BinderParam; import org.jclouds.rest.annotations.Endpoint; @@ -131,9 +131,9 @@ public interface VCloudAsyncClient extends CommonVCloudAsyncClient { @GET @Consumes(MediaType.TEXT_XML) @Path("/ovf") - @XMLResponseParser(OvfEnvelopeHandler.class) + @XMLResponseParser(EnvelopeHandler.class) @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getOvfEnvelopeForVAppTemplate(@EndpointParam URI vAppTemplate); + ListenableFuture getOvfEnvelopeForVAppTemplate(@EndpointParam URI vAppTemplate); /** * @see VCloudClient#findVAppTemplateInOrgCatalogNamed diff --git a/apis/vcloud/src/main/java/org/jclouds/vcloud/VCloudClient.java b/apis/vcloud/src/main/java/org/jclouds/vcloud/VCloudClient.java index d1f5aca4c1..d74a8643c5 100644 --- a/apis/vcloud/src/main/java/org/jclouds/vcloud/VCloudClient.java +++ b/apis/vcloud/src/main/java/org/jclouds/vcloud/VCloudClient.java @@ -28,7 +28,7 @@ import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; import org.jclouds.concurrent.Timeout; -import org.jclouds.ovf.OvfEnvelope; +import org.jclouds.ovf.Envelope; import org.jclouds.vcloud.domain.GuestCustomizationSection; import org.jclouds.vcloud.domain.NetworkConnectionSection; import org.jclouds.vcloud.domain.ReferenceType; @@ -84,7 +84,7 @@ public interface VCloudClient extends CommonVCloudClient { VAppTemplate getVAppTemplate(URI vAppTemplate); - OvfEnvelope getOvfEnvelopeForVAppTemplate(URI vAppTemplate); + Envelope getOvfEnvelopeForVAppTemplate(URI vAppTemplate); /** * Modify the Guest Customization Section of a Virtual Machine diff --git a/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/functions/HardwareForVAppTemplate.java b/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/functions/HardwareForVAppTemplate.java index b26841ea12..f190e19771 100644 --- a/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/functions/HardwareForVAppTemplate.java +++ b/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/functions/HardwareForVAppTemplate.java @@ -28,7 +28,7 @@ import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.HardwareBuilder; import org.jclouds.compute.predicates.ImagePredicates; import org.jclouds.logging.Logger; -import org.jclouds.ovf.OvfEnvelope; +import org.jclouds.ovf.Envelope; import org.jclouds.ovf.VirtualHardwareSection; import org.jclouds.vcloud.VCloudClient; import org.jclouds.vcloud.domain.ReferenceType; @@ -73,19 +73,19 @@ public class HardwareForVAppTemplate implements Function return null; } - OvfEnvelope ovf = client.getOvfEnvelopeForVAppTemplate(from.getHref()); + Envelope ovf = client.getOvfEnvelopeForVAppTemplate(from.getHref()); if (ovf == null) { logger.warn("cannot parse hardware as no ovf envelope found for %s", from); return null; } - if (ovf.getVirtualSystem().getHardware().size() == 0) { + if (ovf.getVirtualSystem().getVirtualHardwareSections().size() == 0) { logger.warn("cannot parse hardware for %s as no hardware sections exist in ovf %s", ovf); return null; } - if (ovf.getVirtualSystem().getHardware().size() > 1) { + if (ovf.getVirtualSystem().getVirtualHardwareSections().size() > 1) { logger.warn("multiple hardware choices found. using first", ovf); } - VirtualHardwareSection hardware = Iterables.get(ovf.getVirtualSystem().getHardware(), 0); + VirtualHardwareSection hardware = Iterables.get(ovf.getVirtualSystem().getVirtualHardwareSections(), 0); HardwareBuilder builder = rasdToHardwareBuilder.apply(hardware.getResourceAllocations()); builder.location(findLocationForResource.apply(checkNotNull(parent, "parent"))); builder.ids(from.getHref().toASCIIString()).name(from.getName()).supportsImage( diff --git a/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/functions/ImageForVAppTemplate.java b/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/functions/ImageForVAppTemplate.java index d5ae785c4b..1fb5bb8ac9 100644 --- a/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/functions/ImageForVAppTemplate.java +++ b/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/functions/ImageForVAppTemplate.java @@ -27,7 +27,7 @@ import org.jclouds.compute.domain.CIMOperatingSystem; import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.ImageBuilder; import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy; -import org.jclouds.ovf.OvfEnvelope; +import org.jclouds.ovf.Envelope; import org.jclouds.vcloud.VCloudClient; import org.jclouds.vcloud.domain.ReferenceType; import org.jclouds.vcloud.domain.VAppTemplate; @@ -64,7 +64,7 @@ public class ImageForVAppTemplate implements Function { builder.name(from.getName()); builder.location(findLocationForResource.apply(checkNotNull(parent, "parent"))); builder.description(from.getDescription() != null ? from.getDescription() : from.getName()); - OvfEnvelope ovf = client.getOvfEnvelopeForVAppTemplate(from.getHref()); + Envelope ovf = client.getOvfEnvelopeForVAppTemplate(from.getHref()); builder.operatingSystem(CIMOperatingSystem.toComputeOs(ovf)); builder.defaultCredentials(credentialsProvider.execute(from)); return builder.build(); diff --git a/apis/vcloud/src/main/java/org/jclouds/vcloud/domain/ovf/VCloudVirtualHardwareSection.java b/apis/vcloud/src/main/java/org/jclouds/vcloud/domain/ovf/VCloudVirtualHardwareSection.java index e909cabb51..45c9ec3245 100644 --- a/apis/vcloud/src/main/java/org/jclouds/vcloud/domain/ovf/VCloudVirtualHardwareSection.java +++ b/apis/vcloud/src/main/java/org/jclouds/vcloud/domain/ovf/VCloudVirtualHardwareSection.java @@ -32,9 +32,10 @@ public class VCloudVirtualHardwareSection extends VirtualHardwareSection { protected final String type; protected final URI href; - public VCloudVirtualHardwareSection(String type, URI href, String info, VirtualSystemSettingData virtualSystem, + public VCloudVirtualHardwareSection(String type, URI href, String info, Iterable transports, + VirtualSystemSettingData virtualSystem, Iterable resourceAllocations) { - super(info, virtualSystem, resourceAllocations); + super(info, transports, virtualSystem, resourceAllocations); this.type = type; this.href = href; } diff --git a/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/VCloudVirtualHardwareHandler.java b/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/VCloudVirtualHardwareHandler.java index a4a0ac9782..63efc8c484 100644 --- a/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/VCloudVirtualHardwareHandler.java +++ b/apis/vcloud/src/main/java/org/jclouds/vcloud/xml/VCloudVirtualHardwareHandler.java @@ -50,7 +50,7 @@ public class VCloudVirtualHardwareHandler extends ParseSax.HandlerWithResult { assertPayloadEquals(request, null, null, false); assertResponseParserClassEquals(method, request, ParseSax.class); - assertSaxResponseParserClassEquals(method, OvfEnvelopeHandler.class); + assertSaxResponseParserClassEquals(method, EnvelopeHandler.class); assertExceptionParserClassEquals(method, ReturnNullOnNotFoundOr404.class); checkFilters(request); diff --git a/compute/src/main/java/org/jclouds/cim/SettingData.java b/compute/src/main/java/org/jclouds/cim/SettingData.java index 09ea7d70a0..130e026a6a 100644 --- a/compute/src/main/java/org/jclouds/cim/SettingData.java +++ b/compute/src/main/java/org/jclouds/cim/SettingData.java @@ -31,7 +31,7 @@ import static com.google.common.base.Preconditions.checkNotNull; * /> * */ -public abstract class SettingData { +public abstract class SettingData implements Comparable { public static Builder builder() { return new Builder(); @@ -123,4 +123,14 @@ public abstract class SettingData { return String.format("[elementName=%s, instanceID=%s]", elementName, instanceID); } + /** + * {@inheritDoc} + */ + @Override + public int compareTo(SettingData o) { + if (instanceID == null) + return -1; + return (this == o) ? 0 : instanceID.compareTo(o.instanceID); + } + } \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/compute/domain/CIMOperatingSystem.java b/compute/src/main/java/org/jclouds/compute/domain/CIMOperatingSystem.java index a973bb2b84..acd4d30519 100644 --- a/compute/src/main/java/org/jclouds/compute/domain/CIMOperatingSystem.java +++ b/compute/src/main/java/org/jclouds/compute/domain/CIMOperatingSystem.java @@ -22,7 +22,7 @@ package org.jclouds.compute.domain; import javax.annotation.Nullable; import org.jclouds.cim.OSType; -import org.jclouds.ovf.OvfEnvelope; +import org.jclouds.ovf.Envelope; import com.google.common.annotations.Beta; @@ -123,8 +123,8 @@ public class CIMOperatingSystem extends OperatingSystem { return new CIMOperatingSystem(OSType.fromValue(os.getId()), "", null, os.getDescription()); } - public static CIMOperatingSystem toComputeOs(OvfEnvelope ovf) { - return toComputeOs(ovf.getVirtualSystem().getOperatingSystem()); + public static CIMOperatingSystem toComputeOs(Envelope ovf) { + return toComputeOs(ovf.getVirtualSystem().getOperatingSystemSection()); } private OSType osType; diff --git a/compute/src/main/java/org/jclouds/ovf/Configuration.java b/compute/src/main/java/org/jclouds/ovf/Configuration.java new file mode 100644 index 0000000000..157970d2cf --- /dev/null +++ b/compute/src/main/java/org/jclouds/ovf/Configuration.java @@ -0,0 +1,120 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.ovf; + +/** + * + * @author Adrian Cole + */ +public class Configuration { + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + protected String id; + protected String label; + protected String description; + + /** + * @see Configuration#getId + */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** + * @see Section#getLabel + */ + public Builder label(String label) { + this.label = label; + return this; + } + + /** + * @see Section#getDescription + */ + public Builder description(String description) { + this.description = description; + return this; + } + + public Configuration build() { + return new Configuration(id, label, description); + } + + public Builder fromNetwork(Configuration in) { + return id(in.getId()).description(in.getDescription()).label(in.getLabel()); + } + } + + private final String id; + private final String label; + private final String description; + + public Configuration(String id, String label, String description) { + this.id = id; + this.label = label; + this.description = description; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Configuration other = (Configuration) obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + return true; + } + + @Override + public String toString() { + return String.format("Configuration [id=%s, label=%s, description=%s]", id, label, description); + } + + public String getId() { + return id; + } + + public String getDescription() { + return description; + } + + public String getLabel() { + return label; + } +} \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/ovf/DeploymentOptionSection.java b/compute/src/main/java/org/jclouds/ovf/DeploymentOptionSection.java new file mode 100644 index 0000000000..88308b5fbe --- /dev/null +++ b/compute/src/main/java/org/jclouds/ovf/DeploymentOptionSection.java @@ -0,0 +1,144 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.ovf; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Set; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; + +/** + * The DeploymentOptionSection specifies a discrete set of intended resource configurations. The + * author of an OVF package can include sizing metadata for different configurations. A consumer of + * the OVF shall select a configuration, for example, by prompting the user. The selected + * configuration is visible in the OVF environment, enabling guest software to adapt to the selected + * configuration. + * + * @author Adrian Cole + */ +public class DeploymentOptionSection extends Section { + + @SuppressWarnings("unchecked") + public static Builder builder() { + return new Builder(); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder toBuilder() { + return builder().fromDeploymentOptionSection(this); + } + + public static class Builder extends Section.Builder { + protected Set configurations = Sets.newLinkedHashSet(); + + /** + * @see DeploymentOptionSection#getConfigurations + */ + public Builder configuration(Configuration configuration) { + this.configurations.add(checkNotNull(configuration, "configuration")); + return this; + } + + /** + * @see DeploymentOptionSection#getConfigurations + */ + public Builder configurations(Iterable configurations) { + this.configurations = ImmutableSet. copyOf(checkNotNull(configurations, "configurations")); + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public DeploymentOptionSection build() { + return new DeploymentOptionSection(info, configurations); + } + + public Builder fromDeploymentOptionSection(DeploymentOptionSection in) { + return info(in.getInfo()).configurations(in.getConfigurations()); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder fromSection(Section in) { + return Builder.class.cast(super.fromSection(in)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder info(String info) { + return Builder.class.cast(super.info(info)); + } + + } + + protected final Set configurations; + + public DeploymentOptionSection(String info, Iterable configurations) { + super(info); + this.configurations = ImmutableSet. copyOf(checkNotNull(configurations, "configurations")); + + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((configurations == null) ? 0 : configurations.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + DeploymentOptionSection other = (DeploymentOptionSection) obj; + if (configurations == null) { + if (other.configurations != null) + return false; + } else if (!configurations.equals(other.configurations)) + return false; + return true; + } + + @Override + public String toString() { + return String.format("[info=%s, configurations=%s]", info, configurations); + } + + public Set getConfigurations() { + return configurations; + } + +} \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/ovf/Disk.java b/compute/src/main/java/org/jclouds/ovf/Disk.java new file mode 100644 index 0000000000..e93a1545e2 --- /dev/null +++ b/compute/src/main/java/org/jclouds/ovf/Disk.java @@ -0,0 +1,237 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.ovf; + +import java.net.URI; + +/** + * + * @author Adrian Cole + */ +public class Disk implements Comparable{ + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String id; + private Long capacity; + private String parentRef; + private String fileRef; + private URI format; + private Long populatedSize; + private String capacityAllocationUnits; + + /** + * @see Disk#getId + */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** + * @see Disk#getCapacity + */ + public Builder capacity(Long capacity) { + this.capacity = capacity; + return this; + } + + /** + * @see Disk#getParentRef + */ + public Builder parentRef(String parentRef) { + this.parentRef = parentRef; + return this; + } + + /** + * @see Disk#getFileRef + */ + public Builder fileRef(String fileRef) { + this.fileRef = fileRef; + return this; + } + + /** + * @see Disk#getFormat + */ + public Builder format(URI format) { + this.format = format; + return this; + } + + /** + * @see Disk#getPopulatedSize + */ + public Builder populatedSize(Long populatedSize) { + this.populatedSize = populatedSize; + return this; + } + + /** + * @see Disk#getCapacityAllocationUnits + */ + public Builder capacityAllocationUnits(String capacityAllocationUnits) { + this.capacityAllocationUnits = capacityAllocationUnits; + return this; + } + + public Disk build() { + return new Disk(id, capacity, parentRef, fileRef, format, populatedSize, capacityAllocationUnits); + } + + public Builder fromDisk(Disk in) { + return id(in.getId()).capacity(in.getCapacity()).parentRef(in.getParentRef()).fileRef(in.getFileRef()).format( + in.getFormat()).populatedSize(in.getPopulatedSize()).capacityAllocationUnits( + in.getCapacityAllocationUnits()); + } + } + + private final String id; + private final Long capacity; + private final String parentRef; + private final String fileRef; + private final URI format; + private final Long populatedSize; + private final String capacityAllocationUnits; + + public Disk(String id, Long capacity, String parentRef, String fileRef, URI format, Long populatedSize, + String capacityAllocationUnits) { + this.id = id; + this.capacity = capacity; + this.parentRef = parentRef; + this.fileRef = fileRef; + this.format = format; + this.populatedSize = populatedSize; + this.capacityAllocationUnits = capacityAllocationUnits; + } + + /** + * Each virtual disk is represented by a Disk element that shall be given a identifier using the + * {@code id} attribute, the identifier shall be unique within the {@link DiskSection}. + */ + public String getId() { + return id; + } + + /** + * The capacity of a virtual disk shall be specified by the {@code capacity} attribute with an + * xs:long integer value. The default unit of allocation shall be bytes. + */ + public Long getCapacity() { + return capacity; + } + + /** + * OVF allows a disk image to be represented as a set of modified blocks in comparison to a + * parent image. The use of parent disks can often significantly reduce the size of an OVF + * package, if it contains multiple disks with similar content. For a Disk element, a parent disk + * may optionally be specified using the {@code parentRef} attribute, which shall contain a valid + * ovf:id reference to a different Disk element. If a disk block does not exist locally, lookup + * for that disk block then occurs in the parent disk. In {@link DiskSection}, parent Disk + * elements shall occur before child Disk elements that refer to them. + */ + public String getParentRef() { + return parentRef; + } + + /** + * The ovf:fileRef attribute denotes the virtual disk content by identifying an existing File + * element in the References element, the File element is identified by matching its {@code id} + * attribute value with the {@code fileRef} attribute value. Omitting the {@code fileRef} + * attribute shall indicate an empty disk. In this case, the disk shall be created and the entire + * disk content zeroed at installation time. The guest software will typically format empty disks + * in some file system format. + */ + public String getFileRef() { + return fileRef; + } + + /** + * The format URI of a non-empty virtual disk shall be specified by the {@code format} attribute. + */ + public URI getFormat() { + return format; + } + + /** + * For non-empty disks, the actual used size of the disk may optionally be specified using the + * {@code populatedSize} attribute. The unit of this attribute is always bytes. {@code + * populatedSize} is allowed to be an estimate of used disk size but shall not be larger than + * {@code capacity}. + */ + public Long getPopulatedSize() { + return populatedSize; + } + + /** + * The optional string attribute {@code ovf:capacityAllocationUnits} may be used to specify a + * particular unit of allocation. Values for {@code ovf:capacityAllocationUnits} shall match the + * format for programmatic units defined in DSP0004. + */ + public String getCapacityAllocationUnits() { + return capacityAllocationUnits; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Disk other = (Disk) obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + return true; + } + + @Override + public String toString() { + return String + .format( + "[id=%s, capacity=%s, capacityAllocationUnits=%s, fileRef=%s, format=%s, parentRef=%s, populatedSize=%s]", + id, capacity, capacityAllocationUnits, fileRef, format, parentRef, populatedSize); + } + + /** + * {@inheritDoc} + */ + @Override + public int compareTo(Disk o) { + if (id == null) + return -1; + return (this == o) ? 0 : id.compareTo(o.id); + } +} \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/ovf/DiskSection.java b/compute/src/main/java/org/jclouds/ovf/DiskSection.java new file mode 100644 index 0000000000..45900a564d --- /dev/null +++ b/compute/src/main/java/org/jclouds/ovf/DiskSection.java @@ -0,0 +1,153 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.ovf; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Set; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; + +/** + * A DiskSection describes meta-information about virtual disks in the OVF package. Virtual disks + * and their metadata are described outside the virtual hardware to facilitate sharing between + * virtual machines within an OVF package. + * + * @author Adrian Cole + */ +public class DiskSection extends Section { + + @SuppressWarnings("unchecked") + public static Builder builder() { + return new Builder(); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder toBuilder() { + return new Builder().fromDiskSection(this); + } + + public static class Builder extends Section.Builder { + protected Set disks = Sets.newLinkedHashSet(); + + /** + * @see DiskSection#getDisks + */ + public Builder disk(Disk disk) { + this.disks.add(checkNotNull(disk, "disk")); + return this; + } + + /** + * @see DiskSection#getDisks + */ + public Builder disks(Iterable disks) { + this.disks = ImmutableSet. copyOf(checkNotNull(disks, "disks")); + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public DiskSection build() { + return new DiskSection(info, disks); + } + + public Builder fromDiskSection(DiskSection in) { + return disks(in.getDisks()).info(in.getInfo()); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder fromSection(Section in) { + return (Builder) super.fromSection(in); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder info(String info) { + return (Builder) super.info(info); + } + + } + + private final Set disks; + + public DiskSection(String info, Iterable disks) { + super(info); + this.disks = ImmutableSet. copyOf(checkNotNull(disks, "disks")); + } + + /** + * All disks referred to from Connection elements in all {@link VirtualHardwareSection} elements + * shall be defined in the DiskSection. + * + * @return + */ + public Set getDisks() { + return disks; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((info == null) ? 0 : info.hashCode()); + result = prime * result + ((disks == null) ? 0 : disks.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + DiskSection other = (DiskSection) obj; + if (info == null) { + if (other.info != null) + return false; + } else if (!info.equals(other.info)) + return false; + if (disks == null) { + if (other.disks != null) + return false; + } else if (!disks.equals(other.disks)) + return false; + return true; + } + + @Override + public String toString() { + return String.format("[info=%s, disks=%s]", info, disks); + } + +} \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/ovf/Envelope.java b/compute/src/main/java/org/jclouds/ovf/Envelope.java new file mode 100644 index 0000000000..42f52c626c --- /dev/null +++ b/compute/src/main/java/org/jclouds/ovf/Envelope.java @@ -0,0 +1,205 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.ovf; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Set; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; + +/** + * @author Adrian Cole + */ +public class Envelope { + + public static Builder builder() { + return new Builder(); + } + + /** + * {@inheritDoc} + */ + public Builder toBuilder() { + return new Builder().fromEnvelope(this); + } + + public static class Builder { + protected Set diskSections = Sets.newLinkedHashSet(); + protected Set networkSections = Sets.newLinkedHashSet(); + @SuppressWarnings("unchecked") + protected Set
additionalSections = Sets.newLinkedHashSet(); + protected VirtualSystem virtualSystem; + + /** + * @see Envelope#getDiskSections + */ + public Builder diskSection(DiskSection diskSection) { + this.diskSections.add(checkNotNull(diskSection, "diskSection")); + return this; + } + + /** + * @see Envelope#getDiskSections + */ + public Builder diskSections(Iterable diskSections) { + this.diskSections = ImmutableSet. copyOf(checkNotNull(diskSections, "diskSections")); + return this; + } + + /** + * @see Envelope#getNetworkSections + */ + public Builder networkSection(NetworkSection networkSection) { + this.networkSections.add(checkNotNull(networkSection, "networkSection")); + return this; + } + + /** + * @see Envelope#getNetworkSections + */ + public Builder networkSections(Iterable networkSections) { + this.networkSections = ImmutableSet. copyOf(checkNotNull(networkSections, "networkSections")); + return this; + } + + /** + * @see Envelope#getAdditionalSections + */ + @SuppressWarnings("unchecked") + public Builder additionalSection(Section additionalSection) { + this.additionalSections.add(checkNotNull(additionalSection, "additionalSection")); + return this; + } + + /** + * @see Envelope#getAdditionalSections + */ + @SuppressWarnings("unchecked") + public Builder additionalSections(Iterable additionalSections) { + this.additionalSections = ImmutableSet + .
copyOf(checkNotNull(additionalSections, "additionalSections")); + return this; + } + + /** + * @see Envelope#getVirtualSystem + */ + public Builder virtualSystem(VirtualSystem virtualSystem) { + this.virtualSystem = virtualSystem; + return this; + } + + /** + * {@inheritDoc} + */ + public Envelope build() { + return new Envelope(diskSections, networkSections, additionalSections, virtualSystem); + } + + public Builder fromEnvelope(Envelope in) { + return virtualSystem(in.getVirtualSystem()).diskSections(in.getDiskSections()).networkSections( + networkSections).additionalSections(in.getAdditionalSections()); + } + + } + + private final Set diskSections; + private final Set networkSections; + @SuppressWarnings("unchecked") + private final Set additionalSections; + private final VirtualSystem virtualSystem; + + @SuppressWarnings("unchecked") + public Envelope(Iterable diskSections, Iterable networkSections, + Iterable additionalSections, VirtualSystem virtualSystem) { + this.diskSections = ImmutableSet.copyOf(checkNotNull(diskSections, "diskSections")); + this.networkSections = ImmutableSet.copyOf(checkNotNull(networkSections, "networkSections")); + this.additionalSections = ImmutableSet.copyOf(checkNotNull(additionalSections, "additionalSections")); + this.virtualSystem = checkNotNull(virtualSystem, "virtualSystem"); + } + + public VirtualSystem getVirtualSystem() { + return virtualSystem; + } + + public Set getDiskSections() { + return diskSections; + } + + @SuppressWarnings("unchecked") + public Set getAdditionalSections() { + return additionalSections; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((additionalSections == null) ? 0 : additionalSections.hashCode()); + result = prime * result + ((diskSections == null) ? 0 : diskSections.hashCode()); + result = prime * result + ((networkSections == null) ? 0 : networkSections.hashCode()); + result = prime * result + ((virtualSystem == null) ? 0 : virtualSystem.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Envelope other = (Envelope) obj; + if (additionalSections == null) { + if (other.additionalSections != null) + return false; + } else if (!additionalSections.equals(other.additionalSections)) + return false; + if (diskSections == null) { + if (other.diskSections != null) + return false; + } else if (!diskSections.equals(other.diskSections)) + return false; + if (networkSections == null) { + if (other.networkSections != null) + return false; + } else if (!networkSections.equals(other.networkSections)) + return false; + if (virtualSystem == null) { + if (other.virtualSystem != null) + return false; + } else if (!virtualSystem.equals(other.virtualSystem)) + return false; + return true; + } + + @Override + public String toString() { + return String.format("[diskSections=%s, networkSections=%s, additionalSections=%s, virtualSystem=%s]", + diskSections, networkSections, additionalSections, virtualSystem); + } + + public Set getNetworkSections() { + return networkSections; + } +} \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/ovf/Network.java b/compute/src/main/java/org/jclouds/ovf/Network.java index 2012350414..8952d3f59d 100644 --- a/compute/src/main/java/org/jclouds/ovf/Network.java +++ b/compute/src/main/java/org/jclouds/ovf/Network.java @@ -1,6 +1,6 @@ /** * - * Copyright (C) 2010 Cloud Conscious, LLC. + * Copyright (C) 2010 Cloud Conscious, LLC. * * ==================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,11 +19,45 @@ package org.jclouds.ovf; + /** * * @author Adrian Cole */ public class Network { + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + protected String name; + protected String description; + + /** + * @see Network#getName + */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** + * @see Section#getDescription + */ + public Builder description(String description) { + this.description = description; + return this; + } + + public Network build() { + return new Network(name, description); + } + + public Builder fromNetwork(Network in) { + return name(in.getName()).description(in.getDescription()); + } + } + private final String name; private final String description; @@ -65,7 +99,7 @@ public class Network { @Override public String toString() { - return "Network [name=" + name + ", description=" + description + "]"; + return "[name=" + name + ", description=" + description + "]"; } public String getName() { diff --git a/compute/src/main/java/org/jclouds/ovf/NetworkSection.java b/compute/src/main/java/org/jclouds/ovf/NetworkSection.java index 35f2520ec5..4906b9bebe 100644 --- a/compute/src/main/java/org/jclouds/ovf/NetworkSection.java +++ b/compute/src/main/java/org/jclouds/ovf/NetworkSection.java @@ -19,31 +19,92 @@ package org.jclouds.ovf; +import static com.google.common.base.Preconditions.checkNotNull; + import java.util.Set; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; /** * The NetworkSection element shall list all logical networks used in the OVF package. * * @author Adrian Cole */ -public class NetworkSection { - private final String info; - private final Set networks; +public class NetworkSection extends Section { - public NetworkSection(String info, Iterable networks) { - this.info = info; - this.networks = ImmutableSet. copyOf(networks); - } - - public String getInfo() { - return info; + @SuppressWarnings("unchecked") + public static Builder builder() { + return new Builder(); } /** - * All networks referred to from Connection elements in all {@link VirtualHardwareSection} elements shall - * be defined in the NetworkSection. + * {@inheritDoc} + */ + @Override + public Builder toBuilder() { + return builder().fromNetworkSection(this); + } + + public static class Builder extends Section.Builder { + protected Set networks = Sets.newLinkedHashSet(); + + /** + * @see NetworkSection#getNetworks + */ + public Builder network(Network network) { + this.networks.add(checkNotNull(network, "network")); + return this; + } + + /** + * @see NetworkSection#getNetworks + */ + public Builder networks(Iterable networks) { + this.networks = ImmutableSet. copyOf(checkNotNull(networks, "networks")); + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public NetworkSection build() { + return new NetworkSection(info, networks); + } + + public Builder fromNetworkSection(NetworkSection in) { + return networks(in.getNetworks()).info(in.getInfo()); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder fromSection(Section in) { + return Builder.class.cast(super.fromSection(in)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder info(String info) { + return Builder.class.cast(super.info(info)); + } + + } + + private final Set networks; + + public NetworkSection(String info, Iterable networks) { + super(info); + this.networks = ImmutableSet. copyOf(checkNotNull(networks, "networks")); + } + + /** + * All networks referred to from Connection elements in all {@link VirtualHardwareSection} + * elements shall be defined in the NetworkSection. * * @return */ @@ -84,7 +145,7 @@ public class NetworkSection { @Override public String toString() { - return "[info=" + info + ", networks=" + networks + "]"; + return String.format("[info=%s, networks=%s]", info, networks); } } \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/ovf/OperatingSystemSection.java b/compute/src/main/java/org/jclouds/ovf/OperatingSystemSection.java index c8eaaa4d20..61db546a96 100644 --- a/compute/src/main/java/org/jclouds/ovf/OperatingSystemSection.java +++ b/compute/src/main/java/org/jclouds/ovf/OperatingSystemSection.java @@ -28,15 +28,23 @@ import org.jclouds.cim.OSType; * * @author Adrian Cole */ -public class OperatingSystemSection { +public class OperatingSystemSection extends Section { + @SuppressWarnings("unchecked") public static Builder builder() { return new Builder(); } - public static class Builder { + /** + * {@inheritDoc} + */ + @Override + public Builder toBuilder() { + return builder().fromOperatingSystemSection(this); + } + + public static class Builder extends Section.Builder { protected Integer id; - protected String info; protected String description; /** @@ -47,14 +55,6 @@ public class OperatingSystemSection { return this; } - /** - * @see OperatingSystemSection#getInfo - */ - public Builder info(String info) { - this.info = info; - return this; - } - /** * @see OperatingSystemSection#getDescription */ @@ -63,6 +63,10 @@ public class OperatingSystemSection { return this; } + /** + * {@inheritDoc} + */ + @Override public OperatingSystemSection build() { return new OperatingSystemSection(id, info, description); } @@ -70,15 +74,31 @@ public class OperatingSystemSection { public Builder fromOperatingSystemSection(OperatingSystemSection in) { return id(in.getId()).info(in.getInfo()).description(in.getDescription()); } + + /** + * {@inheritDoc} + */ + @Override + public Builder fromSection(Section in) { + return Builder.class.cast(super.fromSection(in)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder info(String info) { + return Builder.class.cast(super.info(info)); + } + } protected final Integer id; - protected final String info; protected final String description; public OperatingSystemSection(@Nullable Integer id, @Nullable String info, @Nullable String description) { + super(info); this.id = id; - this.info = info; this.description = description; } @@ -91,14 +111,6 @@ public class OperatingSystemSection { return id; } - /** - * - * @return ovf info - */ - public String getInfo() { - return info; - } - /** * * @return description or null @@ -144,13 +156,9 @@ public class OperatingSystemSection { return true; } - public Builder toBuilder() { - return builder().fromOperatingSystemSection(this); - } - @Override public String toString() { - return "[id=" + getId() + ", info=" + getInfo() + ", description=" + getDescription() + "]"; + return String.format("[info=%s, id=%s, description=%s]", info, id, description); } } \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/ovf/OvfEnvelope.java b/compute/src/main/java/org/jclouds/ovf/Section.java similarity index 52% rename from compute/src/main/java/org/jclouds/ovf/OvfEnvelope.java rename to compute/src/main/java/org/jclouds/ovf/Section.java index b4527e61e8..c6d0c12bab 100644 --- a/compute/src/main/java/org/jclouds/ovf/OvfEnvelope.java +++ b/compute/src/main/java/org/jclouds/ovf/Section.java @@ -19,29 +19,62 @@ package org.jclouds.ovf; -import static com.google.common.base.Preconditions.checkNotNull; +import javax.annotation.Nullable; /** - * + * Metadata about a virtual machine or grouping of them * * @author Adrian Cole */ -public class OvfEnvelope { - private final VirtualSystem virtualSystem; +public class Section> { - public OvfEnvelope(VirtualSystem virtualSystem) { - this.virtualSystem = checkNotNull(virtualSystem, "virtualSystem"); + public static > Builder builder() { + return new Builder(); } - public VirtualSystem getVirtualSystem() { - return virtualSystem; + public Builder toBuilder() { + return new Builder().fromSection(this); + } + + public static class Builder> { + protected String info; + + /** + * @see Section#getInfo + */ + public Builder info(String info) { + this.info = info; + return this; + } + + public Section build() { + return new Section(info); + } + + public Builder fromSection(Section in) { + return info(in.getInfo()); + } + } + + protected final String info; + + public Section(@Nullable String info) { + this.info = info; + } + + /** + * + * @return ovf info + */ + public String getInfo() { + return info; } @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((virtualSystem == null) ? 0 : virtualSystem.hashCode()); + result = prime * result + ((info == null) ? 0 : info.hashCode()); return result; } @@ -53,17 +86,18 @@ public class OvfEnvelope { return false; if (getClass() != obj.getClass()) return false; - OvfEnvelope other = (OvfEnvelope) obj; - if (virtualSystem == null) { - if (other.virtualSystem != null) + Section other = (Section) obj; + if (info == null) { + if (other.info != null) return false; - } else if (!virtualSystem.equals(other.virtualSystem)) + } else if (!info.equals(other.info)) return false; return true; } @Override public String toString() { - return "[virtualSystem=" + virtualSystem + "]"; + return "[info=" + getInfo() + "]"; } + } \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/ovf/VirtualHardwareSection.java b/compute/src/main/java/org/jclouds/ovf/VirtualHardwareSection.java index ffb0d6749b..7c6ad39551 100644 --- a/compute/src/main/java/org/jclouds/ovf/VirtualHardwareSection.java +++ b/compute/src/main/java/org/jclouds/ovf/VirtualHardwareSection.java @@ -27,30 +27,141 @@ import org.jclouds.cim.ResourceAllocationSettingData; import org.jclouds.cim.VirtualSystemSettingData; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; /** - * * The virtual hardware required by a virtual machine is specified in VirtualHardwareSection. *

* This specification supports abstract or incomplete hardware descriptions in which only the major * devices are described. The hypervisor is allowed to create additional virtual hardware * controllers and devices, as long as the required devices listed in the descriptor are realized. + * + * @author Adrian Cole */ -public class VirtualHardwareSection { +public class VirtualHardwareSection extends Section { - protected final String info; - protected final VirtualSystemSettingData virtualSystem; - protected final Set resourceAllocations; - - public VirtualHardwareSection(String info, VirtualSystemSettingData virtualSystem, - Iterable resourceAllocations) { - this.info = info; - this.virtualSystem = virtualSystem; - this.resourceAllocations = ImmutableSet.copyOf(checkNotNull(resourceAllocations, "resourceAllocations")); + @SuppressWarnings("unchecked") + public static Builder builder() { + return new Builder(); } - public String getInfo() { - return info; + /** + * {@inheritDoc} + */ + @Override + public Builder toBuilder() { + return builder().fromVirtualHardwareSection(this); + } + + public static class Builder extends Section.Builder { + protected VirtualSystemSettingData virtualSystem; + protected Set transports = Sets.newLinkedHashSet(); + protected Set resourceAllocations = Sets.newLinkedHashSet(); + + /** + * @see VirtualHardwareSection#getSystem + */ + public Builder system(VirtualSystemSettingData virtualSystem) { + this.virtualSystem = virtualSystem; + return this; + } + + /** + * @see VirtualHardwareSection#getTransports + */ + public Builder transport(String transport) { + this.transports.add(checkNotNull(transport, "transport")); + return this; + } + + /** + * @see VirtualHardwareSection#getTransports + */ + public Builder transports(Iterable transports) { + this.transports = ImmutableSet. copyOf(checkNotNull(transports, "transports")); + return this; + } + + /** + * @see VirtualHardwareSection#getResourceAllocations + */ + public Builder resourceAllocation(ResourceAllocationSettingData resourceAllocation) { + this.resourceAllocations.add(checkNotNull(resourceAllocation, "resourceAllocation")); + return this; + } + + /** + * @see VirtualHardwareSection#getResourceAllocations + */ + public Builder resourceAllocations(Iterable resourceAllocations) { + this.resourceAllocations = ImmutableSet. copyOf(checkNotNull( + resourceAllocations, "resourceAllocations")); + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public VirtualHardwareSection build() { + return new VirtualHardwareSection(info, transports, virtualSystem, resourceAllocations); + } + + public Builder fromVirtualHardwareSection(VirtualHardwareSection in) { + return resourceAllocations(in.getResourceAllocations()).transports(in.getTransports()).system( + in.getSystem()).info(in.getInfo()); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder fromSection(Section in) { + return Builder.class.cast(super.fromSection(in)); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder info(String info) { + return Builder.class.cast(super.info(info)); + } + + } + + protected final VirtualSystemSettingData virtualSystem; + protected final Set transports; + protected final Set resourceAllocations; + + public VirtualHardwareSection(String info, Iterable transports, VirtualSystemSettingData virtualSystem, + Iterable resourceAllocations) { + super(info); + this.virtualSystem = virtualSystem; + this.transports = ImmutableSet. copyOf(checkNotNull(transports, "transports")); + this.resourceAllocations = ImmutableSet. copyOf(checkNotNull(resourceAllocations, + "resourceAllocations")); + } + + /** + * transport types define methods by which the environment document is communicated from the + * deployment platform to the guest software. + *

+ * To enable interoperability, this specification defines an "iso" transport type which all + * implementations that support CD-ROM devices are required to support. The iso transport + * communicates the environment 1346 document by making a dynamically generated ISO image + * available to the guest software. To support the iso transport type, prior to booting a virtual + * machine, an implementation shall make an ISO 9660 read-only disk image available as backing + * for a disconnected CD-ROM. If the iso transport is selected for a VirtualHardwareSection, at + * least one disconnected CD-ROM device shall be present in this section. + *

+ * Support for the "iso" transport type is not a requirement for virtual hardware architectures + * or guest 1351 operating systems which do not have CD-ROM device support. + * + * @return + */ + public Set getTransports() { + return transports; } public VirtualSystemSettingData getSystem() { @@ -61,17 +172,12 @@ public class VirtualHardwareSection { return resourceAllocations; } - @Override - public String toString() { - return "[info=" + getInfo() + ", virtualSystem=" + getSystem() + "]"; - } - @Override public int hashCode() { final int prime = 31; - int result = 1; - result = prime * result + ((info == null) ? 0 : info.hashCode()); + int result = super.hashCode(); result = prime * result + ((resourceAllocations == null) ? 0 : resourceAllocations.hashCode()); + result = prime * result + ((transports == null) ? 0 : transports.hashCode()); result = prime * result + ((virtualSystem == null) ? 0 : virtualSystem.hashCode()); return result; } @@ -80,21 +186,21 @@ public class VirtualHardwareSection { public boolean equals(Object obj) { if (this == obj) return true; - if (obj == null) + if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; VirtualHardwareSection other = (VirtualHardwareSection) obj; - if (info == null) { - if (other.info != null) - return false; - } else if (!info.equals(other.info)) - return false; if (resourceAllocations == null) { if (other.resourceAllocations != null) return false; } else if (!resourceAllocations.equals(other.resourceAllocations)) return false; + if (transports == null) { + if (other.transports != null) + return false; + } else if (!transports.equals(other.transports)) + return false; if (virtualSystem == null) { if (other.virtualSystem != null) return false; @@ -103,4 +209,10 @@ public class VirtualHardwareSection { return true; } + @Override + public String toString() { + return String.format("[info=%s, resourceAllocations=%s, transports=%s, virtualSystem=%s]", info, + resourceAllocations, transports, virtualSystem); + } + } \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/ovf/VirtualSystem.java b/compute/src/main/java/org/jclouds/ovf/VirtualSystem.java index 2ef005430e..15b810e188 100644 --- a/compute/src/main/java/org/jclouds/ovf/VirtualSystem.java +++ b/compute/src/main/java/org/jclouds/ovf/VirtualSystem.java @@ -23,63 +23,175 @@ import static com.google.common.base.Preconditions.checkNotNull; import java.util.Set; - - -import com.google.common.collect.Iterables; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; /** * @author Adrian Cole */ -public class VirtualSystem { +public class VirtualSystem extends Section { + + @SuppressWarnings("unchecked") + public static Builder builder() { + return new Builder(); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder toBuilder() { + return new Builder().fromVirtualSystem(this); + } + + public static class Builder extends Section.Builder { + protected String id; + protected String name; + protected OperatingSystemSection operatingSystem; + protected Set hardwareSections = Sets.newLinkedHashSet(); + @SuppressWarnings("unchecked") + protected Set

additionalSections = Sets.newLinkedHashSet(); + + /** + * @see VirtualSystem#getName + */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** + * @see VirtualSystem#getId + */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** + * @see VirtualSystem#getOperatingSystemSection + */ + public Builder operatingSystemSection(OperatingSystemSection operatingSystem) { + this.operatingSystem = operatingSystem; + return this; + } + + /** + * @see VirtualSystem#getVirtualHardwareSections + */ + public Builder hardwareSection(VirtualHardwareSection hardwareSection) { + this.hardwareSections.add(checkNotNull(hardwareSection, "hardwareSection")); + return this; + } + + /** + * @see VirtualSystem#getVirtualHardwareSections + */ + public Builder hardwareSections(Iterable hardwareSections) { + this.hardwareSections = ImmutableSet. copyOf(checkNotNull(hardwareSections, + "hardwareSections")); + return this; + } + + /** + * @see VirtualSystem#getAdditionalSections + */ + @SuppressWarnings("unchecked") + public Builder additionalSection(Section additionalSection) { + this.additionalSections.add(checkNotNull(additionalSection, "additionalSection")); + return this; + } + + /** + * @see VirtualSystem#getAdditionalSections + */ + @SuppressWarnings("unchecked") + public Builder additionalSections(Iterable additionalSections) { + this.additionalSections = ImmutableSet + .
copyOf(checkNotNull(additionalSections, "additionalSections")); + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public VirtualSystem build() { + return new VirtualSystem(id, info, name, operatingSystem, hardwareSections, additionalSections); + } + + public Builder fromVirtualSystem(VirtualSystem in) { + return fromSection(in).id(in.getId()).name(in.getName()) + .operatingSystemSection(in.getOperatingSystemSection()).hardwareSections( + in.getVirtualHardwareSections()).additionalSections(in.getAdditionalSections()); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder fromSection(Section in) { + return (Builder) super.fromSection(in); + } + + /** + * {@inheritDoc} + */ + @Override + public Builder info(String info) { + return (Builder) super.info(info); + } + + } + private final String id; - private final String info; private final String name; private final OperatingSystemSection operatingSystem; - private final Set hardware = Sets.newLinkedHashSet(); + private final Set hardwareSections; + @SuppressWarnings("unchecked") + private final Set additionalSections; + @SuppressWarnings("unchecked") public VirtualSystem(String id, String info, String name, OperatingSystemSection operatingSystem, - Iterable hardware) { + Iterable hardwareSections, Iterable additionalSections) { + super(info); this.id = id; - this.info = info; this.name = name; this.operatingSystem = checkNotNull(operatingSystem, "operatingSystem"); - Iterables.addAll(this.hardware, checkNotNull(hardware, "hardware")); + this.hardwareSections = ImmutableSet.copyOf(checkNotNull(hardwareSections, "hardwareSections")); + this.additionalSections = ImmutableSet.copyOf(checkNotNull(additionalSections, "additionalSections")); } public String getId() { return id; } - public String getInfo() { - return info; - } - public String getName() { return name; } - public OperatingSystemSection getOperatingSystem() { + public OperatingSystemSection getOperatingSystemSection() { return operatingSystem; } /** * Each VirtualSystem element may contain one or more VirtualHardwareSection elements, each of - * which describes the virtual hardware required by the virtual system. + * which describes the virtual hardwareSections required by the virtual system. * */ - public Set getHardware() { - return hardware; + public Set getVirtualHardwareSections() { + return hardwareSections; + } + + @SuppressWarnings("unchecked") + public Set getAdditionalSections() { + return additionalSections; } @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((hardware == null) ? 0 : hardware.hashCode()); result = prime * result + ((id == null) ? 0 : id.hashCode()); - result = prime * result + ((info == null) ? 0 : info.hashCode()); - result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + ((operatingSystem == null) ? 0 : operatingSystem.hashCode()); return result; } @@ -92,37 +204,17 @@ public class VirtualSystem { if (getClass() != obj.getClass()) return false; VirtualSystem other = (VirtualSystem) obj; - if (hardware == null) { - if (other.hardware != null) - return false; - } else if (!hardware.equals(other.hardware)) - return false; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; - if (info == null) { - if (other.info != null) - return false; - } else if (!info.equals(other.info)) - return false; - if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - if (operatingSystem == null) { - if (other.operatingSystem != null) - return false; - } else if (!operatingSystem.equals(other.operatingSystem)) - return false; return true; } @Override public String toString() { - return "[id=" + getId() + ", name=" + getName() + ", info=" + getInfo() + ", os=" + getOperatingSystem() - + ", hardware=" + getHardware() + "]"; + return String.format("[id=%s, name=%s, info=%s, operatingSystem=%s, hardwareSections=%s, additionalSections=%s]", + id, name, info, operatingSystem, hardwareSections, additionalSections); } } \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/ovf/xml/DeploymentOptionSectionHandler.java b/compute/src/main/java/org/jclouds/ovf/xml/DeploymentOptionSectionHandler.java new file mode 100644 index 0000000000..012fd32d31 --- /dev/null +++ b/compute/src/main/java/org/jclouds/ovf/xml/DeploymentOptionSectionHandler.java @@ -0,0 +1,72 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.ovf.xml; + +import static org.jclouds.util.SaxUtils.currentOrNull; +import static org.jclouds.util.SaxUtils.equalsOrSuffix; + +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Provider; + +import org.jclouds.ovf.Configuration; +import org.jclouds.ovf.DeploymentOptionSection; +import org.jclouds.util.SaxUtils; +import org.xml.sax.Attributes; + +/** + * @author Adrian Cole + */ +public class DeploymentOptionSectionHandler extends + SectionHandler { + protected Configuration.Builder configBuilder = Configuration.builder(); + + @Inject + public DeploymentOptionSectionHandler(Provider builderProvider) { + super(builderProvider); + } + + public void startElement(String uri, String localName, String qName, Attributes attrs) { + Map attributes = SaxUtils.cleanseAttributes(attrs); + if (equalsOrSuffix(qName, "Configuration")) { + configBuilder.id(attributes.get("id")); + // TODO default; + } + } + + @Override + public void endElement(String uri, String localName, String qName) { + if (equalsOrSuffix(qName, "Info")) { + builder.info(currentOrNull(currentText)); + } else if (equalsOrSuffix(qName, "Label")) { + configBuilder.label(currentOrNull(currentText)); + } else if (equalsOrSuffix(qName, "Description")) { + configBuilder.description(currentOrNull(currentText)); + } else if (equalsOrSuffix(qName, "Configuration")) { + try { + builder.configuration(configBuilder.build()); + } finally { + configBuilder = Configuration.builder(); + } + } + super.endElement(uri, localName, qName); + } +} diff --git a/compute/src/main/java/org/jclouds/ovf/xml/DiskSectionHandler.java b/compute/src/main/java/org/jclouds/ovf/xml/DiskSectionHandler.java new file mode 100644 index 0000000000..e2385d328f --- /dev/null +++ b/compute/src/main/java/org/jclouds/ovf/xml/DiskSectionHandler.java @@ -0,0 +1,93 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.ovf.xml; + +import static org.jclouds.util.SaxUtils.currentOrNull; +import static org.jclouds.util.SaxUtils.equalsOrSuffix; + +import java.net.URI; +import java.util.Map; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Provider; + +import org.jclouds.logging.Logger; +import org.jclouds.ovf.Disk; +import org.jclouds.ovf.DiskSection; +import org.jclouds.util.SaxUtils; +import org.xml.sax.Attributes; + +/** + * @author Adrian Cole + */ +public class DiskSectionHandler extends SectionHandler { + + @Resource + protected Logger logger = Logger.NULL; + protected Disk.Builder diskBuilder = Disk.builder(); + + @Inject + public DiskSectionHandler(Provider builderProvider) { + super(builderProvider); + } + + public void startElement(String uri, String localName, String qName, Attributes attrs) { + Map attributes = SaxUtils.cleanseAttributes(attrs); + if (equalsOrSuffix(qName, "Disk")) { + diskBuilder.id(attributes.get("diskId")); + diskBuilder.capacity(attemptToParse(attributes.get("capacity"), "capacity", attributes.get("diskId"))); + diskBuilder.parentRef(attributes.get("parentRef")); + diskBuilder.fileRef(attributes.get("fileRef")); + if (attributes.containsKey("format")) + diskBuilder.format(URI.create(attributes.get("format"))); + diskBuilder.populatedSize(attemptToParse(attributes.get("populatedSize"), "populatedSize", attributes + .get("diskId"))); + diskBuilder.capacityAllocationUnits(attributes.get("capacityAllocationUnits")); + } + } + + private Long attemptToParse(String toParse, String key, String diskId) { + Long val = null; + if (toParse != null) { + try { + val = new Long(toParse); + } catch (NumberFormatException e) { + logger.warn("%s for disk %s not a number [%s]", key, diskId, toParse); + } + } + return val; + } + + @Override + public void endElement(String uri, String localName, String qName) { + if (equalsOrSuffix(qName, "Info")) { + builder.info(currentOrNull(currentText)); + } else if (equalsOrSuffix(qName, "Disk")) { + try { + builder.disk(diskBuilder.build()); + } finally { + diskBuilder = Disk.builder(); + } + } + super.endElement(uri, localName, qName); + } + +} diff --git a/compute/src/main/java/org/jclouds/ovf/xml/EnvelopeHandler.java b/compute/src/main/java/org/jclouds/ovf/xml/EnvelopeHandler.java new file mode 100644 index 0000000000..b1aad197f0 --- /dev/null +++ b/compute/src/main/java/org/jclouds/ovf/xml/EnvelopeHandler.java @@ -0,0 +1,162 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.ovf.xml; + +import static org.jclouds.util.SaxUtils.equalsOrSuffix; + +import java.util.Map; + +import javax.inject.Named; +import javax.inject.Provider; + +import org.jclouds.http.functions.ParseSax; +import org.jclouds.ovf.Envelope; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; + +import com.google.common.collect.ImmutableMap; +import com.google.inject.Inject; + +/** + * @author Adrian Cole + */ +public class EnvelopeHandler extends ParseSax.HandlerWithResult { + + protected StringBuilder currentText = new StringBuilder(); + protected Envelope.Builder builder = Envelope.builder(); + + public Envelope getResult() { + try { + return builder.build(); + } finally { + builder = Envelope.builder(); + } + } + + private final VirtualSystemHandler virtualSystemHandler; + private final DiskSectionHandler diskHandler; + private final NetworkSectionHandler networkHandler; + + @Inject + public EnvelopeHandler(DiskSectionHandler diskHandler, NetworkSectionHandler networkHandler, + VirtualSystemHandler osHandler) { + this.virtualSystemHandler = osHandler; + this.diskHandler = diskHandler; + this.networkHandler = networkHandler; + } + + @SuppressWarnings("unchecked") + protected SectionHandler defaultSectionHandler = SectionHandler.create(); + + @SuppressWarnings("unchecked") + @Inject(optional = true) + @Named("VirtualSystem") + Map> extensionHandlers = ImmutableMap + .> of(); + + @SuppressWarnings("unchecked") + protected SectionHandler extensionHandler; + + private boolean inDisk; + private boolean inNetwork; + private boolean inVirtualSystem; + private boolean inSection; + private boolean inExtensionSection; + + public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { + if (equalsOrSuffix(qName, "DiskSection")) { + inDisk = true; + } else if (equalsOrSuffix(qName, "NetworkSection")) { + inNetwork = true; + } else if (equalsOrSuffix(qName, "VirtualSystem")) { + inVirtualSystem = true; + } else if (extensionHandlers.containsKey(qName)) { + inExtensionSection = true; + extensionHandler = extensionHandlers.get(qName).get(); + } else if (qName.endsWith("Section")) { + inSection = true; + } + + if (inDisk) { + diskHandler.startElement(uri, localName, qName, attrs); + } else if (inNetwork) { + networkHandler.startElement(uri, localName, qName, attrs); + } else if (inVirtualSystem) { + virtualSystemHandler.startElement(uri, localName, qName, attrs); + } else if (inExtensionSection) { + extensionHandler.startElement(uri, localName, qName, attrs); + } else if (inSection) { + defaultSectionHandler.startElement(uri, localName, qName, attrs); + } + + } + + @Override + public void endElement(String uri, String localName, String qName) { + if (equalsOrSuffix(qName, "DiskSection")) { + inDisk = false; + builder.diskSection(diskHandler.getResult()); + } else if (equalsOrSuffix(qName, "NetworkSection")) { + inNetwork = false; + builder.networkSection(networkHandler.getResult()); + } else if (equalsOrSuffix(qName, "VirtualSystem")) { + inVirtualSystem = false; + builder.virtualSystem(virtualSystemHandler.getResult()); + } else if (extensionHandlers.containsKey(qName)) { + builder.additionalSection(extensionHandler.getResult()); + inExtensionSection = false; + } else if (qName.endsWith("Section")) { + builder.additionalSection(defaultSectionHandler.getResult()); + inSection = false; + } + + if (inDisk) { + diskHandler.endElement(uri, localName, qName); + } else if (inNetwork) { + networkHandler.endElement(uri, localName, qName); + } else if (inVirtualSystem) { + virtualSystemHandler.endElement(uri, localName, qName); + } else if (inExtensionSection) { + extensionHandler.endElement(uri, localName, qName); + } else if (inSection) { + defaultSectionHandler.endElement(uri, localName, qName); + } else { + currentText = new StringBuilder(); + } + } + + @Override + public void characters(char ch[], int start, int length) { + if (inDisk) { + diskHandler.characters(ch, start, length); + } else if (inNetwork) { + networkHandler.characters(ch, start, length); + } else if (inVirtualSystem) { + virtualSystemHandler.characters(ch, start, length); + } else if (inExtensionSection) { + extensionHandler.characters(ch, start, length); + } else if (inSection) { + defaultSectionHandler.characters(ch, start, length); + } else { + currentText.append(ch, start, length); + } + } + +} diff --git a/compute/src/main/java/org/jclouds/ovf/xml/NetworkSectionHandler.java b/compute/src/main/java/org/jclouds/ovf/xml/NetworkSectionHandler.java index 935891af51..0209a4c543 100644 --- a/compute/src/main/java/org/jclouds/ovf/xml/NetworkSectionHandler.java +++ b/compute/src/main/java/org/jclouds/ovf/xml/NetworkSectionHandler.java @@ -23,56 +23,46 @@ import static org.jclouds.util.SaxUtils.currentOrNull; import static org.jclouds.util.SaxUtils.equalsOrSuffix; import java.util.Map; -import java.util.Set; -import org.jclouds.http.functions.ParseSax; +import javax.inject.Inject; +import javax.inject.Provider; + import org.jclouds.ovf.Network; import org.jclouds.ovf.NetworkSection; import org.jclouds.util.SaxUtils; import org.xml.sax.Attributes; -import com.google.common.collect.Sets; - /** * @author Adrian Cole */ -public class NetworkSectionHandler extends ParseSax.HandlerWithResult { - protected StringBuilder currentText = new StringBuilder(); +public class NetworkSectionHandler extends SectionHandler { + protected Network.Builder networkBuilder = Network.builder(); - protected String info; - protected String name; - protected String description; - - protected Set networks = Sets.newLinkedHashSet(); - - public NetworkSection getResult() { - NetworkSection system = new NetworkSection(info, networks); - this.info = null; - this.networks = Sets.newLinkedHashSet(); - return system; + @Inject + public NetworkSectionHandler(Provider builderProvider) { + super(builderProvider); } public void startElement(String uri, String localName, String qName, Attributes attrs) { Map attributes = SaxUtils.cleanseAttributes(attrs); if (equalsOrSuffix(qName, "Network")) { - name = attributes.get("name"); + networkBuilder.name(attributes.get("name")); } } @Override public void endElement(String uri, String localName, String qName) { if (equalsOrSuffix(qName, "Info")) { - this.info = currentOrNull(currentText); + builder.info(currentOrNull(currentText)); } else if (equalsOrSuffix(qName, "Description")) { - this.description = currentOrNull(currentText); + networkBuilder.description(currentOrNull(currentText)); } else if (equalsOrSuffix(qName, "Network")) { - this.networks.add(new Network(name, description)); + try { + builder.network(networkBuilder.build()); + } finally { + networkBuilder = Network.builder(); + } } - currentText = new StringBuilder(); + super.endElement(uri, localName, qName); } - - public void characters(char ch[], int start, int length) { - currentText.append(ch, start, length); - } - } diff --git a/compute/src/main/java/org/jclouds/ovf/xml/OperatingSystemSectionHandler.java b/compute/src/main/java/org/jclouds/ovf/xml/OperatingSystemSectionHandler.java index 520f50f1f6..b035d2375b 100644 --- a/compute/src/main/java/org/jclouds/ovf/xml/OperatingSystemSectionHandler.java +++ b/compute/src/main/java/org/jclouds/ovf/xml/OperatingSystemSectionHandler.java @@ -25,26 +25,20 @@ import static org.jclouds.util.SaxUtils.equalsOrSuffix; import java.util.Map; -import org.jclouds.http.functions.ParseSax; +import javax.inject.Inject; +import javax.inject.Provider; + import org.jclouds.ovf.OperatingSystemSection; import org.xml.sax.Attributes; /** * @author Adrian Cole */ -public class OperatingSystemSectionHandler extends ParseSax.HandlerWithResult { - private StringBuilder currentText = new StringBuilder(); - - protected Integer id; - protected String info; - protected String description; - - public OperatingSystemSection getResult() { - OperatingSystemSection system = new OperatingSystemSection(id, info, description); - id = null; - info = null; - description = null; - return system; +public class OperatingSystemSectionHandler extends + SectionHandler { + @Inject + public OperatingSystemSectionHandler(Provider builderProvider) { + super(builderProvider); } @Override @@ -52,21 +46,17 @@ public class OperatingSystemSectionHandler extends ParseSax.HandlerWithResult attributes = cleanseAttributes(attrs); if (equalsOrSuffix(qName, "OperatingSystemSection")) { if (attributes.containsKey("id")) - this.id = Integer.parseInt(attributes.get("id")); + builder.id(Integer.parseInt(attributes.get("id"))); } } @Override public void endElement(String uri, String localName, String qName) { if (equalsOrSuffix(qName, "Info")) { - this.info = currentOrNull(currentText); + builder.info(currentOrNull(currentText)); } else if (equalsOrSuffix(qName, "Description")) { - this.description = currentOrNull(currentText); + builder.description(currentOrNull(currentText)); } - currentText = new StringBuilder(); - } - - public void characters(char ch[], int start, int length) { - currentText.append(ch, start, length); + super.endElement(uri, localName, qName); } } \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/ovf/xml/OvfEnvelopeHandler.java b/compute/src/main/java/org/jclouds/ovf/xml/OvfEnvelopeHandler.java deleted file mode 100644 index 5efa444f62..0000000000 --- a/compute/src/main/java/org/jclouds/ovf/xml/OvfEnvelopeHandler.java +++ /dev/null @@ -1,87 +0,0 @@ -/** - * - * Copyright (C) 2010 Cloud Conscious, LLC. - * - * ==================================================================== - * 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.vdc/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.ovf.xml; - -//import static org.jclouds.vcloud.util.Utils.cleanseAttributes; - -import javax.inject.Inject; - -import org.jclouds.http.functions.ParseSax; -import org.jclouds.ovf.OvfEnvelope; -import org.jclouds.ovf.VirtualSystem; -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; - -/** - * @author Adrian Cole - */ -public class OvfEnvelopeHandler extends ParseSax.HandlerWithResult { - - protected final VirtualSystemHandler virtualSystemHandler; - - @Inject - public OvfEnvelopeHandler(VirtualSystemHandler virtualSystemHandler) { - this.virtualSystemHandler = virtualSystemHandler; - } - - protected StringBuilder currentText = new StringBuilder(); - - private VirtualSystem virtualSystem; - - private boolean inVirtualSystem; - - public OvfEnvelope getResult() { - return new OvfEnvelope(virtualSystem); - } - - @Override - public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { -// Map attributes = cleanseAttributes(attrs); - if (qName.endsWith("VirtualSystem")) { - inVirtualSystem = true; - } - if (inVirtualSystem) { - virtualSystemHandler.startElement(uri, localName, qName, attrs); - } - } - - public void endElement(String uri, String name, String qName) { - if (qName.endsWith("VirtualSystem")) { - inVirtualSystem = false; - virtualSystem = virtualSystemHandler.getResult(); - } - if (inVirtualSystem) { - virtualSystemHandler.endElement(uri, name, qName); - } - currentText = new StringBuilder(); - } - - public void characters(char ch[], int start, int length) { - if (inVirtualSystem) - virtualSystemHandler.characters(ch, start, length); - else - currentText.append(ch, start, length); - } - - protected String currentOrNull() { - String returnVal = currentText.toString().trim(); - return returnVal.equals("") ? null : returnVal; - } -} diff --git a/compute/src/main/java/org/jclouds/ovf/xml/SectionHandler.java b/compute/src/main/java/org/jclouds/ovf/xml/SectionHandler.java new file mode 100644 index 0000000000..2ffd34bf39 --- /dev/null +++ b/compute/src/main/java/org/jclouds/ovf/xml/SectionHandler.java @@ -0,0 +1,76 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.ovf.xml; + +import static org.jclouds.util.SaxUtils.currentOrNull; +import static org.jclouds.util.SaxUtils.equalsOrSuffix; + +import javax.inject.Provider; + +import org.jclouds.http.functions.ParseSax; +import org.jclouds.ovf.Section; +import org.jclouds.ovf.Section.Builder; + +/** + * @author Adrian Cole + */ +public class SectionHandler, B extends Section.Builder> extends ParseSax.HandlerWithResult { + @SuppressWarnings("unchecked") + public static SectionHandler create() { + return new SectionHandler(new Provider() { + + @Override + public Builder get() { + return new Section.Builder(); + } + + }); + } + + protected final Provider> builderProvider; + protected StringBuilder currentText = new StringBuilder(); + protected B builder; + + public SectionHandler(Provider builderProvider) { + this.builderProvider = builderProvider; + this.builder = builderProvider.get(); + } + + @SuppressWarnings("unchecked") + public T getResult() { + try { + return (T) builder.build(); + } finally { + builder = (B) builderProvider.get(); + } + } + + @Override + public void endElement(String uri, String localName, String qName) { + if (equalsOrSuffix(qName, "Info")) { + builder.info(currentOrNull(currentText)); + } + currentText = new StringBuilder(); + } + + public void characters(char ch[], int start, int length) { + currentText.append(ch, start, length); + } +} \ No newline at end of file diff --git a/compute/src/main/java/org/jclouds/ovf/xml/VirtualHardwareSectionHandler.java b/compute/src/main/java/org/jclouds/ovf/xml/VirtualHardwareSectionHandler.java index 7195b6240a..ce76830aa8 100644 --- a/compute/src/main/java/org/jclouds/ovf/xml/VirtualHardwareSectionHandler.java +++ b/compute/src/main/java/org/jclouds/ovf/xml/VirtualHardwareSectionHandler.java @@ -19,53 +19,53 @@ package org.jclouds.ovf.xml; -import java.util.Set; +import static org.jclouds.util.SaxUtils.cleanseAttributes; +import static org.jclouds.util.SaxUtils.currentOrNull; +import static org.jclouds.util.SaxUtils.equalsOrSuffix; + +import java.util.Map; import javax.inject.Inject; +import javax.inject.Provider; -import org.jclouds.cim.ResourceAllocationSettingData; -import org.jclouds.cim.VirtualSystemSettingData; import org.jclouds.cim.xml.ResourceAllocationSettingDataHandler; import org.jclouds.cim.xml.VirtualSystemSettingDataHandler; -import org.jclouds.http.functions.ParseSax; import org.jclouds.ovf.VirtualHardwareSection; import org.xml.sax.Attributes; -import com.google.common.collect.Sets; +import com.google.common.base.Splitter; /** * @author Adrian Cole */ -public class VirtualHardwareSectionHandler extends ParseSax.HandlerWithResult { - protected StringBuilder currentText = new StringBuilder(); +public class VirtualHardwareSectionHandler extends + SectionHandler { private final VirtualSystemSettingDataHandler systemHandler; private final ResourceAllocationSettingDataHandler allocationHandler; @Inject - public VirtualHardwareSectionHandler(VirtualSystemSettingDataHandler systemHandler, - ResourceAllocationSettingDataHandler allocationHandler) { + public VirtualHardwareSectionHandler(Provider builderProvider, + VirtualSystemSettingDataHandler systemHandler, ResourceAllocationSettingDataHandler allocationHandler) { + super(builderProvider); this.systemHandler = systemHandler; this.allocationHandler = allocationHandler; } - private String info; - protected VirtualSystemSettingData system; - protected Set allocations = Sets.newLinkedHashSet(); - private boolean inItem; private boolean inSystem; - public VirtualHardwareSection getResult() { - return new VirtualHardwareSection(info, system, allocations); - } - public void startElement(String uri, String localName, String qName, Attributes attrs) { - if (qName.endsWith("System")) { + Map attributes = cleanseAttributes(attrs); + if (equalsOrSuffix(qName, "VirtualHardwareSection")) { + if (attributes.containsKey("transport")) + builder.transports(Splitter.on(' ').split(attributes.get("transport"))); + } else if (equalsOrSuffix(qName, "System")) { inSystem = true; - } else if (!inSystem && qName.endsWith("Item")) { + } else if (!inSystem && equalsOrSuffix(qName, "Item")) { inItem = true; } + if (inSystem) { systemHandler.startElement(uri, localName, qName, attrs); } else if (inItem) { @@ -75,30 +75,33 @@ public class VirtualHardwareSectionHandler extends ParseSax.HandlerWithResult { - protected StringBuilder currentText = new StringBuilder(); +public class VirtualSystemHandler extends SectionHandler { + private final OperatingSystemSectionHandler osHandler; private final VirtualHardwareSectionHandler hardwareHandler; @Inject - public VirtualSystemHandler(OperatingSystemSectionHandler osHandler, VirtualHardwareSectionHandler hardwareHandler) { + public VirtualSystemHandler(Provider builderProvider, + OperatingSystemSectionHandler osHandler, VirtualHardwareSectionHandler hardwareHandler) { + super(builderProvider); this.osHandler = osHandler; this.hardwareHandler = hardwareHandler; } - protected String id; - protected String info; - protected String name; - protected OperatingSystemSection operatingSystem; - protected Set hardware = Sets.newLinkedHashSet(); + @SuppressWarnings("unchecked") + protected SectionHandler defaultSectionHandler = SectionHandler.create(); + + @SuppressWarnings("unchecked") + @Inject(optional = true) + @Named("VirtualSystem") + Map> extensionHandlers = ImmutableMap + .> of(); + + @SuppressWarnings("unchecked") + protected SectionHandler extensionHandler; private boolean inHardware; private boolean inOs; - private boolean inNetwork; - private boolean inGuest; + private boolean inSection; + private boolean inExtensionSection; - public VirtualSystem getResult() { - VirtualSystem vs = new VirtualSystem(id, info, name, operatingSystem, hardware); - id = null; - info = null; - name = null; - operatingSystem = null; - hardware = Sets.newLinkedHashSet(); - return vs; - } - - public void startElement(String uri, String localName, String qName, Attributes attrs) { + public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { Map attributes = cleanseAttributes(attrs); if (equalsOrSuffix(qName, "VirtualHardwareSection")) { inHardware = true; } else if (equalsOrSuffix(qName, "OperatingSystemSection")) { inOs = true; - } else if (equalsOrSuffix(qName, "NetworkConnectionSection")) { - inNetwork = true; - } else if (equalsOrSuffix(qName, "GuestCustomizationSection")) { - inGuest = true; + } else if (extensionHandlers.containsKey(qName)) { + inExtensionSection = true; + extensionHandler = extensionHandlers.get(qName).get(); + } else if (qName.endsWith("Section")) { + inSection = true; } if (inHardware) { hardwareHandler.startElement(uri, localName, qName, attrs); } else if (inOs) { osHandler.startElement(uri, localName, qName, attrs); - } else if (inNetwork) { - // TODO - } else if (inGuest) { - // TODO + } else if (inExtensionSection) { + extensionHandler.startElement(uri, localName, qName, attrs); + } else if (inSection) { + defaultSectionHandler.startElement(uri, localName, qName, attrs); } else if (equalsOrSuffix(qName, "VirtualSystem")) { - id = attributes.get("id"); + builder.id(attributes.get("id")); } } @@ -100,42 +99,49 @@ public class VirtualSystemHandler extends ParseSax.HandlerWithResult + * + * ==================================================================== + * 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.ovf.xml; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; +import java.net.URI; + +import org.jclouds.http.functions.ParseSax; +import org.jclouds.http.functions.ParseSax.Factory; +import org.jclouds.http.functions.config.SaxParserModule; +import org.jclouds.ovf.Disk; +import org.jclouds.ovf.DiskSection; +import org.testng.annotations.Test; + +import com.google.inject.Guice; +import com.google.inject.Injector; + +/** + * Tests behavior of {@code DiskSectionHandler} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class DiskSectionHandlerTest { + public void test() { + InputStream is = getClass().getResourceAsStream("/disksection.xml"); + Injector injector = Guice.createInjector(new SaxParserModule()); + Factory factory = injector.getInstance(ParseSax.Factory.class); + DiskSection result = factory.create(injector.getInstance(DiskSectionHandler.class)).parse(is); + assertEquals(result.toString(), DiskSection.builder().info("Describes the set of virtual disks").disk( + Disk.builder().id("vmdisk1") + + .fileRef("file1").capacity(8589934592l).populatedSize(3549324972l).format( + URI.create("http://www.vmware.com/interfaces/specifications/vmdk.html#sparse")).build()).disk( + Disk.builder().id("vmdisk2").capacity(536870912l).build()).disk( + Disk.builder().id("vmdisk3").capacityAllocationUnits("byte * 2^30").build()) + + .build().toString() + + ); + } +} diff --git a/compute/src/test/java/org/jclouds/ovf/xml/OvfEnvelopeHandlerTest.java b/compute/src/test/java/org/jclouds/ovf/xml/EnvelopeHandlerTest.java similarity index 83% rename from compute/src/test/java/org/jclouds/ovf/xml/OvfEnvelopeHandlerTest.java rename to compute/src/test/java/org/jclouds/ovf/xml/EnvelopeHandlerTest.java index 9968887ee9..d7088ea673 100644 --- a/compute/src/test/java/org/jclouds/ovf/xml/OvfEnvelopeHandlerTest.java +++ b/compute/src/test/java/org/jclouds/ovf/xml/EnvelopeHandlerTest.java @@ -25,29 +25,28 @@ import org.jclouds.cim.xml.VirtualSystemSettingDataHandlerTest; import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ParseSax.Factory; import org.jclouds.http.functions.config.SaxParserModule; -import org.jclouds.ovf.OvfEnvelope; -import org.jclouds.ovf.xml.OvfEnvelopeHandler; +import org.jclouds.ovf.Envelope; import org.testng.annotations.Test; import com.google.inject.Guice; import com.google.inject.Injector; /** - * Tests behavior of {@code OvfEnvelopeHandler} + * Tests behavior of {@code EnvelopeHandler} * * @author Adrian Cole */ @Test(groups = "unit") -public class OvfEnvelopeHandlerTest { +public class EnvelopeHandlerTest { public void testVCloud1_0() { InputStream is = getClass().getResourceAsStream("/ovf.xml"); Injector injector = Guice.createInjector(new SaxParserModule()); Factory factory = injector.getInstance(ParseSax.Factory.class); - OvfEnvelope result = factory.create(injector.getInstance(OvfEnvelopeHandler.class)).parse(is); + Envelope result = factory.create(injector.getInstance(EnvelopeHandler.class)).parse(is); checkOvfEnvelope(result); } - static void checkOvfEnvelope(OvfEnvelope result) { + static void checkOvfEnvelope(Envelope result) { VirtualSystemSettingDataHandlerTest.checkVirtualSystem(result.getVirtualSystem()); } diff --git a/compute/src/test/java/org/jclouds/ovf/xml/NetworkSectionHandlerTest.java b/compute/src/test/java/org/jclouds/ovf/xml/NetworkSectionHandlerTest.java new file mode 100644 index 0000000000..f763297179 --- /dev/null +++ b/compute/src/test/java/org/jclouds/ovf/xml/NetworkSectionHandlerTest.java @@ -0,0 +1,58 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.ovf.xml; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; + +import org.jclouds.http.functions.ParseSax; +import org.jclouds.http.functions.ParseSax.Factory; +import org.jclouds.http.functions.config.SaxParserModule; +import org.jclouds.ovf.Network; +import org.jclouds.ovf.NetworkSection; +import org.testng.annotations.Test; + +import com.google.inject.Guice; +import com.google.inject.Injector; + +/** + * Tests behavior of {@code NetworkSectionHandler} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class NetworkSectionHandlerTest { + public void test() { + InputStream is = getClass().getResourceAsStream("/networksection.xml"); + Injector injector = Guice.createInjector(new SaxParserModule()); + Factory factory = injector.getInstance(ParseSax.Factory.class); + NetworkSection result = factory.create(injector.getInstance(NetworkSectionHandler.class)).parse(is); + assertEquals(result.toString(), NetworkSection.builder().info("List of logical networks used in the package") + .network( + Network.builder().name("red").description("The network the Red service is available on") + .build()).network( + Network.builder().name("blue").description("The network the Blue service is available on") + .build()) + .build().toString() + + ); + } +} diff --git a/compute/src/test/java/org/jclouds/ovf/xml/OperatingSystemSectionHandlerTest.java b/compute/src/test/java/org/jclouds/ovf/xml/OperatingSystemSectionHandlerTest.java new file mode 100644 index 0000000000..9f474110c1 --- /dev/null +++ b/compute/src/test/java/org/jclouds/ovf/xml/OperatingSystemSectionHandlerTest.java @@ -0,0 +1,53 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.ovf.xml; + +import static org.testng.Assert.assertEquals; + +import java.io.InputStream; + +import org.jclouds.http.functions.ParseSax; +import org.jclouds.http.functions.ParseSax.Factory; +import org.jclouds.http.functions.config.SaxParserModule; +import org.jclouds.ovf.OperatingSystemSection; +import org.testng.annotations.Test; + +import com.google.inject.Guice; +import com.google.inject.Injector; + +/** + * Tests behavior of {@code OperatingSystemSectionHandler} + * + * @author Adrian Cole + */ +@Test(groups = "unit") +public class OperatingSystemSectionHandlerTest { + public void test() { + InputStream is = getClass().getResourceAsStream("/operatingsystemsection.xml"); + Injector injector = Guice.createInjector(new SaxParserModule()); + Factory factory = injector.getInstance(ParseSax.Factory.class); + OperatingSystemSection result = factory.create(injector.getInstance(OperatingSystemSectionHandler.class)).parse( + is); + assertEquals(result.toString(), OperatingSystemSection.builder().info("Specifies the operating system installed") + .description("Microsoft Windows Server 2008").id(76).build().toString() + + ); + } +} diff --git a/compute/src/test/resources/disksection.xml b/compute/src/test/resources/disksection.xml new file mode 100644 index 0000000000..910c8dded4 --- /dev/null +++ b/compute/src/test/resources/disksection.xml @@ -0,0 +1,10 @@ + + Describes the set of virtual disks + + + + + \ No newline at end of file diff --git a/compute/src/test/resources/networksection.xml b/compute/src/test/resources/networksection.xml new file mode 100644 index 0000000000..8c136c8bb9 --- /dev/null +++ b/compute/src/test/resources/networksection.xml @@ -0,0 +1,11 @@ + + List of logical networks used in the package + + The network the Red service is available on + + + + The network the Blue service is available on + + + \ No newline at end of file diff --git a/compute/src/test/resources/operatingsystemsection.xml b/compute/src/test/resources/operatingsystemsection.xml new file mode 100644 index 0000000000..0bf83d293a --- /dev/null +++ b/compute/src/test/resources/operatingsystemsection.xml @@ -0,0 +1,4 @@ + + Specifies the operating system installed + Microsoft Windows Server 2008 + \ No newline at end of file diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.java index f7aa572d05..b5cad92428 100644 --- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.java +++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.java @@ -132,7 +132,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions credentialsMap.put(key, pair); } else { if (hasPublicKeyMaterial.apply(options)) { - logger.warn("to avoid creating extra keys in aws-ec2, use templateOption overrideLoginCredentialWith(id_rsa)"); + logger.warn("to avoid creating temporary keys in aws-ec2, use templateOption overrideLoginCredentialWith(id_rsa)"); } return createUniqueKeyPairAndPutIntoMap(region, group); } diff --git a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/domain/SavvisOperatingSystemSpecification.java b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/domain/SavvisOperatingSystemSpecification.java deleted file mode 100644 index 07862eec70..0000000000 --- a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/domain/SavvisOperatingSystemSpecification.java +++ /dev/null @@ -1,209 +0,0 @@ -/** - * - * Copyright (C) 2010 Cloud Conscious, LLC. - * - * ==================================================================== - * 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 org.jclouds.cim.OSType; -import org.jclouds.compute.domain.OsFamily; - -/** - * Savvis Operating System Specification - * - * @see - * @author Adrian Cole - */ -public class SavvisOperatingSystemSpecification { - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - private int savvisId; - private int typeId; - private String name; - private OsFamily family; - private String description; - private boolean supportedBySavvis; - - /** - * @see SavvisOperatingSystemSpecification#getSavvisId - */ - public Builder savvisId(int savvisId) { - this.savvisId = savvisId; - return this; - } - - /** - * @see SavvisOperatingSystemSpecification#getTypeId - */ - public Builder typeId(int typeId) { - this.typeId = typeId; - return this; - } - - /** - * @see SavvisOperatingSystemSpecification#getOsFamily - */ - public Builder family(OsFamily family) { - this.family = family; - return this; - } - - /** - * @see SavvisOperatingSystemSpecification#getInfo - */ - public Builder name(String name) { - this.name = name; - return this; - } - - /** - * @see SavvisOperatingSystemSpecification#getDescription - */ - public Builder description(String description) { - this.description = description; - return this; - } - - /** - * @see SavvisOperatingSystemSpecification#isSupportedBySavvis - */ - public Builder supportedBySavvis(boolean supportedBySavvis) { - this.supportedBySavvis = supportedBySavvis; - return this; - } - - public SavvisOperatingSystemSpecification build() { - return new SavvisOperatingSystemSpecification(savvisId, typeId, family, name, description, supportedBySavvis); - } - - public Builder fromSavvisOperatingSystemSpecification(SavvisOperatingSystemSpecification in) { - return savvisId(in.getSavvisId()).typeId(in.getTypeId()).family(in.getFamily()).name(in.getName()) - .description(in.getDescription()).supportedBySavvis(in.isSupportedBySavvis()); - } - } - - private final int savvisId; - private final int typeId; - private final OsFamily family; - private final String name; - private final String description; - private final boolean supportedBySavvis; - - public SavvisOperatingSystemSpecification(int savvisId, int typeId, OsFamily family, String name, - String description, boolean supportedBySavvis) { - this.savvisId = savvisId; - this.typeId = typeId; - this.family = family; - this.name = name; - this.description = description; - this.supportedBySavvis = supportedBySavvis; - } - - /** - * @return Internal name used by Savvis - */ - public int getSavvisId() { - return savvisId; - } - - /** - * - * @return CIM OS Type Id - * @see OSType#getCode() - */ - public int getTypeId() { - return typeId; - } - - /** - * - * @return the name of the OS - */ - public String getName() { - return name; - } - - /** - * - * @return the operating system family - */ - public OsFamily getFamily() { - return family; - } - - /** - * - * @return description - */ - public String getDescription() { - return description; - } - - /** - * - * @return whether or not this operating system is supported by Savvis - */ - public boolean isSupportedBySavvis() { - return supportedBySavvis; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + typeId; - result = prime * result + savvisId; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - SavvisOperatingSystemSpecification other = (SavvisOperatingSystemSpecification) obj; - if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - if (typeId != other.typeId) - return false; - if (savvisId != other.savvisId) - return false; - return true; - } - - public Builder toBuilder() { - return builder().fromSavvisOperatingSystemSpecification(this); - } - - @Override - public String toString() { - return String.format("[description=%s, family=%s, name=%s, typeId=%s, savvisId=%s, supportedBySavvis=%s]", - description, family, name, typeId, savvisId, supportedBySavvis); - } - -} \ No newline at end of file diff --git a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/domain/vapp/Network.java b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/domain/vapp/Network.java index 9f65e6386e..93e1f41aed 100644 --- a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/domain/vapp/Network.java +++ b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/domain/vapp/Network.java @@ -1,3 +1,22 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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.vapp; /** From 26a3a2f9deae4d8711a6f8aa43617cbd0e9a78a7 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Tue, 22 Mar 2011 02:41:08 -0700 Subject: [PATCH 2/3] labeled unparsed ovf sections --- .../main/java/org/jclouds/ovf/Envelope.java | 27 ++++---- .../java/org/jclouds/ovf/VirtualSystem.java | 23 ++++--- .../org/jclouds/ovf/xml/EnvelopeHandler.java | 65 ++++++++++--------- .../jclouds/ovf/xml/VirtualSystemHandler.java | 50 +++++++------- 4 files changed, 90 insertions(+), 75 deletions(-) diff --git a/compute/src/main/java/org/jclouds/ovf/Envelope.java b/compute/src/main/java/org/jclouds/ovf/Envelope.java index 42f52c626c..34f19cf4b1 100644 --- a/compute/src/main/java/org/jclouds/ovf/Envelope.java +++ b/compute/src/main/java/org/jclouds/ovf/Envelope.java @@ -23,7 +23,10 @@ import static com.google.common.base.Preconditions.checkNotNull; import java.util.Set; +import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; import com.google.common.collect.Sets; /** @@ -46,7 +49,7 @@ public class Envelope { protected Set diskSections = Sets.newLinkedHashSet(); protected Set networkSections = Sets.newLinkedHashSet(); @SuppressWarnings("unchecked") - protected Set
additionalSections = Sets.newLinkedHashSet(); + protected Multimap additionalSections = LinkedHashMultimap.create(); protected VirtualSystem virtualSystem; /** @@ -85,8 +88,8 @@ public class Envelope { * @see Envelope#getAdditionalSections */ @SuppressWarnings("unchecked") - public Builder additionalSection(Section additionalSection) { - this.additionalSections.add(checkNotNull(additionalSection, "additionalSection")); + public Builder additionalSection(String name, Section additionalSection) { + this.additionalSections.put(checkNotNull(name, "name"), checkNotNull(additionalSection, "additionalSection")); return this; } @@ -94,9 +97,9 @@ public class Envelope { * @see Envelope#getAdditionalSections */ @SuppressWarnings("unchecked") - public Builder additionalSections(Iterable additionalSections) { - this.additionalSections = ImmutableSet - .
copyOf(checkNotNull(additionalSections, "additionalSections")); + public Builder additionalSections(Multimap additionalSections) { + this.additionalSections = ImmutableMultimap. copyOf(checkNotNull(additionalSections, + "additionalSections")); return this; } @@ -116,8 +119,8 @@ public class Envelope { } public Builder fromEnvelope(Envelope in) { - return virtualSystem(in.getVirtualSystem()).diskSections(in.getDiskSections()).networkSections( - networkSections).additionalSections(in.getAdditionalSections()); + return virtualSystem(in.getVirtualSystem()).diskSections(in.getDiskSections()) + .networkSections(networkSections).additionalSections(in.getAdditionalSections()); } } @@ -125,15 +128,15 @@ public class Envelope { private final Set diskSections; private final Set networkSections; @SuppressWarnings("unchecked") - private final Set additionalSections; + private final Multimap additionalSections; private final VirtualSystem virtualSystem; @SuppressWarnings("unchecked") public Envelope(Iterable diskSections, Iterable networkSections, - Iterable additionalSections, VirtualSystem virtualSystem) { + Multimap additionalSections, VirtualSystem virtualSystem) { this.diskSections = ImmutableSet.copyOf(checkNotNull(diskSections, "diskSections")); this.networkSections = ImmutableSet.copyOf(checkNotNull(networkSections, "networkSections")); - this.additionalSections = ImmutableSet.copyOf(checkNotNull(additionalSections, "additionalSections")); + this.additionalSections = ImmutableMultimap.copyOf(checkNotNull(additionalSections, "additionalSections")); this.virtualSystem = checkNotNull(virtualSystem, "virtualSystem"); } @@ -146,7 +149,7 @@ public class Envelope { } @SuppressWarnings("unchecked") - public Set getAdditionalSections() { + public Multimap getAdditionalSections() { return additionalSections; } diff --git a/compute/src/main/java/org/jclouds/ovf/VirtualSystem.java b/compute/src/main/java/org/jclouds/ovf/VirtualSystem.java index 15b810e188..6eaaef5f84 100644 --- a/compute/src/main/java/org/jclouds/ovf/VirtualSystem.java +++ b/compute/src/main/java/org/jclouds/ovf/VirtualSystem.java @@ -23,7 +23,10 @@ import static com.google.common.base.Preconditions.checkNotNull; import java.util.Set; +import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; import com.google.common.collect.Sets; /** @@ -50,7 +53,7 @@ public class VirtualSystem extends Section { protected OperatingSystemSection operatingSystem; protected Set hardwareSections = Sets.newLinkedHashSet(); @SuppressWarnings("unchecked") - protected Set
additionalSections = Sets.newLinkedHashSet(); + protected Multimap additionalSections = LinkedHashMultimap.create(); /** * @see VirtualSystem#getName @@ -97,8 +100,8 @@ public class VirtualSystem extends Section { * @see VirtualSystem#getAdditionalSections */ @SuppressWarnings("unchecked") - public Builder additionalSection(Section additionalSection) { - this.additionalSections.add(checkNotNull(additionalSection, "additionalSection")); + public Builder additionalSection(String name, Section additionalSection) { + this.additionalSections.put(checkNotNull(name, "name"), checkNotNull(additionalSection, "additionalSection")); return this; } @@ -106,9 +109,9 @@ public class VirtualSystem extends Section { * @see VirtualSystem#getAdditionalSections */ @SuppressWarnings("unchecked") - public Builder additionalSections(Iterable additionalSections) { - this.additionalSections = ImmutableSet - .
copyOf(checkNotNull(additionalSections, "additionalSections")); + public Builder additionalSections(Multimap additionalSections) { + this.additionalSections = ImmutableMultimap. copyOf(checkNotNull(additionalSections, + "additionalSections")); return this; } @@ -149,17 +152,17 @@ public class VirtualSystem extends Section { private final OperatingSystemSection operatingSystem; private final Set hardwareSections; @SuppressWarnings("unchecked") - private final Set additionalSections; + private final Multimap additionalSections; @SuppressWarnings("unchecked") public VirtualSystem(String id, String info, String name, OperatingSystemSection operatingSystem, - Iterable hardwareSections, Iterable additionalSections) { + Iterable hardwareSections, Multimap additionalSections) { super(info); this.id = id; this.name = name; this.operatingSystem = checkNotNull(operatingSystem, "operatingSystem"); this.hardwareSections = ImmutableSet.copyOf(checkNotNull(hardwareSections, "hardwareSections")); - this.additionalSections = ImmutableSet.copyOf(checkNotNull(additionalSections, "additionalSections")); + this.additionalSections = ImmutableMultimap.copyOf(checkNotNull(additionalSections, "additionalSections")); } public String getId() { @@ -183,7 +186,7 @@ public class VirtualSystem extends Section { } @SuppressWarnings("unchecked") - public Set getAdditionalSections() { + public Multimap getAdditionalSections() { return additionalSections; } diff --git a/compute/src/main/java/org/jclouds/ovf/xml/EnvelopeHandler.java b/compute/src/main/java/org/jclouds/ovf/xml/EnvelopeHandler.java index b1aad197f0..4dd0cc1c2c 100644 --- a/compute/src/main/java/org/jclouds/ovf/xml/EnvelopeHandler.java +++ b/compute/src/main/java/org/jclouds/ovf/xml/EnvelopeHandler.java @@ -39,7 +39,6 @@ import com.google.inject.Inject; */ public class EnvelopeHandler extends ParseSax.HandlerWithResult { - protected StringBuilder currentText = new StringBuilder(); protected Envelope.Builder builder = Envelope.builder(); public Envelope getResult() { @@ -80,18 +79,23 @@ public class EnvelopeHandler extends ParseSax.HandlerWithResult { private boolean inSection; private boolean inExtensionSection; + private int depth = 0; + public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { - if (equalsOrSuffix(qName, "DiskSection")) { - inDisk = true; - } else if (equalsOrSuffix(qName, "NetworkSection")) { - inNetwork = true; - } else if (equalsOrSuffix(qName, "VirtualSystem")) { - inVirtualSystem = true; - } else if (extensionHandlers.containsKey(qName)) { - inExtensionSection = true; - extensionHandler = extensionHandlers.get(qName).get(); - } else if (qName.endsWith("Section")) { - inSection = true; + depth++; + if (depth == 2) { + if (equalsOrSuffix(qName, "DiskSection")) { + inDisk = true; + } else if (equalsOrSuffix(qName, "NetworkSection")) { + inNetwork = true; + } else if (equalsOrSuffix(qName, "VirtualSystem")) { + inVirtualSystem = true; + } else if (extensionHandlers.containsKey(qName)) { + inExtensionSection = true; + extensionHandler = extensionHandlers.get(qName).get(); + } else if (qName.endsWith("Section")) { + inSection = true; + } } if (inDisk) { @@ -110,21 +114,24 @@ public class EnvelopeHandler extends ParseSax.HandlerWithResult { @Override public void endElement(String uri, String localName, String qName) { - if (equalsOrSuffix(qName, "DiskSection")) { - inDisk = false; - builder.diskSection(diskHandler.getResult()); - } else if (equalsOrSuffix(qName, "NetworkSection")) { - inNetwork = false; - builder.networkSection(networkHandler.getResult()); - } else if (equalsOrSuffix(qName, "VirtualSystem")) { - inVirtualSystem = false; - builder.virtualSystem(virtualSystemHandler.getResult()); - } else if (extensionHandlers.containsKey(qName)) { - builder.additionalSection(extensionHandler.getResult()); - inExtensionSection = false; - } else if (qName.endsWith("Section")) { - builder.additionalSection(defaultSectionHandler.getResult()); - inSection = false; + depth--; + if (depth == 1) { + if (equalsOrSuffix(qName, "DiskSection")) { + inDisk = false; + builder.diskSection(diskHandler.getResult()); + } else if (equalsOrSuffix(qName, "NetworkSection")) { + inNetwork = false; + builder.networkSection(networkHandler.getResult()); + } else if (equalsOrSuffix(qName, "VirtualSystem")) { + inVirtualSystem = false; + builder.virtualSystem(virtualSystemHandler.getResult()); + } else if (extensionHandlers.containsKey(qName)) { + builder.additionalSection(qName, extensionHandler.getResult()); + inExtensionSection = false; + } else if (qName.endsWith("Section")) { + builder.additionalSection(qName, defaultSectionHandler.getResult()); + inSection = false; + } } if (inDisk) { @@ -137,8 +144,6 @@ public class EnvelopeHandler extends ParseSax.HandlerWithResult { extensionHandler.endElement(uri, localName, qName); } else if (inSection) { defaultSectionHandler.endElement(uri, localName, qName); - } else { - currentText = new StringBuilder(); } } @@ -154,8 +159,6 @@ public class EnvelopeHandler extends ParseSax.HandlerWithResult { extensionHandler.characters(ch, start, length); } else if (inSection) { defaultSectionHandler.characters(ch, start, length); - } else { - currentText.append(ch, start, length); } } diff --git a/compute/src/main/java/org/jclouds/ovf/xml/VirtualSystemHandler.java b/compute/src/main/java/org/jclouds/ovf/xml/VirtualSystemHandler.java index 18c7054f54..b54078c7e3 100644 --- a/compute/src/main/java/org/jclouds/ovf/xml/VirtualSystemHandler.java +++ b/compute/src/main/java/org/jclouds/ovf/xml/VirtualSystemHandler.java @@ -67,20 +67,23 @@ public class VirtualSystemHandler extends SectionHandler attributes = cleanseAttributes(attrs); - if (equalsOrSuffix(qName, "VirtualHardwareSection")) { - inHardware = true; - } else if (equalsOrSuffix(qName, "OperatingSystemSection")) { - inOs = true; - } else if (extensionHandlers.containsKey(qName)) { - inExtensionSection = true; - extensionHandler = extensionHandlers.get(qName).get(); - } else if (qName.endsWith("Section")) { - inSection = true; + depth++; + if (depth == 2) { + if (equalsOrSuffix(qName, "VirtualHardwareSection")) { + inHardware = true; + } else if (equalsOrSuffix(qName, "OperatingSystemSection")) { + inOs = true; + } else if (extensionHandlers.containsKey(qName)) { + inExtensionSection = true; + extensionHandler = extensionHandlers.get(qName).get(); + } else if (qName.endsWith("Section")) { + inSection = true; + } } - if (inHardware) { hardwareHandler.startElement(uri, localName, qName, attrs); } else if (inOs) { @@ -97,18 +100,21 @@ public class VirtualSystemHandler extends SectionHandler Date: Wed, 23 Mar 2011 17:50:57 -0700 Subject: [PATCH 3/3] added vm feature to savvis --- sandbox-providers/savvis-symphonyvpdc/pom.xml | 15 ++ .../jclouds/savvis/vpdc/VPDCAsyncClient.java | 11 +- .../org/jclouds/savvis/vpdc/VPDCClient.java | 11 +- .../vpdc/binders/BindVMSpecToXmlPayload.java | 201 ++++++++++++++++ .../VPDCComputeServiceContextModule.java | 14 +- .../vpdc/config/VPDCRestClientModule.java | 45 ++-- .../savvis/vpdc/domain/{VApp.java => VM.java} | 10 +- .../jclouds/savvis/vpdc/domain/VMSpec.java | 214 ++++++++++++++++++ .../vpdc/features/BrowsingAsyncClient.java | 20 +- .../savvis/vpdc/features/BrowsingClient.java | 10 +- .../savvis/vpdc/features/VMAsyncClient.java | 78 +++++++ .../savvis/vpdc/features/VMClient.java | 72 ++++++ ...VAppOptions.java => BindGetVMOptions.java} | 8 +- ...{GetVAppOptions.java => GetVMOptions.java} | 14 +- .../xml/{VAppHandler.java => VMHandler.java} | 14 +- .../predefined_operatingsystems.json | 2 +- .../savvis/vpdc/VPDCAsyncClientTest.java | 2 + .../binders/BindVMSpecToXmlPayloadTest.java | 66 ++++++ .../vpdc/features/BaseVPDCClientLiveTest.java | 16 +- .../features/BrowsingAsyncClientTest.java | 34 +-- .../vpdc/features/BrowsingClientLiveTest.java | 14 +- .../vpdc/features/VMAsyncClientTest.java | 103 +++++++++ .../vpdc/features/VMClientLiveTest.java | 140 ++++++++++++ .../src/test/resources/vm-default.xml | 1 + .../src/test/resources/vm-withdisks.xml | 18 ++ 25 files changed, 1036 insertions(+), 97 deletions(-) create mode 100644 sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/binders/BindVMSpecToXmlPayload.java rename sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/domain/{VApp.java => VM.java} (95%) create mode 100644 sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/domain/VMSpec.java create mode 100644 sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/features/VMAsyncClient.java create mode 100644 sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/features/VMClient.java rename sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/options/{BindGetVAppOptions.java => BindGetVMOptions.java} (74%) rename sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/options/{GetVAppOptions.java => GetVMOptions.java} (80%) rename sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/xml/{VAppHandler.java => VMHandler.java} (90%) create mode 100644 sandbox-providers/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/binders/BindVMSpecToXmlPayloadTest.java create mode 100644 sandbox-providers/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/features/VMAsyncClientTest.java create mode 100644 sandbox-providers/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/features/VMClientLiveTest.java create mode 100644 sandbox-providers/savvis-symphonyvpdc/src/test/resources/vm-default.xml create mode 100644 sandbox-providers/savvis-symphonyvpdc/src/test/resources/vm-withdisks.xml diff --git a/sandbox-providers/savvis-symphonyvpdc/pom.xml b/sandbox-providers/savvis-symphonyvpdc/pom.xml index acc3402847..fd7653ec81 100644 --- a/sandbox-providers/savvis-symphonyvpdc/pom.xml +++ b/sandbox-providers/savvis-symphonyvpdc/pom.xml @@ -56,6 +56,8 @@ 0.8 FIXME FIXME + FIXME + FIXME @@ -100,6 +102,11 @@ ${project.version} test + + com.jamesmurty.utils + java-xmlbuilder + 0.3 + @@ -134,6 +141,14 @@ test.savvis-symphonyvpdc.credential ${test.savvis-symphonyvpdc.credential} + + test.savvis-symphonyvpdc.loginUser + ${test.savvis-symphonyvpdc.loginUser} + + + test.savvis-symphonyvpdc.loginPassword + ${test.savvis-symphonyvpdc.loginPassword} + jclouds.compute.blacklist-nodes ${jclouds.compute.blacklist-nodes} diff --git a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/VPDCAsyncClient.java b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/VPDCAsyncClient.java index c08523e108..98a118fa6c 100644 --- a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/VPDCAsyncClient.java +++ b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/VPDCAsyncClient.java @@ -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 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 diff --git a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/VPDCClient.java b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/VPDCClient.java index 5d6b683436..956a052a70 100644 --- a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/VPDCClient.java +++ b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/VPDCClient.java @@ -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 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 diff --git a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/binders/BindVMSpecToXmlPayload.java b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/binders/BindVMSpecToXmlPayload.java new file mode 100644 index 0000000000..3bbf49f27d --- /dev/null +++ b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/binders/BindVMSpecToXmlPayload.java @@ -0,0 +1,201 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 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 bindToRequest(R request, Map 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 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"); + } + +} diff --git a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/compute/config/VPDCComputeServiceContextModule.java b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/compute/config/VPDCComputeServiceContextModule.java index cbcd0372d3..bccd56f516 100644 --- a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/compute/config/VPDCComputeServiceContextModule.java +++ b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/compute/config/VPDCComputeServiceContextModule.java @@ -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 VAPPSTATUS_TO_NODESTATE = ImmutableMap - . 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 VAPPSTATUS_TO_NODESTATE = ImmutableMap + . 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 provideVAppStatusToNodeState() { + protected Map provideVAppStatusToNodeState() { return VAPPSTATUS_TO_NODESTATE; } diff --git a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/config/VPDCRestClientModule.java b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/config/VPDCRestClientModule.java index 160a5ccd05..c2629169cd 100644 --- a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/config/VPDCRestClientModule.java +++ b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/config/VPDCRestClientModule.java @@ -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 provideOrgs(Supplier 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 successTester(Injector injector, - @Named(PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED) long completed) { + @Named(PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED) long completed) { return new RetryablePredicate(injector.getInstance(TaskSuccess.class), completed); } public static final Map, Class> DELEGATE_MAP = ImmutableMap., 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 provideOperatingSystems(Json json, @Provider String providerName) - throws IOException { - return json.fromJson(Strings2.toStringAndClose(getClass().getResourceAsStream( - "/" + providerName + "/predefined_operatingsystems.json")), new TypeLiteral>() { - }.getType()); + throws IOException { + return json.fromJson( + Strings2.toStringAndClose(getClass().getResourceAsStream( + "/" + providerName + "/predefined_operatingsystems.json")), + new TypeLiteral>() { + }.getType()); } @Provides @Singleton protected Supplier provideVCloudTokenCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds, - final LoginAsyncClient login) { + final LoginAsyncClient login) { return new MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier(authException, seconds, - new Supplier() { + new Supplier() { - @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 diff --git a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/domain/VApp.java b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/domain/VM.java similarity index 95% rename from sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/domain/VApp.java rename to sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/domain/VM.java index 310fef5f02..2e0e112cf9 100644 --- a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/domain/VApp.java +++ b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/domain/VM.java @@ -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 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 resourceAllocations) { super(id, name, type, href); this.status = status; diff --git a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/domain/VMSpec.java b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/domain/VMSpec.java new file mode 100644 index 0000000000..ef56b800aa --- /dev/null +++ b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/domain/VMSpec.java @@ -0,0 +1,214 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 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 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 dataDriveDeviceNameToSizeInGig; + + protected VMSpec(CIMOperatingSystem operatingSystem, float processorCount, int memoryInGig, String bootDeviceName, + int bootDriveSize, Map 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 getDataDiskDeviceNameToSizeInGig() { + return dataDriveDeviceNameToSizeInGig; + } + + @Override + public String toString() { + return "[operatingSystem=" + operatingSystem + ", processorCount=" + processorCount + ", memoryInGig=" + + memoryInGig + ", bootDeviceName=" + bootDeviceName + ", bootDriveSize=" + bootDriveSize + + ", dataDriveDeviceNameToSizeInGig=" + dataDriveDeviceNameToSizeInGig + "]"; + } + +} \ No newline at end of file diff --git a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/features/BrowsingAsyncClient.java b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/features/BrowsingAsyncClient.java index 4fdf388210..86ad518ca0 100644 --- a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/features/BrowsingAsyncClient.java +++ b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/features/BrowsingAsyncClient.java @@ -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 getNetworkInOrgAndVDC( + ListenableFuture 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 getVAppInOrgAndVDC( + ListenableFuture 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 diff --git a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/features/BrowsingClient.java b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/features/BrowsingClient.java index ca2037b12a..cb749a26e7 100644 --- a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/features/BrowsingClient.java +++ b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/features/BrowsingClient.java @@ -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. */ diff --git a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/features/VMAsyncClient.java b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/features/VMAsyncClient.java new file mode 100644 index 0000000000..574b1db53c --- /dev/null +++ b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/features/VMAsyncClient.java @@ -0,0 +1,78 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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. + *

+ * + * @see + * @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 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 removeVMFromVDC( + @PathParam("billingSiteId") @Nullable @ParamParser(DefaultOrgIfNull.class) String billingSiteId, + @PathParam("vpdcId") String vpdcId, @PathParam("vAppId") String vAppId); + +} diff --git a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/features/VMClient.java b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/features/VMClient.java new file mode 100644 index 0000000000..2c0bef2225 --- /dev/null +++ b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/features/VMClient.java @@ -0,0 +1,72 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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. + *

+ * + * @see + * @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 + *

+ *

Pre-conditions:

+ * + *
    + *
  • No snapshot has been created for the VM.
  • + *
  • For Balanced profile, the VM must not be associated with any firewall rule and/or included + * in a load balancing pool.
  • + *
+ * + * @param billingSiteId + * @param vpdcId + * @param vAppId + * @return + */ + Task removeVMFromVDC(String billingSiteId, String vpdcId, String vAppId); + +} \ No newline at end of file diff --git a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/options/BindGetVAppOptions.java b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/options/BindGetVMOptions.java similarity index 74% rename from sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/options/BindGetVAppOptions.java rename to sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/options/BindGetVMOptions.java index d5ccb99437..ed3f912db7 100644 --- a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/options/BindGetVAppOptions.java +++ b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/options/BindGetVMOptions.java @@ -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; @Inject - public BindGetVAppOptions(Provider uriBuilder) { + public BindGetVMOptions(Provider uriBuilder) { this.uriBuilder = uriBuilder; } @SuppressWarnings("unchecked") @Override public 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(); diff --git a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/options/GetVAppOptions.java b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/options/GetVMOptions.java similarity index 80% rename from sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/options/GetVAppOptions.java rename to sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/options/GetVMOptions.java index 587c919ca7..ef489e870c 100644 --- a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/options/GetVAppOptions.java +++ b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/options/GetVMOptions.java @@ -30,21 +30,21 @@ package org.jclouds.savvis.vpdc.options; * import static org.jclouds.savvis.vpdc.options.GetVAppOptions.Builder.* *

* - * vApp = context.getApi().getBrowsingClient().getVAppInOrgAndVDC(orgId, vdcId, vAppId, withPowerState()); + * vApp = context.getApi().getBrowsingClient().getVAppInVDC(orgId, vdcId, vAppId, withPowerState()); * * * @author Adrian Cole * @see */ -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(); } diff --git a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/xml/VAppHandler.java b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/xml/VMHandler.java similarity index 90% rename from sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/xml/VAppHandler.java rename to sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/xml/VMHandler.java index 4b812fea78..f7c65aaf96 100644 --- a/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/xml/VAppHandler.java +++ b/sandbox-providers/savvis-symphonyvpdc/src/main/java/org/jclouds/savvis/vpdc/xml/VMHandler.java @@ -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 { +public class VMHandler extends ParseSax.HandlerWithResult { 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 { .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")) diff --git a/sandbox-providers/savvis-symphonyvpdc/src/main/resources/savvis-symphonyvpdc/predefined_operatingsystems.json b/sandbox-providers/savvis-symphonyvpdc/src/main/resources/savvis-symphonyvpdc/predefined_operatingsystems.json index e34ba0fcf3..f92ff7541a 100644 --- a/sandbox-providers/savvis-symphonyvpdc/src/main/resources/savvis-symphonyvpdc/predefined_operatingsystems.json +++ b/sandbox-providers/savvis-symphonyvpdc/src/main/resources/savvis-symphonyvpdc/predefined_operatingsystems.json @@ -16,7 +16,7 @@ "osType": "RHEL" }, { - "family": "RHEL_64", + "family": "RHEL", "name": "rhel5_64Guest", "version": "5", "description": "Red Hat Enterprise Linux 5.x 64bit", diff --git a/sandbox-providers/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/VPDCAsyncClientTest.java b/sandbox-providers/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/VPDCAsyncClientTest.java index 59438c47dd..e5da8e2258 100644 --- a/sandbox-providers/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/VPDCAsyncClientTest.java +++ b/sandbox-providers/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/VPDCAsyncClientTest.java @@ -45,6 +45,7 @@ public class VPDCAsyncClientTest extends BaseVPDCAsyncClientTest + * + * ==================================================================== + * 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().> fromJson( + Strings2.toStringAndClose(getClass().getResourceAsStream( + "/savvis-symphonyvpdc/predefined_operatingsystems.json")), + new TypeLiteral>() { + }.getType()), new Predicate() { + + @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); + } +} diff --git a/sandbox-providers/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/features/BaseVPDCClientLiveTest.java b/sandbox-providers/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/features/BaseVPDCClientLiveTest.java index 4492b891e4..215b5dc094 100644 --- a/sandbox-providers/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/features/BaseVPDCClientLiveTest.java +++ b/sandbox-providers/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/features/BaseVPDCClientLiveTest.java @@ -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. of(new Log4JLoggingModule()), - overrides); + // context = new RestContextFactory().createContext(provider, ImmutableSet. of(new + // Log4JLoggingModule()), + // overrides); + injector = new RestContextFactory().createContextBuilder(provider, + ImmutableSet. of(new Log4JLoggingModule(), new JschSshClientModule()), overrides).buildInjector(); + context = injector.getInstance(Key.get(new TypeLiteral>() { + })); } @AfterGroups(groups = "live") diff --git a/sandbox-providers/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/features/BrowsingAsyncClientTest.java b/sandbox-providers/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/features/BrowsingAsyncClientTest.java index 69d72ac7a8..9742295fd2 100644 --- a/sandbox-providers/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/features/BrowsingAsyncClientTest.java +++ b/sandbox-providers/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/features/BrowsingAsyncClientTest.java @@ -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 + * + * ==================================================================== + * 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 { + + 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>() { + })), new Predicate() { + + @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> createTypeLiteral() { + return new TypeLiteral>() { + }; + } + +} diff --git a/sandbox-providers/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/features/VMClientLiveTest.java b/sandbox-providers/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/features/VMClientLiveTest.java new file mode 100644 index 0000000000..f4e380c236 --- /dev/null +++ b/sandbox-providers/savvis-symphonyvpdc/src/test/java/org/jclouds/savvis/vpdc/features/VMClientLiveTest.java @@ -0,0 +1,140 @@ +/** + * + * Copyright (C) 2010 Cloud Conscious, LLC. + * + * ==================================================================== + * 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 socketTester; + private RetryablePredicate 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(injector.getInstance(SocketOpen.class), 130, 10, TimeUnit.SECONDS);// make + taskTester = new RetryablePredicate(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>() { + })), new Predicate() { + + @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(); + } +} \ No newline at end of file diff --git a/sandbox-providers/savvis-symphonyvpdc/src/test/resources/vm-default.xml b/sandbox-providers/savvis-symphonyvpdc/src/test/resources/vm-default.xml new file mode 100644 index 0000000000..d4a58aae43 --- /dev/null +++ b/sandbox-providers/savvis-symphonyvpdc/src/test/resources/vm-default.xml @@ -0,0 +1 @@ +Specifies the operating system installedRed Hat Enterprise Linux 5.x 64bitVirtual HardwareVirtual Hardware FamilyDemoHost-11DemoHost-13 GHzNumber of Virtual CPUs1 CPU131GigabytesMemory SizeMemory241falseVM Tier01Network3101GigabytesHard Disk/boot42710 \ No newline at end of file diff --git a/sandbox-providers/savvis-symphonyvpdc/src/test/resources/vm-withdisks.xml b/sandbox-providers/savvis-symphonyvpdc/src/test/resources/vm-withdisks.xml new file mode 100644 index 0000000000..0de09a6782 --- /dev/null +++ b/sandbox-providers/savvis-symphonyvpdc/src/test/resources/vm-withdisks.xml @@ -0,0 +1,18 @@ + + + + 1.1.1.1 + 2.2.2.2 + + + allowInOut + + + + + + \ No newline at end of file