Issue 112: added delete disk command

git-svn-id: http://jclouds.googlecode.com/svn/trunk@2506 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-12-23 06:13:59 +00:00
parent c53d246223
commit 082d5404a9
10 changed files with 469 additions and 74 deletions

View File

@ -45,8 +45,8 @@ public class ResourceAllocation implements Comparable<ResourceAllocation> {
private final String virtualQuantityUnits; private final String virtualQuantityUnits;
public ResourceAllocation(int id, String name, String description, ResourceType type, public ResourceAllocation(int id, String name, String description, ResourceType type,
String subType, String hostResource, Integer address, Integer addressOnParent, Integer parent, String subType, String hostResource, Integer address, Integer addressOnParent,
Boolean connected, long virtualQuantity, String virtualQuantityUnits) { Integer parent, Boolean connected, long virtualQuantity, String virtualQuantityUnits) {
this.id = id; this.id = id;
this.name = checkNotNull(name, "name"); this.name = checkNotNull(name, "name");
this.description = description; this.description = description;
@ -73,6 +73,12 @@ public class ResourceAllocation implements Comparable<ResourceAllocation> {
return BEFORE; return BEFORE;
if (this.id > that.id) if (this.id > that.id)
return AFTER; return AFTER;
if (this.addressOnParent != null && that.addressOnParent != null) {
if (this.addressOnParent < that.addressOnParent)
return BEFORE;
if (this.addressOnParent > that.addressOnParent)
return AFTER;
}
return 1; return 1;
} }

View File

@ -141,6 +141,7 @@ public class BindVAppConfigurationToXmlPayload implements MapBinder {
VAppConfiguration configuration) { VAppConfiguration configuration) {
for (ResourceAllocation disk : vApp.getResourceAllocationByType() for (ResourceAllocation disk : vApp.getResourceAllocationByType()
.get(ResourceType.DISK_DRIVE)) { .get(ResourceType.DISK_DRIVE)) {
if (!configuration.getDisksToDelete().contains(disk.getAddressOnParent()))
addDiskWithQuantity(sectionBuilder, disk); addDiskWithQuantity(sectionBuilder, disk);
} }
for (Long quantity : configuration.getDisks()) { for (Long quantity : configuration.getDisks()) {

View File

@ -37,8 +37,4 @@ public interface TerremarkVApp extends VApp {
NamedResource getVDC(); NamedResource getVDC();
NamedResource getComputeOptions();
NamedResource getCustomizationOptions();
} }

View File

@ -39,6 +39,7 @@ public class VAppConfiguration {
private Integer processorCount = null; private Integer processorCount = null;
private Long memory = null; private Long memory = null;
private List<Long> disks = Lists.newArrayList(); private List<Long> disks = Lists.newArrayList();
private List<Integer> disksToDelete = Lists.newArrayList();
/** /**
* The vApp name has the following requirements: Name can use uppercase and/or lowercase letters. * The vApp name has the following requirements: Name can use uppercase and/or lowercase letters.
@ -97,6 +98,24 @@ public class VAppConfiguration {
return this; return this;
} }
/**
* To remove a disk, you specify its addressOnParent.
*
* Ex.
*
* <pre>
* SortedSet&lt;ResourceAllocation&gt; disks = Sets.newTreeSet(vApp.getResourceAllocationByType().get(
* ResourceType.DISK_DRIVE));
* ResourceAllocation lastDisk = disks.last();
* VAppConfiguration config = deleteDiskWithAddressOnParent(lastDisk.getAddressOnParent());
* </pre>
*/
public VAppConfiguration deleteDiskWithAddressOnParent(int addressOnParent) {
checkArgument(addressOnParent > 0, "you cannot delete the system disk");
disksToDelete.add(addressOnParent);
return this;
}
public static class Builder { public static class Builder {
/** /**
@ -131,6 +150,14 @@ public class VAppConfiguration {
return options.addDisk(kilobytes); return options.addDisk(kilobytes);
} }
/**
* @see VAppConfiguration#deleteDiskWithAddressOnParent(int)
*/
public static VAppConfiguration deleteDiskWithAddressOnParent(int addressOnParent) {
VAppConfiguration options = new VAppConfiguration();
return options.deleteDiskWithAddressOnParent(addressOnParent);
}
} }
public Integer getProcessorCount() { public Integer getProcessorCount() {
@ -148,4 +175,8 @@ public class VAppConfiguration {
public String getName() { public String getName() {
return name; return name;
} }
public List<Integer> getDisksToDelete() {
return disksToDelete;
}
} }

View File

@ -45,43 +45,27 @@ import com.google.common.collect.ListMultimap;
public class TerremarkVAppImpl extends VAppImpl implements TerremarkVApp { public class TerremarkVAppImpl extends VAppImpl implements TerremarkVApp {
private final NamedResource vDC; private final NamedResource vDC;
private final NamedResource computeOptions;
private final NamedResource customizationOptions;
/** The serialVersionUID */ /** The serialVersionUID */
private static final long serialVersionUID = 8464716396538298809L; private static final long serialVersionUID = 8464716396538298809L;
public TerremarkVAppImpl(String id, String name, String type, URI location, VAppStatus status, public TerremarkVAppImpl(String id, String name, String type, URI location, VAppStatus status,
long size, NamedResource vDC, NamedResource computeOptions, NamedResource customizationOptions, long size, NamedResource vDC, ListMultimap<String, InetAddress> networkToAddresses,
ListMultimap<String, InetAddress> networkToAddresses,
String operatingSystemDescription, TerremarkVirtualSystem system, String operatingSystemDescription, TerremarkVirtualSystem system,
SortedSet<ResourceAllocation> resourceAllocations) { SortedSet<ResourceAllocation> resourceAllocations) {
super(id, name, location, status, size, networkToAddresses, operatingSystemDescription, system, super(id, name, location, status, size, networkToAddresses, operatingSystemDescription,
resourceAllocations); system, resourceAllocations);
this.vDC = vDC; this.vDC = vDC;
this.computeOptions = computeOptions;
this.customizationOptions = customizationOptions;
} }
public NamedResource getVDC() { public NamedResource getVDC() {
return vDC; return vDC;
} }
public NamedResource getComputeOptions() {
return computeOptions;
}
public NamedResource getCustomizationOptions() {
return customizationOptions;
}
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = super.hashCode(); int result = super.hashCode();
result = prime * result + ((computeOptions == null) ? 0 : computeOptions.hashCode());
result = prime * result
+ ((customizationOptions == null) ? 0 : customizationOptions.hashCode());
result = prime * result + ((vDC == null) ? 0 : vDC.hashCode()); result = prime * result + ((vDC == null) ? 0 : vDC.hashCode());
return result; return result;
} }
@ -95,16 +79,6 @@ public class TerremarkVAppImpl extends VAppImpl implements TerremarkVApp {
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
TerremarkVAppImpl other = (TerremarkVAppImpl) obj; TerremarkVAppImpl other = (TerremarkVAppImpl) obj;
if (computeOptions == null) {
if (other.computeOptions != null)
return false;
} else if (!computeOptions.equals(other.computeOptions))
return false;
if (customizationOptions == null) {
if (other.customizationOptions != null)
return false;
} else if (!customizationOptions.equals(other.customizationOptions))
return false;
if (vDC == null) { if (vDC == null) {
if (other.vDC != null) if (other.vDC != null)
return false; return false;
@ -113,4 +87,5 @@ public class TerremarkVAppImpl extends VAppImpl implements TerremarkVApp {
return true; return true;
} }
} }

View File

@ -71,8 +71,6 @@ public class TerremarkVAppHandler extends ParseSax.HandlerWithResult<TerremarkVA
private VAppStatus status; private VAppStatus status;
private int size; private int size;
private boolean skip; private boolean skip;
private NamedResource computeOptions;
private NamedResource customizationOptions;
private final ListMultimap<String, InetAddress> networkToAddresses = ArrayListMultimap.create(); private final ListMultimap<String, InetAddress> networkToAddresses = ArrayListMultimap.create();
private StringBuilder currentText = new StringBuilder(); private StringBuilder currentText = new StringBuilder();
private String operatingSystemDescription; private String operatingSystemDescription;
@ -81,8 +79,8 @@ public class TerremarkVAppHandler extends ParseSax.HandlerWithResult<TerremarkVA
public TerremarkVApp getResult() { public TerremarkVApp getResult() {
return new TerremarkVAppImpl(vApp.getId(), vApp.getName(), vApp.getType(), return new TerremarkVAppImpl(vApp.getId(), vApp.getName(), vApp.getType(),
vApp.getLocation(), status, size, vDC, computeOptions, customizationOptions, vApp.getLocation(), status, size, vDC, networkToAddresses,
networkToAddresses, operatingSystemDescription, system, allocations); operatingSystemDescription, system, allocations);
} }
public void startElement(String uri, String localName, String qName, Attributes attributes) public void startElement(String uri, String localName, String qName, Attributes attributes)
@ -96,11 +94,6 @@ public class TerremarkVAppHandler extends ParseSax.HandlerWithResult<TerremarkVA
if (qName.equals("Link")) { if (qName.equals("Link")) {
if (attributes.getValue(attributes.getIndex("type")).equals(VCloudMediaType.VDC_XML)) { if (attributes.getValue(attributes.getIndex("type")).equals(VCloudMediaType.VDC_XML)) {
vDC = Utils.newNamedResource(attributes); vDC = Utils.newNamedResource(attributes);
} else if (attributes.getValue(attributes.getIndex("name")).equals("Compute Options")) {
this.computeOptions = Utils.newNamedResource(attributes);
} else if (attributes.getValue(attributes.getIndex("name"))
.equals("Customization Options")) {
this.customizationOptions = Utils.newNamedResource(attributes);
} }
} else if (qName.equals("VApp")) { } else if (qName.equals("VApp")) {
vApp = Utils.newNamedResource(attributes); vApp = Utils.newNamedResource(attributes);

View File

@ -26,6 +26,7 @@ package org.jclouds.vcloud.terremark;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.vcloud.options.CloneVAppOptions.Builder.deploy; import static org.jclouds.vcloud.options.CloneVAppOptions.Builder.deploy;
import static org.jclouds.vcloud.terremark.domain.VAppConfiguration.Builder.changeNameTo; import static org.jclouds.vcloud.terremark.domain.VAppConfiguration.Builder.changeNameTo;
import static org.jclouds.vcloud.terremark.domain.VAppConfiguration.Builder.deleteDiskWithAddressOnParent;
import static org.jclouds.vcloud.terremark.options.TerremarkInstantiateVAppTemplateOptions.Builder.processorCount; import static org.jclouds.vcloud.terremark.options.TerremarkInstantiateVAppTemplateOptions.Builder.processorCount;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNotNull;
@ -34,6 +35,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.List;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -52,6 +54,7 @@ import org.jclouds.vcloud.VCloudMediaType;
import org.jclouds.vcloud.domain.Catalog; import org.jclouds.vcloud.domain.Catalog;
import org.jclouds.vcloud.domain.CatalogItem; import org.jclouds.vcloud.domain.CatalogItem;
import org.jclouds.vcloud.domain.NamedResource; import org.jclouds.vcloud.domain.NamedResource;
import org.jclouds.vcloud.domain.ResourceAllocation;
import org.jclouds.vcloud.domain.ResourceType; import org.jclouds.vcloud.domain.ResourceType;
import org.jclouds.vcloud.domain.Task; import org.jclouds.vcloud.domain.Task;
import org.jclouds.vcloud.domain.VAppStatus; import org.jclouds.vcloud.domain.VAppStatus;
@ -75,6 +78,7 @@ import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.inject.Injector; import com.google.inject.Injector;
/** /**
@ -351,6 +355,16 @@ public class TerremarkVCloudClientLiveTest extends VCloudClientLiveTest {
vApp.getResourceAllocationByType().get(ResourceType.MEMORY)).getVirtualQuantity(), vApp.getResourceAllocationByType().get(ResourceType.MEMORY)).getVirtualQuantity(),
1024); 1024);
assertEquals(vApp.getResourceAllocationByType().get(ResourceType.DISK_DRIVE).size(), 2); assertEquals(vApp.getResourceAllocationByType().get(ResourceType.DISK_DRIVE).size(), 2);
// extract the disks on the vApp sorted by addressOnParent
List<ResourceAllocation> disks = Lists.newArrayList(vApp.getResourceAllocationByType()
.get(ResourceType.DISK_DRIVE));
// delete the second disk
task = tmClient.configureVApp(vApp, deleteDiskWithAddressOnParent(disks.get(1).getAddressOnParent()));
assert successTester.apply(task.getId());
assert successTester.apply(tmClient.powerOnVApp(vApp.getId()).getId()); assert successTester.apply(tmClient.powerOnVApp(vApp.getId()).getId());
} }
@ -439,7 +453,7 @@ public class TerremarkVCloudClientLiveTest extends VCloudClientLiveTest {
.getInstance(SocketOpen.class), 130, 10, TimeUnit.SECONDS);// make it longer then .getInstance(SocketOpen.class), 130, 10, TimeUnit.SECONDS);// make it longer then
// default internet // default internet
// service timeout // service timeout
successTester = new RetryablePredicate<String>(injector.getInstance(TaskSuccess.class), 300, successTester = new RetryablePredicate<String>(injector.getInstance(TaskSuccess.class), 450,
10, TimeUnit.SECONDS); 10, TimeUnit.SECONDS);
} }

View File

@ -77,16 +77,17 @@ public class BindVAppConfigurationToXmlPayloadTest {
TerremarkVAppImpl vApp = new TerremarkVAppImpl("4213", "MyAppServer6", TerremarkVAppImpl vApp = new TerremarkVAppImpl("4213", "MyAppServer6",
"application/vnd.vmware.vcloud.vApp+xml", URI "application/vnd.vmware.vcloud.vApp+xml", URI
.create("https://services.vcloudexpress/terremark.com/api/v0.8/vapp/4213"), .create("https://services.vcloudexpress/terremark.com/api/v0.8/vapp/4213"),
VAppStatus.OFF, 4194304, null, null, null, ImmutableListMultimap VAppStatus.OFF, 4194304, null, ImmutableListMultimap.<String, InetAddress> of(),
.<String, InetAddress> of(), null, null, ImmutableSortedSet.of( null, null, ImmutableSortedSet.of(new ResourceAllocation(1, "n/a", null,
new ResourceAllocation(1, "n/a", null, ResourceType.PROCESSOR, null, null, ResourceType.PROCESSOR, null, null, null, null, null, null, 2, null),
null, null, null, null, 2, null), new ResourceAllocation(2, "n/a", new ResourceAllocation(2, "n/a", null, ResourceType.MEMORY, null, null,
null, ResourceType.MEMORY, null, null, null, null, null, null, null, null, null, null, 1024, null), new ResourceAllocation(9,
1024, null), new ResourceAllocation(9, "n/a", null, "n/a", null, ResourceType.DISK_DRIVE, null, "1048576", null, 0,
ResourceType.DISK_DRIVE, null, "1048576", null, 0, null, null, null, null, 209152, null)));
209152, null)));
String expected = Utils.toStringAndClose(getClass().getResourceAsStream("/terremark/configureVApp.xml")).replace("eduardo", "roberto"); String expected = Utils.toStringAndClose(
getClass().getResourceAsStream("/terremark/configureVApp.xml")).replace("eduardo",
"roberto");
Multimap<String, String> headers = Multimaps.synchronizedMultimap(HashMultimap Multimap<String, String> headers = Multimaps.synchronizedMultimap(HashMultimap
.<String, String> create()); .<String, String> create());
VAppConfiguration config = new VAppConfiguration().changeNameTo("roberto"); VAppConfiguration config = new VAppConfiguration().changeNameTo("roberto");
@ -106,4 +107,40 @@ public class BindVAppConfigurationToXmlPayloadTest {
verify(request); verify(request);
} }
public void testRemoveDisk() throws IOException {
TerremarkVAppImpl vApp = new TerremarkVAppImpl("4213", "MyAppServer6",
"application/vnd.vmware.vcloud.vApp+xml", URI
.create("https://services.vcloudexpress/terremark.com/api/v0.8/vapp/4213"),
VAppStatus.OFF, 4194304, null, ImmutableListMultimap.<String, InetAddress> of(),
null, null, ImmutableSortedSet.of(new ResourceAllocation(1, "n/a", null,
ResourceType.PROCESSOR, null, null, null, null, null, null, 2, null),
new ResourceAllocation(2, "n/a", null, ResourceType.MEMORY, null, null,
null, null, null, null, 1024, null), new ResourceAllocation(9,
"n/a", null, ResourceType.DISK_DRIVE, null, "1048576", null, 0,
null, null, 209152, null),new ResourceAllocation(9,
"n/a", null, ResourceType.DISK_DRIVE, null, "1048576", null, 1,
null, null, 209152, null)));
String expected = Utils.toStringAndClose(
getClass().getResourceAsStream("/terremark/configureVApp.xml")).replace("eduardo",
"MyAppServer6");
Multimap<String, String> headers = Multimaps.synchronizedMultimap(HashMultimap
.<String, String> create());
VAppConfiguration config = new VAppConfiguration().deleteDiskWithAddressOnParent(1);
GeneratedHttpRequest<?> request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
expect(request.getArgs()).andReturn(new Object[] { vApp, config }).atLeastOnce();
expect(request.getFirstHeaderOrNull("Content-Type")).andReturn(null).atLeastOnce();
expect(request.getHeaders()).andReturn(headers).atLeastOnce();
request.setPayload(expected);
replay(request);
BindVAppConfigurationToXmlPayload binder = injector
.getInstance(BindVAppConfigurationToXmlPayload.class);
Map<String, String> map = Maps.newHashMap();
binder.bindToRequest(request, map);
verify(request);
}
} }

View File

@ -29,8 +29,7 @@ import java.io.InputStream;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.URI; import java.net.URI;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.List;
import javax.ws.rs.core.MediaType;
import org.jclouds.http.functions.BaseHandlerTest; import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ParseSax;
@ -48,6 +47,7 @@ import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Lists;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Provides; import com.google.inject.Provides;
@ -118,22 +118,7 @@ public class TerremarkVAppHandlerTest extends BaseHandlerTest {
.create("https://services.vcloudexpress.terremark.com/api/v0.8/vapp/13850")); .create("https://services.vcloudexpress.terremark.com/api/v0.8/vapp/13850"));
assertEquals(result.getVDC(), new NamedResourceImpl("32", null, VCloudMediaType.VDC_XML, URI assertEquals(result.getVDC(), new NamedResourceImpl("32", null, VCloudMediaType.VDC_XML, URI
.create("https://services.vcloudexpress.terremark.com/api/v0.8/vdc/32"))); .create("https://services.vcloudexpress.terremark.com/api/v0.8/vdc/32")));
assertEquals(
result.getComputeOptions(),
new NamedResourceImpl(
"compute",
"Compute Options",
MediaType.APPLICATION_XML,
URI
.create("https://services.vcloudexpress.terremark.com/api/v0.8/vapp/13850/options/compute")));
assertEquals(
result.getCustomizationOptions(),
new NamedResourceImpl(
"customization",
"Customization Options",
MediaType.APPLICATION_XML,
URI
.create("https://services.vcloudexpress.terremark.com/api/v0.8/vapp/13850/options/customization")));
assertEquals(result.getSystem(), new TerremarkVirtualSystem(null, null, null, null, null, assertEquals(result.getSystem(), new TerremarkVirtualSystem(null, null, null, null, null,
null, null, null, null, null, null, "Virtual Hardware Family", 0, null, null, null, null, null, null, null, null, null, "Virtual Hardware Family", 0, null, null, null,
null, null, "adriantest1", "vmx-07")); null, null, "adriantest1", "vmx-07"));
@ -169,4 +154,64 @@ public class TerremarkVAppHandlerTest extends BaseHandlerTest {
result.getResourceAllocationByType().get(ResourceType.DISK_DRIVE)) result.getResourceAllocationByType().get(ResourceType.DISK_DRIVE))
.getVirtualQuantity()); .getVirtualQuantity());
} }
public void testGetVApp2disks() throws UnknownHostException {
InputStream is = getClass().getResourceAsStream("/terremark/get_vapp2disks.xml");
TerremarkVApp vApp = (TerremarkVApp) factory.create(
injector.getInstance(TerremarkVAppHandler.class)).parse(is);
assertEquals(vApp.getId(), 15639 + "");
assertEquals(vApp.getName(), "eduardo");
assertEquals(vApp.getStatus(), VAppStatus.OFF);
assertEquals(vApp.getSize().longValue(), 30408704);
assertEquals(vApp.getOperatingSystemDescription(), "Ubuntu Linux (32-bit)");
assertEquals(vApp.getLocation(), URI
.create("https://services.vcloudexpress.terremark.com/api/v0.8/vapp/15639"));
assertEquals(vApp.getVDC(), new NamedResourceImpl("32", null, VCloudMediaType.VDC_XML, URI
.create("https://services.vcloudexpress.terremark.com/api/v0.8/vdc/32")));
assertEquals(vApp.getSystem(), new TerremarkVirtualSystem(null, null, null, null, null,
null, null, null, null, null, null, "Virtual Hardware Family", 0, null, null, null,
null, null, "eduardo", "vmx-07"));
assertEquals(vApp.getNetworkToAddresses().get("Internal"), ImmutableList.of(InetAddress
.getByName("10.114.34.131")));
ResourceAllocation cpu = new ResourceAllocation(1, "2 virtual CPU(s)",
"Number of Virtual CPUs", ResourceType.PROCESSOR, null, null, null, null, null,
null, 2, "hertz * 10^6");
ResourceAllocation controller = new ResourceAllocation(3, "SCSI Controller 0",
"SCSI Controller", ResourceType.SCSI_CONTROLLER, "lsilogic", null, 0, null, null,
null, 1, null);
ResourceAllocation memory = new ResourceAllocation(2, "1024MB of memory", "Memory Size",
ResourceType.MEMORY, null, null, null, null, null, null, 1024, "byte * 2^20");
ResourceAllocation disk = new ResourceAllocation(9, "Hard Disk 1", null,
ResourceType.DISK_DRIVE, null, "4194304", null, 0, 3, null, 4194304, null);
ResourceAllocation disk2 = new ResourceAllocation(9, "Hard Disk 2", null,
ResourceType.DISK_DRIVE, null, "26214400", null, 1, 3, null, 26214400, null);
assertEquals(vApp.getResourceAllocations(), ImmutableSortedSet.of(cpu, controller, memory,
disk, disk2));
assertEquals(Iterables.getOnlyElement(
vApp.getResourceAllocationByType().get(ResourceType.PROCESSOR))
.getVirtualQuantity(), 2);
assertEquals(Iterables.getOnlyElement(
vApp.getResourceAllocationByType().get(ResourceType.SCSI_CONTROLLER))
.getVirtualQuantity(), 1);
assertEquals(Iterables.getOnlyElement(
vApp.getResourceAllocationByType().get(ResourceType.MEMORY)).getVirtualQuantity(),
1024);
// extract the disks on the vApp sorted by addressOnParent
List<ResourceAllocation> disks = Lists.newArrayList(vApp.getResourceAllocationByType()
.get(ResourceType.DISK_DRIVE));
assertEquals(disks.get(0).getVirtualQuantity(), 4194304);
assertEquals(disks.get(1).getVirtualQuantity(), 26214400);
}
} }

View File

@ -0,0 +1,297 @@
<VApp href="https://services.vcloudexpress.terremark.com/api/v0.8/vapp/15639"
type="application/vnd.vmware.vcloud.vApp+xml" name="eduardo" status="2"
size="30408704" xmlns="http://www.vmware.com/vcloud/v1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Link rel="up"
href="https://services.vcloudexpress.terremark.com/api/v0.8/vdc/32"
type="application/vnd.vmware.vcloud.vdc+xml" />
<Link rel="down"
href="https://services.vcloudexpress.terremark.com/api/v0.8/vapp/15639/options/compute"
type="application/xml" name="Compute Options" />
<Link rel="down"
href="https://services.vcloudexpress.terremark.com/api/v0.8/vapp/15639/options/customization"
type="application/xml" name="Customization Options" />
<Section xsi:type="q1:NetworkConnectionSectionType" xmlns="http://schemas.dmtf.org/ovf/envelope/1"
xmlns:q1="http://www.vmware.com/vcloud/v1">
<q1:NetworkConnection Network="Internal">
<q1:IpAddress>10.114.34.131</q1:IpAddress>
</q1:NetworkConnection>
</Section>
<OperatingSystemSection d2p1:id="45"
xmlns="http://schemas.dmtf.org/ovf/envelope/1" xmlns:d2p1="http://schemas.dmtf.org/ovf/envelope/1">
<Info>The kind of installed guest operating system</Info>
<Description>Ubuntu Linux (32-bit)</Description>
</OperatingSystemSection>
<Section xsi:type="q2:VirtualHardwareSection_Type" xmlns="http://schemas.dmtf.org/ovf/envelope/1"
xmlns:q2="http://www.vmware.com/vcloud/v1">
<Info>Virtual Hardware</Info>
<q2:System>
<AutomaticRecoveryAction xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" />
<AutomaticShutdownAction xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" />
<AutomaticStartupAction xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" />
<AutomaticStartupActionDelay
xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" />
<AutomaticStartupActionSequenceNumber
xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" />
<Caption xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" />
<ConfigurationDataRoot xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" />
<ConfigurationFile xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" />
<ConfigurationID xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" />
<CreationTime xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" />
<Description xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" />
<ElementName
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData">Virtual Hardware Family</ElementName>
<InstanceID
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData">0</InstanceID>
<LogDataRoot xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" />
<RecoveryFile xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" />
<SnapshotDataRoot xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" />
<SuspendDataRoot xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" />
<SwapFileDataRoot xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData" />
<VirtualSystemIdentifier
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData">eduardo</VirtualSystemIdentifier>
<VirtualSystemType
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData">vmx-07</VirtualSystemType>
</q2:System>
<q2:Item>
<Address xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<AddressOnParent xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<AllocationUnits
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">hertz * 10^6</AllocationUnits>
<AutomaticAllocation xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<AutomaticDeallocation xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Caption xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<ConsumerVisibility xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Description
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">Number of Virtual CPUs</Description>
<ElementName
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">2 virtual CPU(s)</ElementName>
<InstanceID
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">1</InstanceID>
<Limit xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<MappingBehavior xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<OtherResourceType xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Parent xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<PoolID xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Reservation xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<ResourceSubType xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<ResourceType
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">3</ResourceType>
<VirtualQuantity
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">2</VirtualQuantity>
<VirtualQuantityUnits
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">count</VirtualQuantityUnits>
<Weight xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
</q2:Item>
<q2:Item>
<Address xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<AddressOnParent xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<AllocationUnits
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">byte * 2^20</AllocationUnits>
<AutomaticAllocation xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<AutomaticDeallocation xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Caption xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<ConsumerVisibility xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Description
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">Memory Size</Description>
<ElementName
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">1024MB of memory</ElementName>
<InstanceID
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">2</InstanceID>
<Limit xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<MappingBehavior xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<OtherResourceType xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Parent xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<PoolID xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Reservation xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<ResourceSubType xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<ResourceType
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">4</ResourceType>
<VirtualQuantity
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">1024</VirtualQuantity>
<VirtualQuantityUnits
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">byte * 2^20</VirtualQuantityUnits>
<Weight xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
</q2:Item>
<q2:Item>
<Address
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">0</Address>
<AddressOnParent xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<AllocationUnits xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<AutomaticAllocation xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<AutomaticDeallocation xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Caption xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<ConsumerVisibility xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Description
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">SCSI Controller</Description>
<ElementName
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">SCSI Controller 0</ElementName>
<InstanceID
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">3</InstanceID>
<Limit xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<MappingBehavior xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<OtherResourceType xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Parent xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<PoolID xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Reservation xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<ResourceSubType
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">lsilogic</ResourceSubType>
<ResourceType
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">6</ResourceType>
<VirtualQuantity xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<VirtualQuantityUnits xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Weight xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
</q2:Item>
<q2:Item>
<Address xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<AddressOnParent
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">0</AddressOnParent>
<AllocationUnits xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<AutomaticAllocation xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<AutomaticDeallocation xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Caption xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<ConsumerVisibility xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Description xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<ElementName
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">Hard Disk 1</ElementName>
<HostResource
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">4194304</HostResource>
<InstanceID
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">9</InstanceID>
<Limit xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<MappingBehavior xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<OtherResourceType xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Parent
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">3</Parent>
<PoolID xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Reservation xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<ResourceSubType xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<ResourceType
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">17</ResourceType>
<VirtualQuantity
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">4194304</VirtualQuantity>
<VirtualQuantityUnits xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Weight xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
</q2:Item>
<q2:Item>
<Address xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<AddressOnParent
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">1</AddressOnParent>
<AllocationUnits xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<AutomaticAllocation xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<AutomaticDeallocation xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Caption xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<ConsumerVisibility xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Description xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<ElementName
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">Hard Disk 2</ElementName>
<HostResource
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">26214400</HostResource>
<InstanceID
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">9</InstanceID>
<Limit xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<MappingBehavior xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<OtherResourceType xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Parent
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">3</Parent>
<PoolID xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Reservation xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<ResourceSubType xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<ResourceType
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">17</ResourceType>
<VirtualQuantity
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData">26214400</VirtualQuantity>
<VirtualQuantityUnits xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
<Weight xsi:nil="true"
xmlns="http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData" />
</q2:Item>
</Section>
</VApp>