diff --git a/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/options/VCloudTemplateOptions.java b/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/options/VCloudTemplateOptions.java index e119a98407..67eff71be7 100644 --- a/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/options/VCloudTemplateOptions.java +++ b/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/options/VCloudTemplateOptions.java @@ -18,11 +18,19 @@ */ package org.jclouds.vcloud.compute.options; +import static com.google.common.base.Objects.equal; + +import java.net.URI; import java.util.Map; import org.jclouds.compute.options.TemplateOptions; import org.jclouds.util.Preconditions2; +import org.jclouds.vcloud.domain.network.FenceMode; import org.jclouds.vcloud.domain.network.IpAddressAllocationMode; +import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions; + +import com.google.common.base.Objects; +import com.google.common.base.Objects.ToStringHelper; /** * Contains options supported in the {@code ComputeService#runNode} operation on @@ -60,14 +68,45 @@ public class VCloudTemplateOptions extends TemplateOptions implements Cloneable eTo.description(getDescription()); if (getIpAddressAllocationMode() != null) eTo.ipAddressAllocationMode(getIpAddressAllocationMode()); + if (getIpAddressAllocationMode() != null) + eTo.ipAddressAllocationMode(getIpAddressAllocationMode()); + if (getParentNetwork() != null) + eTo.parentNetwork(getParentNetwork()); + if (getFenceMode() != null) + eTo.fenceMode(getFenceMode()); } } private String description = null; private String customizationScript = null; private IpAddressAllocationMode ipAddressAllocationMode = null; + private URI parentNetwork = null; + private FenceMode fenceMode = null; - public static final VCloudTemplateOptions NONE = new VCloudTemplateOptions(); + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + VCloudTemplateOptions that = VCloudTemplateOptions.class.cast(o); + return super.equals(that) && equal(this.description, that.description) + && equal(this.customizationScript, that.customizationScript) + && equal(this.ipAddressAllocationMode, that.ipAddressAllocationMode) + && equal(this.parentNetwork, that.parentNetwork); + } + + @Override + public int hashCode() { + return Objects.hashCode(super.hashCode(), description, customizationScript, ipAddressAllocationMode, + parentNetwork); + } + + @Override + public ToStringHelper string() { + return super.string().add("description", description).add("customizationScript", customizationScript) + .add("ipAddressAllocationMode", ipAddressAllocationMode).add("parentNetwork", parentNetwork); + } /** * Optional description. Used for the Description of the vApp created by this @@ -96,29 +135,61 @@ public class VCloudTemplateOptions extends TemplateOptions implements Cloneable return this; } + /** + * Specifies the parentNetwork to connect the the network interfaces on the + * VMs to. + * + * @see InstantiateVAppTemplateOptions#addNetworkConfig + */ + public VCloudTemplateOptions parentNetwork(URI parentNetwork) { + this.parentNetwork = parentNetwork; + return this; + } + + /** + * How to connect to the parent network + * + * @see InstantiateVAppTemplateOptions#addNetworkConfig + */ + public VCloudTemplateOptions fenceMode(FenceMode fenceMode) { + this.fenceMode = fenceMode; + return this; + } + public static class Builder { /** * @see VCloudTemplateOptions#description */ public static VCloudTemplateOptions description(String description) { - VCloudTemplateOptions options = new VCloudTemplateOptions(); - return VCloudTemplateOptions.class.cast(options.description(description)); + return new VCloudTemplateOptions().description(description); } /** * @see VCloudTemplateOptions#customizationScript */ public static VCloudTemplateOptions customizationScript(String customizationScript) { - VCloudTemplateOptions options = new VCloudTemplateOptions(); - return VCloudTemplateOptions.class.cast(options.customizationScript(customizationScript)); + return new VCloudTemplateOptions().customizationScript(customizationScript); } /** * @see VCloudTemplateOptions#ipAddressAllocationMode */ public static VCloudTemplateOptions ipAddressAllocationMode(IpAddressAllocationMode ipAddressAllocationMode) { - VCloudTemplateOptions options = new VCloudTemplateOptions(); - return VCloudTemplateOptions.class.cast(options.ipAddressAllocationMode(ipAddressAllocationMode)); + return new VCloudTemplateOptions().ipAddressAllocationMode(ipAddressAllocationMode); + } + + /** + * @see VCloudTemplateOptions#parentNetwork(URI parentNetwork) + */ + public static VCloudTemplateOptions parentNetwork(URI parentNetwork) { + return new VCloudTemplateOptions().parentNetwork(parentNetwork); + } + + /** + * @see VCloudTemplateOptions#fenceMode(FenceMode) + */ + public static VCloudTemplateOptions fenceMode(FenceMode fenceMode) { + return new VCloudTemplateOptions().fenceMode(fenceMode); } // methods that only facilitate returning the correct object type @@ -177,6 +248,20 @@ public class VCloudTemplateOptions extends TemplateOptions implements Cloneable return ipAddressAllocationMode; } + /** + * @return parentNetwork to connect to the vms + */ + public URI getParentNetwork() { + return parentNetwork; + } + + /** + * @return FenceMode to connect the parent network with + */ + public FenceMode getFenceMode() { + return fenceMode; + } + // methods that only facilitate returning the correct object type /** @@ -233,47 +318,4 @@ public class VCloudTemplateOptions extends TemplateOptions implements Cloneable return VCloudTemplateOptions.class.cast(super.userMetadata(key, value)); } - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((customizationScript == null) ? 0 : customizationScript.hashCode()); - result = prime * result + ((description == null) ? 0 : description.hashCode()); - result = prime * result + ((ipAddressAllocationMode == null) ? 0 : ipAddressAllocationMode.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; - VCloudTemplateOptions other = (VCloudTemplateOptions) obj; - if (customizationScript == null) { - if (other.customizationScript != null) - return false; - } else if (!customizationScript.equals(other.customizationScript)) - return false; - if (description == null) { - if (other.description != null) - return false; - } else if (!description.equals(other.description)) - return false; - if (ipAddressAllocationMode != other.ipAddressAllocationMode) - return false; - return true; - } - - @Override - public String toString() { - return "[customizationScript=" + (customizationScript != null) + ", description=" + description - + ", ipAddressAllocationMode=" + ipAddressAllocationMode + ", inboundPorts=" - + inboundPorts + ", privateKey=" + (privateKey != null) + ", publicKey=" - + (publicKey != null) + ", runScript=" + (script != null) + ", port:seconds=" + port + ":" + seconds - + ", userMetadata: " + userMetadata + "]"; - } - } diff --git a/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/strategy/InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn.java b/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/strategy/InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn.java index 83300a54aa..19b36d7be2 100644 --- a/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/strategy/InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn.java +++ b/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/strategy/InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn.java @@ -47,17 +47,17 @@ import org.jclouds.vcloud.compute.options.VCloudTemplateOptions; import org.jclouds.vcloud.domain.GuestCustomizationSection; import org.jclouds.vcloud.domain.NetworkConnection; import org.jclouds.vcloud.domain.NetworkConnectionSection; +import org.jclouds.vcloud.domain.NetworkConnectionSection.Builder; import org.jclouds.vcloud.domain.Task; import org.jclouds.vcloud.domain.VApp; import org.jclouds.vcloud.domain.VAppTemplate; import org.jclouds.vcloud.domain.Vm; -import org.jclouds.vcloud.domain.NetworkConnectionSection.Builder; import org.jclouds.vcloud.domain.network.IpAddressAllocationMode; import org.jclouds.vcloud.domain.network.NetworkConfig; import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Predicate; -import com.google.common.base.Supplier; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableSet; @@ -73,31 +73,20 @@ public class InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployA protected final VCloudClient client; protected final Predicate successTester; protected final LoadingCache vAppTemplates; - protected final Supplier defaultNetworkConfig; + protected final NetworkConfigurationForNetworkAndOptions networkConfigurationForNetworkAndOptions; protected final String buildVersion; + @Inject protected InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn(VCloudClient client, - Predicate successTester, LoadingCache vAppTemplates, - Supplier defaultNetworkConfig, @BuildVersion String buildVersion) { + Predicate successTester, LoadingCache vAppTemplates, NetworkConfigurationForNetworkAndOptions networkConfigurationForNetworkAndOptions, + @BuildVersion String buildVersion) { this.client = client; this.successTester = successTester; this.vAppTemplates = vAppTemplates; - this.defaultNetworkConfig = defaultNetworkConfig; + this.networkConfigurationForNetworkAndOptions = networkConfigurationForNetworkAndOptions; this.buildVersion = buildVersion; } - - // TODO: filtering on "none" is a hack until we can filter on - // vAppTemplate.getNetworkConfigSection().getNetworkConfigs() where - // name = getChildren().NetworkConnectionSection.connection where ipallocationmode == none - Predicate networkWithNoIpAllocation = new Predicate() { - - @Override - public boolean apply(Network input) { - return "none".equals(input.getName()); - } - - }; /** * per john ellis at bluelock, vCloud Director 1.5 is more strict than earlier versions. @@ -124,54 +113,7 @@ public class InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployA public NodeAndInitialCredentials createNodeWithGroupEncodedIntoName(String group, String name, Template template) { // no sense waiting until failures occur later ComputerNameValidator.INSTANCE.validate(name); - - URI templateId = URI.create(template.getImage().getId()); - - VAppTemplate vAppTemplate = vAppTemplates.getUnchecked(templateId); - - if (vAppTemplate.getChildren().size() > 1) - throw new UnsupportedOperationException("we currently do not support multiple vms in a vAppTemplate " - + vAppTemplate); - - if (vAppTemplate.getNetworkSection().getNetworks().size() > 1) - throw new UnsupportedOperationException( - "we currently do not support multiple network connections in a vAppTemplate " + vAppTemplate); - - Network networkToConnect = get(vAppTemplate.getNetworkSection().getNetworks(), 0); - - NetworkConfig config; - // if we only have a disconnected network, let's add a new section for the upstream - // TODO: remove the disconnected entry - if (networkWithNoIpAllocation.apply(networkToConnect)) - config = defaultNetworkConfig.get(); - else - config = defaultNetworkConfig.get().toBuilder().networkName(networkToConnect.getName()).build(); - - // note that in VCD 1.5, the network name after instantiation will be the same as the parent - InstantiateVAppTemplateOptions options = addNetworkConfig(config); - - // TODO make disk size specifiable - // disk((long) ((template.getHardware().getVolumes().get(0).getSize()) * - // 1024 * 1024l)); - - String customizationScript = VCloudTemplateOptions.class.cast(template.getOptions()).getCustomizationScript(); - IpAddressAllocationMode ipAllocationMode = VCloudTemplateOptions.class.cast(template.getOptions()) - .getIpAddressAllocationMode(); - - String description = VCloudTemplateOptions.class.cast(template.getOptions()).getDescription(); - if (description == null) - description = vAppTemplate.getName(); - - options.description(description); - options.deploy(false); - options.powerOn(false); - - URI VDC = URI.create(template.getLocation().getId()); - - logger.debug(">> instantiating vApp vDC(%s) template(%s) name(%s) options(%s) ", VDC, templateId, name, options); - - VApp vAppResponse = client.getVAppTemplateClient().createVAppInVDCByInstantiatingTemplate(name, VDC, templateId, - options); + VApp vAppResponse = instantiateVAppFromTemplate(name, template); waitForTask(vAppResponse.getTasks().get(0)); logger.debug("<< instantiated VApp(%s)", vAppResponse.getName()); @@ -181,15 +123,17 @@ public class InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployA // per above check, we know there is only a single VM Vm vm = get(vAppResponse.getChildren(), 0); + VCloudTemplateOptions vOptions = VCloudTemplateOptions.class.cast(template.getOptions()); + // note we cannot do tasks in parallel or VCD will throw "is busy" errors // note we must do this before any other customizations as there is a dependency on // valid naming conventions before you can perform commands such as updateCPUCount logger.trace(">> updating customization vm(%s) name->(%s)", vm.getName(), name); - waitForTask(updateVmWithNameAndCustomizationScript(vm, name, customizationScript)); + waitForTask(updateVmWithNameAndCustomizationScript(vm, name, vOptions.getCustomizationScript())); logger.trace("<< updated customization vm(%s)", name); - ensureVmHasAllocationModeOrPooled(vAppResponse, ipAllocationMode); + ensureVmHasAllocationModeOrPooled(vAppResponse, vOptions.getIpAddressAllocationMode()); int cpuCount = new Double(getCores(template.getHardware())).intValue(); logger.trace(">> updating cpuCount(%d) vm(%s)", cpuCount, vm.getName()); @@ -213,13 +157,71 @@ public class InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployA getCredentialsFrom(vAppResponse)); } + + @VisibleForTesting + protected VApp instantiateVAppFromTemplate(String name, Template template) { + VCloudTemplateOptions vOptions = VCloudTemplateOptions.class.cast(template.getOptions()); + + URI templateId = URI.create(template.getImage().getId()); + VAppTemplate vAppTemplate = vAppTemplates.getUnchecked(templateId); + + if (vAppTemplate.getChildren().size() > 1) + throw new UnsupportedOperationException("we currently do not support multiple vms in a vAppTemplate " + + vAppTemplate); + + if (vAppTemplate.getNetworkSection().getNetworks().size() > 1) + throw new UnsupportedOperationException( + "we currently do not support multiple network connections in a vAppTemplate " + vAppTemplate); + + Network networkToConnect = get(vAppTemplate.getNetworkSection().getNetworks(), 0); + + + NetworkConfig config = networkConfigurationForNetworkAndOptions.apply(networkToConnect, vOptions); + + // note that in VCD 1.5, the network name after instantiation will be the same as the parent + InstantiateVAppTemplateOptions options = addNetworkConfig(config); + + // TODO make disk size specifiable + // disk((long) ((template.getHardware().getVolumes().get(0).getSize()) * + // 1024 * 1024l)); + + + + String description = VCloudTemplateOptions.class.cast(template.getOptions()).getDescription(); + if (description == null) + description = vAppTemplate.getName(); + + options.description(description); + options.deploy(false); + options.powerOn(false); + + URI VDC = URI.create(template.getLocation().getId()); + + logger.debug(">> instantiating vApp vDC(%s) template(%s) name(%s) options(%s) ", VDC, templateId, name, options); + + VApp vAppResponse = client.getVAppTemplateClient().createVAppInVDCByInstantiatingTemplate(name, VDC, templateId, + options); + return vAppResponse; + } + + // TODO: filtering on "none" is a hack until we can filter on + // vAppTemplate.getNetworkConfigSection().getNetworkConfigs() where + // name = getChildren().NetworkConnectionSection.connection where ipallocationmode == none + static Predicate networkWithNoIpAllocation = new Predicate() { + + @Override + public boolean apply(Network input) { + return "none".equals(input.getName()); + } + + }; + public void waitForTask(Task task) { if (!successTester.apply(task.getHref())) { throw new TaskStillRunningException(task); } } - /** * Naming constraints modifying a VM on a VApp in vCloud Director (at least v1.5) can be more * strict than those in a vAppTemplate. For example, while it is possible to instantiate a diff --git a/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/strategy/NetworkConfigurationForNetworkAndOptions.java b/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/strategy/NetworkConfigurationForNetworkAndOptions.java new file mode 100644 index 0000000000..10844990c9 --- /dev/null +++ b/apis/vcloud/src/main/java/org/jclouds/vcloud/compute/strategy/NetworkConfigurationForNetworkAndOptions.java @@ -0,0 +1,82 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.vcloud.compute.strategy; + +import java.net.URI; + +import javax.inject.Inject; + +import org.jclouds.ovf.Network; +import org.jclouds.vcloud.compute.options.VCloudTemplateOptions; +import org.jclouds.vcloud.domain.network.FenceMode; +import org.jclouds.vcloud.domain.network.NetworkConfig; + +import com.google.common.annotations.Beta; +import com.google.common.base.Supplier; + +/** + * + * @author Adrian Cole + */ +@Beta +public class NetworkConfigurationForNetworkAndOptions { + protected final Supplier defaultNetworkConfig; + protected final FenceMode defaultFenceMode; + + @Inject + protected NetworkConfigurationForNetworkAndOptions(Supplier defaultNetworkConfig, + FenceMode defaultFenceMode) { + this.defaultNetworkConfig = defaultNetworkConfig; + this.defaultFenceMode = defaultFenceMode; + } + + /** + * + * returns a {@link NetworkConfig} used to instantiate a vAppTemplate to + * either the default parent (org) network, or one specified by options. + * + * @param networkToConnect + * network defined in the VAppTemplate you wish to connect to + * @param vOptions + * options to override defaults with + * @return + */ + public NetworkConfig apply(Network networkToConnect, VCloudTemplateOptions vOptions) { + NetworkConfig config; + URI userDefinedParentNetwork = vOptions.getParentNetwork(); + FenceMode fenceMode = vOptions.getFenceMode() != null ? vOptions.getFenceMode() : defaultFenceMode; + if (userDefinedParentNetwork != null) { + config = NetworkConfig.builder().networkName("jclouds").fenceMode(fenceMode) + .parentNetwork(userDefinedParentNetwork).build(); + } else { + config = defaultNetworkConfig.get().toBuilder().fenceMode(fenceMode).build(); + } + + // if we only have a disconnected network, we are adding a new section + // for the upstream + if (InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn.networkWithNoIpAllocation + .apply(networkToConnect)) { + // TODO: remove the disconnected entry + } else { + config = config.toBuilder().networkName(networkToConnect.getName()).build(); + } + return config; + } + +} \ No newline at end of file diff --git a/apis/vcloud/src/test/java/org/jclouds/vcloud/compute/options/VCloudTemplateOptionsTest.java b/apis/vcloud/src/test/java/org/jclouds/vcloud/compute/options/VCloudTemplateOptionsTest.java index 50c32ec50c..4f47d80aee 100644 --- a/apis/vcloud/src/test/java/org/jclouds/vcloud/compute/options/VCloudTemplateOptionsTest.java +++ b/apis/vcloud/src/test/java/org/jclouds/vcloud/compute/options/VCloudTemplateOptionsTest.java @@ -23,9 +23,11 @@ import static org.jclouds.vcloud.compute.options.VCloudTemplateOptions.Builder.c import static org.jclouds.vcloud.compute.options.VCloudTemplateOptions.Builder.description; import static org.jclouds.vcloud.compute.options.VCloudTemplateOptions.Builder.inboundPorts; import static org.jclouds.vcloud.compute.options.VCloudTemplateOptions.Builder.ipAddressAllocationMode; +import static org.jclouds.vcloud.compute.options.VCloudTemplateOptions.Builder.parentNetwork; import static org.testng.Assert.assertEquals; import java.io.IOException; +import java.net.URI; import org.jclouds.compute.options.TemplateOptions; import org.jclouds.vcloud.domain.network.IpAddressAllocationMode; @@ -81,6 +83,25 @@ public class VCloudTemplateOptionsTest { assertEquals(options.getCustomizationScript(), "mykeypair"); } + @Test + public void testNullparentNetwork() { + VCloudTemplateOptions options = new VCloudTemplateOptions(); + assertEquals(options.getParentNetwork(), null); + } + + @Test + public void testparentNetwork() { + VCloudTemplateOptions options = new VCloudTemplateOptions(); + options.parentNetwork(URI.create("https://network")); + assertEquals(options.getParentNetwork(), URI.create("https://network")); + } + + @Test + public void testparentNetworkStatic() { + VCloudTemplateOptions options = parentNetwork(URI.create("https://network")); + assertEquals(options.getParentNetwork(), URI.create("https://network")); + } + @Test public void testdescription() { VCloudTemplateOptions options = new VCloudTemplateOptions(); diff --git a/apis/vcloud/src/test/java/org/jclouds/vcloud/compute/strategy/InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOnExpectTest.java b/apis/vcloud/src/test/java/org/jclouds/vcloud/compute/strategy/InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOnExpectTest.java index 7cd597f4a6..cdabd0da22 100644 --- a/apis/vcloud/src/test/java/org/jclouds/vcloud/compute/strategy/InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOnExpectTest.java +++ b/apis/vcloud/src/test/java/org/jclouds/vcloud/compute/strategy/InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOnExpectTest.java @@ -20,16 +20,25 @@ package org.jclouds.vcloud.compute.strategy; import static org.testng.Assert.assertEquals; +import java.net.URI; +import java.util.Properties; + import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeServiceAdapter.NodeAndInitialCredentials; +import org.jclouds.compute.domain.Template; import org.jclouds.domain.LoginCredentials; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.vcloud.compute.BaseVCloudComputeServiceExpectTest; +import org.jclouds.vcloud.compute.options.VCloudTemplateOptions; import org.jclouds.vcloud.domain.VApp; +import org.jclouds.vcloud.domain.network.FenceMode; import org.testng.annotations.Test; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.net.HttpHeaders; +import com.jamesmurty.utils.XMLBuilder; /** * @@ -39,28 +48,68 @@ import com.google.common.collect.ImmutableMap; public class InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOnExpectTest extends BaseVCloudComputeServiceExpectTest { - // TODO: finish me + String ns = "http://www.vmware.com/vcloud/v1"; + Properties outputProperties; + public InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOnExpectTest(){ + outputProperties = new Properties(); + outputProperties.put(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes"); + } + + HttpResponse successfulVersion1_0InstantiatedVApp = HttpResponse.builder() + .statusCode(200) + .message("HTTP/1.1 200 OK") + .payload(payloadFromResourceWithContentType("/instantiatedvapp.xml", "application/vnd.vmware.vcloud.vApp+xml")).build(); + + // TODO: finish me! @Test(enabled = false) public void testCreateNodeUsingVCloud1_0ApiAgainstVCloudDirector1_5WhenVAppTemplateHasNetworkNamedNone() throws Exception { - ComputeService compute = requestsSendResponses(ImmutableMap. builder().put( - versionsRequest, versionsResponseFromVCD1_5).put(version1_0LoginRequest, - successfulVersion1_0LoginResponseFromVCD1_5WithSingleOrg).put(version1_0GetOrgRequest, - successfulVersion1_0GetOrgResponseFromVCD1_5WithSingleTasksListVDCAndNetwork).put( - version1_0GetCatalogRequest, successfulVersion1_0GetCatalogResponseFromVCD1_5WithSingleTemplate).put( - version1_0GetCatalogItemRequest, successfulVersion1_0GetCatalogItemResponseFromVCD1_5ForTemplate).put( - version1_0GetVDCRequest, successfulVersion1_0GetVDCResponseFromVCD1_5WithSingleTemplateAndNetwork).put( - version1_0GetVAppTemplateRequest, - successfulVersion1_0GetVAppTemplateResponseFromVCD1_5WithSingleVMAndVDCParent).put( - version1_0GetOVFForVAppTemplateRequest, - successfulVersion1_0GetOVFForVAppTemplateResponseFromVCD1_5WithSingleVM).build()); + + String group = "group"; + String name = "group-abcd"; + + String instantiateXML = XMLBuilder.create("InstantiateVAppTemplateParams") + .a("xmlns", ns).a("xmlns:ovf", "http://schemas.dmtf.org/ovf/envelope/1") + .a("deploy", "false").a("name", name).a("powerOn", "false") + .e("Description").t("UbuntuServer-x64-2GB").up() + .e("InstantiationParams") + .e("NetworkConfigSection") + .e("ovf:Info").t("Configuration parameters for logical networks").up() + .e("NetworkConfig").a("networkName", "orgNet-jclouds-External") // NOTE not "None" + .e("Configuration") + .e("ParentNetwork").a("href", ENDPOINT + "/v1.0/network/" + networkId).up() + .e("FenceMode").t("bridged").up() + .up() + .up() + .up() + .up() + .e("Source").a("href", ENDPOINT + "/v1.0/vAppTemplate/" + templateId).up() + .e("AllEULAsAccepted").t("true").up() + .asString(outputProperties); + + HttpRequest version1_0InstantiateWithNetworkNamedSameAsOrgNetwork = HttpRequest.builder() + .method("POST") + .endpoint(URI.create(ENDPOINT + "/v1.0/vdc/" + vdcId + "/action/instantiateVAppTemplate")) + .headers(ImmutableMultimap. builder() + .put(HttpHeaders.ACCEPT, "application/vnd.vmware.vcloud.vApp+xml") + .put(HttpHeaders.COOKIE, "vcloud-token=" + sessionToken).build()) + .payload(payloadFromStringWithContentType(instantiateXML, "application/vnd.vmware.vcloud.instantiateVAppTemplateParams+xml")).build(); + + ComputeService compute = requestsSendResponses(ImmutableMap. builder() + .put(versionsRequest, versionsResponseFromVCD1_5) + .put(version1_0LoginRequest, successfulVersion1_0LoginResponseFromVCD1_5WithSingleOrg) + .put(version1_0GetOrgRequest, successfulVersion1_0GetOrgResponseFromVCD1_5WithSingleTasksListVDCAndNetwork) + .put(version1_0GetCatalogRequest, successfulVersion1_0GetCatalogResponseFromVCD1_5WithSingleTemplate) + .put(version1_0GetCatalogItemRequest, successfulVersion1_0GetCatalogItemResponseFromVCD1_5ForTemplate) + .put(version1_0GetVDCRequest, successfulVersion1_0GetVDCResponseFromVCD1_5WithSingleTemplateAndNetwork) + .put(version1_0GetVAppTemplateRequest, successfulVersion1_0GetVAppTemplateResponseFromVCD1_5WithSingleVMAndVDCParent) + .put(version1_0GetOVFForVAppTemplateRequest, successfulVersion1_0GetOVFForVAppTemplateResponseFromVCD1_5WithSingleVM) + .put(version1_0InstantiateWithNetworkNamedSameAsOrgNetwork, successfulVersion1_0InstantiatedVApp).build()); InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn starter = compute.getContext() .utils().injector().getInstance( InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn.class); - String group = "group"; - String name = "group-abcd"; NodeAndInitialCredentials appAndCreds = starter.createNodeWithGroupEncodedIntoName(group, name, compute .templateBuilder().build()); @@ -69,4 +118,59 @@ public class InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployA assertEquals(appAndCreds.getCredentials(), LoginCredentials.builder().user("root").password("fromVApp").build()); } + + public void testInstantiateVAppFromTemplateWhenUsingOverriddenNetworkAndFenceMode() + throws Exception { + + String name = "group-abcd"; + FenceMode fenceMode = FenceMode.NAT_ROUTED; + URI parentNetwork = URI.create(ENDPOINT + "/v1.0/network/" + "foooooooo"); + + String instantiateXML = XMLBuilder.create("InstantiateVAppTemplateParams") + .a("xmlns", ns).a("xmlns:ovf", "http://schemas.dmtf.org/ovf/envelope/1") + .a("deploy", "false").a("name", name).a("powerOn", "false") + .e("Description").t("UbuntuServer-x64-2GB").up() + .e("InstantiationParams") + .e("NetworkConfigSection") + .e("ovf:Info").t("Configuration parameters for logical networks").up() + .e("NetworkConfig").a("networkName", "jclouds") // NOTE not "None" + .e("Configuration") + .e("ParentNetwork").a("href", parentNetwork.toASCIIString()).up() + .e("FenceMode").t(fenceMode.toString()).up() + .up() + .up() + .up() + .up() + .e("Source").a("href", ENDPOINT + "/v1.0/vAppTemplate/" + templateId).up() + .e("AllEULAsAccepted").t("true").up() + .asString(outputProperties); + + HttpRequest version1_0InstantiateWithCustomizedNetwork = HttpRequest.builder() + .method("POST") + .endpoint(URI.create(ENDPOINT + "/v1.0/vdc/" + vdcId + "/action/instantiateVAppTemplate")) + .headers(ImmutableMultimap. builder() + .put(HttpHeaders.ACCEPT, "application/vnd.vmware.vcloud.vApp+xml") + .put(HttpHeaders.COOKIE, "vcloud-token=" + sessionToken).build()) + .payload(payloadFromStringWithContentType(instantiateXML, "application/vnd.vmware.vcloud.instantiateVAppTemplateParams+xml")).build(); + + ComputeService compute = requestsSendResponses(ImmutableMap. builder() + .put(versionsRequest, versionsResponseFromVCD1_5) + .put(version1_0LoginRequest, successfulVersion1_0LoginResponseFromVCD1_5WithSingleOrg) + .put(version1_0GetOrgRequest, successfulVersion1_0GetOrgResponseFromVCD1_5WithSingleTasksListVDCAndNetwork) + .put(version1_0GetCatalogRequest, successfulVersion1_0GetCatalogResponseFromVCD1_5WithSingleTemplate) + .put(version1_0GetCatalogItemRequest, successfulVersion1_0GetCatalogItemResponseFromVCD1_5ForTemplate) + .put(version1_0GetVDCRequest, successfulVersion1_0GetVDCResponseFromVCD1_5WithSingleTemplateAndNetwork) + .put(version1_0GetVAppTemplateRequest, successfulVersion1_0GetVAppTemplateResponseFromVCD1_5WithSingleVMAndVDCParent) + .put(version1_0GetOVFForVAppTemplateRequest, successfulVersion1_0GetOVFForVAppTemplateResponseFromVCD1_5WithSingleVM) + .put(version1_0InstantiateWithCustomizedNetwork, successfulVersion1_0InstantiatedVApp).build()); + + InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn starter = compute.getContext() + .utils().injector().getInstance( + InstantiateVAppTemplateWithGroupEncodedIntoNameThenCustomizeDeployAndPowerOn.class); + + Template template = compute.templateBuilder().build(); + template.getOptions().as(VCloudTemplateOptions.class).parentNetwork(parentNetwork).fenceMode(fenceMode); + starter.instantiateVAppFromTemplate(name, template); + + } } diff --git a/apis/vcloud/src/test/resources/instantiatedvapp.xml b/apis/vcloud/src/test/resources/instantiatedvapp.xml index ec9255e356..9d98c2daec 100644 --- a/apis/vcloud/src/test/resources/instantiatedvapp.xml +++ b/apis/vcloud/src/test/resources/instantiatedvapp.xml @@ -1,9 +1,13 @@ - - + + + + + OS-Ubuntu10.04_x64 + + + + + + \ No newline at end of file