blob: 7ed8579882376491d51574987cd287eb707ddbb9 [file] [log] [blame]
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.vcloud.director.v1_5.features;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkCustomizationSection;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkLeaseSettingsSection;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadata;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataFor;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkMetadataKeyAbsentFor;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkNetworkConfigSection;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkOvfEnvelope;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkOvfNetworkSection;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkOwner;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkProductSectionList;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.checkVAppTemplate;
import static org.jclouds.vcloud.director.v1_5.domain.Checks.metadataToMap;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jclouds.dmtf.ovf.NetworkSection;
import org.jclouds.vcloud.director.v1_5.AbstractVAppApiLiveTest;
import org.jclouds.vcloud.director.v1_5.domain.Link;
import org.jclouds.vcloud.director.v1_5.domain.Link.Rel;
import org.jclouds.vcloud.director.v1_5.domain.Metadata;
import org.jclouds.vcloud.director.v1_5.domain.MetadataEntry;
import org.jclouds.vcloud.director.v1_5.domain.Owner;
import org.jclouds.vcloud.director.v1_5.domain.ProductSectionList;
import org.jclouds.vcloud.director.v1_5.domain.Reference;
import org.jclouds.vcloud.director.v1_5.domain.Task;
import org.jclouds.vcloud.director.v1_5.domain.VAppTemplate;
import org.jclouds.vcloud.director.v1_5.domain.dmtf.Envelope;
import org.jclouds.vcloud.director.v1_5.domain.params.CloneVAppTemplateParams;
import org.jclouds.vcloud.director.v1_5.domain.section.CustomizationSection;
import org.jclouds.vcloud.director.v1_5.domain.section.LeaseSettingsSection;
import org.jclouds.vcloud.director.v1_5.domain.section.NetworkConfigSection;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
/**
* Tests the request/response behavior of {@link VAppTemplateApi}
*
* NOTE The environment MUST have at least one template configured
*
* @author Aled Sage
*/
@Test(groups = { "live", "user" }, singleThreaded = true, testName = "VAppTemplateApiLiveTest")
public class VAppTemplateApiLiveTest extends AbstractVAppApiLiveTest {
private String key;
private String val;
@AfterClass(alwaysRun = true, dependsOnMethods = { "cleanUpEnvironment" })
protected void tidyUp() {
if (key != null) {
try {
Task remove = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).remove(key);
taskDoneEventually(remove);
} catch (Exception e) {
logger.warn(e, "Error when deleting metadata entry '%s'", key);
}
}
}
private VAppTemplate cloneVAppTemplate(boolean waitForTask) throws Exception {
CloneVAppTemplateParams cloneVAppTemplateParams = CloneVAppTemplateParams.builder()
.source(Reference.builder().href(lazyGetVAppTemplate().getHref()).build()).isSourceDelete(false)
.name("clone").build();
VAppTemplate clonedVappTemplate = vdcApi.cloneVAppTemplate(vdcUrn, cloneVAppTemplateParams);
if (waitForTask) {
Task cloneTask = Iterables.getFirst(clonedVappTemplate.getTasks(), null);
assertNotNull(cloneTask, "vdcApi.cloneVAppTemplate returned VAppTemplate that did not contain any tasks");
assertTaskSucceeds(cloneTask);
}
return clonedVappTemplate;
}
@Test(description = "GET /vAppTemplate/{id}")
public void testGetVAppTemplate() {
vAppTemplate = vAppTemplateApi.get(vAppTemplateUrn);
checkVAppTemplate(vAppTemplate);
assertEquals(vAppTemplate.getId(), vAppTemplateUrn);
}
@Test(description = "GET /vAppTemplate/{id}/owner")
public void testGetVAppTemplateOwner() {
Owner owner = vAppTemplateApi.getOwner(vAppTemplateUrn);
checkOwner(owner);
assertEquals(owner.getUser(), vAppTemplateApi.get(vAppTemplateUrn).getOwner().getUser());
}
@Test(description = "GET /vAppTemplate/{id}/customizationSection")
public void testGetCustomizationSection() {
CustomizationSection customizationSection = vAppTemplateApi.getCustomizationSection(vAppTemplateUrn);
checkCustomizationSection(customizationSection);
}
@Test(description = "GET /vAppTemplate/{id}/productSections")
public void testGetProductSections() {
ProductSectionList productSectionList = vAppTemplateApi.getProductSections(vAppTemplateUrn);
checkProductSectionList(productSectionList);
}
@Test(description = "GET /vAppTemplate/{id}/leaseSettingsSection")
public void testGetLeaseSettingsSection() {
LeaseSettingsSection leaseSettingsSection = vAppTemplateApi.getLeaseSettingsSection(vAppTemplateUrn);
checkLeaseSettingsSection(leaseSettingsSection);
}
@Test(description = "GET /vAppTemplate/{id}/metadata", dependsOnMethods = { "testEditMetadataValue" })
public void testGetVAppTemplateMetadata() {
Metadata metadata = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).get();
checkMetadata(metadata);
}
// implicitly tested by testEditVAppTemplateMetadataValue, which first adds the metadata entry;
// otherwise no entry may exist
@Test(description = "GET /vAppTemplate/{id}/metadata/{key}", dependsOnMethods = { "testGetVAppTemplateMetadata" })
public void testGetMetadataValue() {
Metadata metadata = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).get();
MetadataEntry entry = Iterables.get(metadata.getMetadataEntries(), 0);
String val = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).get(entry.getKey());
assertEquals(val, entry.getValue());
}
@Test(description = "GET /vAppTemplate/{id}/networkConfigSection")
public void testGetVAppTemplateNetworkConfigSection() {
NetworkConfigSection networkConfigSection = vAppTemplateApi.getNetworkConfigSection(vAppTemplateUrn);
checkNetworkConfigSection(networkConfigSection);
}
@Test(description = "GET /vAppTemplate/{id}/networkSection")
public void testGetVAppTemplateNetworkSection() {
NetworkSection networkSection = vAppTemplateApi.getNetworkSection(vAppTemplateUrn);
checkOvfNetworkSection(networkSection);
}
@Test(description = "GET /vAppTemplate/{id}/ovf")
public void testGetVAppTemplateOvf() {
Envelope envelope = vAppTemplateApi.getOvf(vAppTemplateUrn);
checkOvfEnvelope(envelope);
}
@Test(description = "PUT /vAppTemplate/{id}")
public void testEditVAppTemplate() {
String name = name("myname-");
String description = name("Description ");
VAppTemplate template = VAppTemplate.builder().name(name).description(description).build();
final Task task = vAppTemplateApi.edit(vAppTemplateUrn, template);
assertTaskSucceeds(task);
VAppTemplate newTemplate = vAppTemplateApi.get(vAppTemplateUrn);
assertEquals(newTemplate.getName(), name);
assertEquals(newTemplate.getDescription(), description);
}
@Test(description = "POST /vAppTemplate/{id}/metadata", dependsOnMethods = { "testGetVAppTemplate" })
public void testEditMetadata() {
Metadata oldMetadata = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).get();
Map<String, String> oldMetadataMap = metadataToMap(oldMetadata);
key = name("key-");
val = name("value-");
final Task task = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).putAll(ImmutableMap.of(key, val));
assertTaskSucceeds(task);
Metadata newMetadata = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).get();
Map<String, String> expectedMetadataMap = ImmutableMap.<String, String> builder().putAll(oldMetadataMap)
.put(key, val).build();
checkMetadataFor("vAppTemplate", newMetadata, expectedMetadataMap);
}
@Test(description = "PUT /vAppTemplate/{id}/metadata/{key}", dependsOnMethods = { "testEditMetadata" })
public void testEditMetadataValue() {
val = "new" + val;
final Task task = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).put(key, val);
retryTaskSuccess.apply(task);
String newMetadataValue = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).get(key);
assertEquals(newMetadataValue, val);
}
@Test(description = "DELETE /vAppTemplate/{id}/metadata/{key}", dependsOnMethods = { "testGetMetadataValue" })
public void testRemoveVAppTemplateMetadataValue() {
final Task deletionTask = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).remove(key);
assertTaskSucceeds(deletionTask);
Metadata newMetadata = vAppTemplateApi.getMetadataApi(vAppTemplateUrn).get();
checkMetadataKeyAbsentFor("vAppTemplate", newMetadata, key);
key = null;
}
// NOTE vAppTemplate supports only storageLease (deployment lease applies to vApp too)
@Test(description = "PUT /vAppTemplate/{id}/leaseSettingsSection")
public void testEditLeaseSettingsSection() throws Exception {
// NOTE use smallish number for storageLeaseInSeconds; it seems to be capped at 5184000?
int storageLeaseInSeconds = random.nextInt(10000) + 1;
LeaseSettingsSection leaseSettingSection = LeaseSettingsSection.builder().info("my info")
.storageLeaseInSeconds(storageLeaseInSeconds).build();
final Task task = vAppTemplateApi.editLeaseSettingsSection(vAppTemplateUrn, leaseSettingSection);
assertTaskSucceeds(task);
LeaseSettingsSection newLeaseSettingsSection = vAppTemplateApi.getLeaseSettingsSection(vAppTemplateUrn);
assertEquals(newLeaseSettingsSection.getStorageLeaseInSeconds(), (Integer) storageLeaseInSeconds);
}
@Test(description = "DELETE /vAppTemplate/{id}", dependsOnMethods = { "testGetVAppTemplate" })
public void testRemoveVAppTemplate() throws Exception {
VAppTemplate clonedVappTemplate = cloneVAppTemplate(true);
// Confirm that "get" works pre-remove
VAppTemplate vAppTemplatePreDelete = vAppTemplateApi.get(clonedVappTemplate.getHref());
checkVAppTemplate(vAppTemplatePreDelete);
// Delete the template
final Task task = vAppTemplateApi.remove(clonedVappTemplate.getHref());
assertTaskSucceeds(task);
// Confirm that can't access post-remove, i.e. template has been removed
VAppTemplate removed = vAppTemplateApi.get(clonedVappTemplate.getHref());
assertNull(removed);
}
@Test(description = "POST /vAppTemplate/{id}/action/disableDownload")
public void testDisableVAppTemplateDownload() throws Exception {
vAppTemplateApi.disableDownload(vAppTemplateUrn);
// TODO Check that it really is disabled. The only thing I can see for determining this
// is the undocumented "download" link in the VAppTemplate. But that is brittle and we
// don't know what timing guarantees there are for adding/removing the link.
VAppTemplate vAppTemplate = vAppTemplateApi.get(vAppTemplateUrn);
Set<Link> links = vAppTemplate.getLinks();
assertTrue(Iterables.all(Iterables.transform(links, rel),
Predicates.not(Predicates.in(EnumSet.of(Link.Rel.DOWNLOAD_DEFAULT, Link.Rel.DOWNLOAD_ALTERNATE)))),
"Should not offer download link after disabling download: " + vAppTemplate);
}
@Test(description = "POST /vAppTemplate/{id}/action/enableDownload")
public void testEnableVAppTemplateDownload() throws Exception {
// First disable so that enable really has some work to do...
vAppTemplateApi.disableDownload(vAppTemplateUrn);
final Task task = vAppTemplateApi.enableDownload(vAppTemplateUrn);
assertTaskSucceedsLong(task);
// TODO Check that it really is enabled. The only thing I can see for determining this
// is the undocumented "download" link in the VAppTemplate. But that is brittle and we
// don't know what timing guarantees there are for adding/removing the link.
VAppTemplate vAppTemplate = vAppTemplateApi.get(vAppTemplateUrn);
Set<Link> links = vAppTemplate.getLinks();
assertTrue(
Iterables.any(Iterables.transform(links, rel),
Predicates.in(EnumSet.of(Link.Rel.DOWNLOAD_DEFAULT, Link.Rel.DOWNLOAD_ALTERNATE))),
"Should offer download link after enabling download: " + vAppTemplate);
}
private Function<Link, Link.Rel> rel = new Function<Link, Link.Rel>() {
@Override
public Rel apply(Link input) {
return input.getRel();
}
};
// This failed previously, but is passing now.
// However, it's not part of the official API so not necessary to assert it.
@Test(description = "test completed task not included in vAppTemplate")
public void testCompletedTaskNotIncludedInVAppTemplate() throws Exception {
// Kick off a task, and wait for it to complete
vAppTemplateApi.disableDownload(vAppTemplateUrn);
final Task task = vAppTemplateApi.enableDownload(vAppTemplateUrn);
assertTaskDoneEventually(task);
// Ask the VAppTemplate for its tasks, and the status of the matching task if it exists
VAppTemplate vAppTemplate = vAppTemplateApi.get(vAppTemplateUrn);
List<Task> tasks = vAppTemplate.getTasks();
for (Task contender : tasks) {
if (task.getId().equals(contender.getId())) {
Task.Status status = contender.getStatus();
if (EnumSet.of(Task.Status.QUEUED, Task.Status.PRE_RUNNING, Task.Status.RUNNING).contains(status)) {
fail("Task " + contender + " reported complete, but is included in VAppTemplate in status " + status);
}
}
}
}
}