/***************************************************************************
* Copyright (c) 2012-2013 VMware, Inc. All Rights Reserved.
* 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 com.vmware.aurora.vc;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import com.vmware.aurora.util.AuAssert;
import com.vmware.aurora.vc.VcTask.TaskType;
import com.vmware.aurora.vc.VcTaskMgr.IVcPseudoTaskBody;
import com.vmware.aurora.vc.VcTaskMgr.IVcTaskBody;
import com.vmware.aurora.vc.vcevent.VcEventHandlers.VcEventType;
import com.vmware.aurora.vc.vcservice.VcContext;
import com.vmware.aurora.vc.vcservice.VcSession;
import com.vmware.vim.binding.impl.vim.ResourceConfigSpecImpl;
import com.vmware.vim.binding.vim.ClusterComputeResource;
import com.vmware.vim.binding.vim.Folder;
import com.vmware.vim.binding.vim.HttpNfcLease;
import com.vmware.vim.binding.vim.ImportSpec;
import com.vmware.vim.binding.vim.ManagedEntity;
import com.vmware.vim.binding.vim.ResourceAllocationInfo;
import com.vmware.vim.binding.vim.ResourceConfigSpec;
import com.vmware.vim.binding.vim.ResourcePool;
import com.vmware.vim.binding.vim.ResourcePool.ResourceUsage;
import com.vmware.vim.binding.vim.VirtualApp;
import com.vmware.vim.binding.vim.event.ResourcePoolCreatedEvent;
import com.vmware.vim.binding.vim.event.ResourcePoolEvent;
import com.vmware.vim.binding.vim.fault.DuplicateName;
import com.vmware.vim.binding.vim.vApp.ProductInfo;
import com.vmware.vim.binding.vim.vApp.VAppConfigSpec;
import com.vmware.vim.binding.vim.vm.ConfigSpec;
import com.vmware.vim.binding.vim.vm.FileInfo;
import com.vmware.vim.binding.vmodl.ManagedObject;
import com.vmware.vim.binding.vmodl.ManagedObjectReference;
import com.vmware.vim.binding.vmodl.fault.ManagedObjectNotFound;
public interface VcResourcePool extends VcObject {
/**
* @return the full path name
*/
abstract String getPath();
abstract boolean isVApp();
abstract String getVersion();
abstract String getFullVersion();
/**
* Returns the closest ancestor vApp of the current RP or null if
* this RP is not under any vApps.
* @return ancestor vApp RP.
*/
abstract VcResourcePool getAncestorVAppRp();
abstract boolean isHADRSCompatible();
abstract boolean isLeaf();
abstract boolean isRootRP();
/**
* @return reasons for the VC resource pool to be incompatible for resource bundle
*/
abstract List<String> getIncompatReasonsForRBQual();
/**
* @return true if the VC resource pool can be used in a resource bundle.
*/
abstract boolean isQualifiedResourceBundleRP();
/**
* @return the VC cluster that contains this resource pool
*/
abstract VcCluster getVcCluster();
/**
* @return the parent VC resource pool, null if the current is root.
*/
abstract VcResourcePool getParent();
/**
* Create a child resource pool
* @param name child resource pool name
* @param cpuAllocation
* @param memAllocation
* @return the new resource pool
* @throws Exception
*/
abstract VcResourcePool createChild(final String name,
final ResourceAllocationInfo cpuAllocation,
final ResourceAllocationInfo memAllocation) throws Exception;
/**
* Create a child resource pool
* @param name child resource pool name
* @param cpuAllocation
* @param memAllocation
* @param force true to suppress DuplicateName exception, and remove existing child RP
* false to throw DuplicateName exception.
* @return the new resource pool
* @throws Exception
*/
abstract VcResourcePool createChild(final String name,
final ResourceAllocationInfo cpuAllocation,
final ResourceAllocationInfo memAllocation,
final boolean force) throws Exception;
/**
* @return child resource pools
*/
abstract List<VcResourcePool> getChildren();
/**
* @return VMs under the resource pool
*/
abstract List<VcVirtualMachine> getChildVMs();
/**
* Import a VM template (step 1).
* @param spec VM template import spec
* @return lease used for uploading OVF files
* @throws Exception
* XXX do we really need to copy files from CMS to datastores?
* TODO: not tested
*/
abstract HttpNfcLease importVApp(ImportSpec spec) throws Exception;
/**
* Create a VM under the resource pool
* @param config VM configuration
* @param callback (optional) call-back function for the task
* @return task for the VM creation operation
* @throws Exception
* TODO: not tested
*/
abstract VcTask createVm(final ConfigSpec config,
final IVcTaskCallback callback, Folder folder) throws Exception;
abstract VcVirtualMachine createVm(ConfigSpec config, Folder folder) throws Exception;
/**
* Use this method when the VM needs to be created on a specific datastore
* and when it is not already captured in the input <code>config</code>.
* @throws Exception
*/
abstract VcVirtualMachine createVm(ConfigSpec config, VcDatastore ds)
throws Exception;
/**
* Use this method when the VM needs to be created on a specific datastore
* and in a specific vm folder
* @throws Exception
*/
abstract VcVirtualMachine createVm(ConfigSpec config, VcDatastore ds, Folder folder)
throws Exception;
/**
* Finds a VM by its name and deletes it.
*
* @throws Exception
*/
abstract void destroyVm(String vmName) throws Exception;
/**
* Remove all child resource pools recursively.
* @throws Exception
*/
abstract void destroyChildren() throws Exception;
/**
* Remove this resource pool.
* @throws Exception
*/
abstract void destroy() throws Exception;
/**
* Reconfigure resource settings.
* @name optional, to rename resource pool
* @cpuAllocation optional, change CPU allocation
* @memAllocation optional, change memory allocation
* @throws Exception
*/
abstract void updateConfig(final String name,
final ResourceAllocationInfo cpuAllocation,
final ResourceAllocationInfo memAllocation) throws Exception;
/**
* Reconfigure version and fullVersion for vApp
* @version
* @fullVersion
* @throws Exception
*
*/
abstract void updateVAppConfig(VAppConfigSpec spec) throws Exception;
abstract ResourceAllocationInfo getCpuAllocationInfo();
abstract ResourceAllocationInfo getMemAllocationInfo();
abstract ResourceUsage getCpuUsageInfo();
abstract ResourceUsage getMemUsageInfo();
abstract String getName();
}
@SuppressWarnings("serial")
class VcResourcePoolImpl extends VcObjectImpl implements VcResourcePool {
private String path; // full path of the resource pool from the cluster
private String name; // name of the resource pool
private ManagedObjectReference owner; // the cluster that contains the resource pool
private List<ManagedObjectReference> childVMs;
private ManagedObjectReference parent;
private boolean isVApp;
private String version;
private String fullVersion;
private ResourceAllocationInfo cpuAlloc;
private ResourceAllocationInfo memAlloc;
// Usage fields
private ResourceUsage cpuUsage;
private ResourceUsage memUsage;
/**
* Sync request to send update requests for a subtree of RPs.
*/
protected static class SyncRequest extends VcInventory.SyncRequest {
SyncRequest(ManagedObjectReference moRef, VcInventory.SyncRequest parent) {
super(moRef, parent);
}
@Override
protected void syncChildObjects(VcObject obj) {
if (obj instanceof VcResourcePoolImpl) {
VcResourcePoolImpl rp = (VcResourcePoolImpl)obj;
for (ManagedObjectReference child : rp.getChildRps()) {
add(new SyncRequest(child, this));
}
}
}
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcResourcePool#getPath()
*/
@Override
public String getPath() { return path; }
@Override
protected void update(ManagedObject mo) throws Exception {
ResourcePool rp = (ResourcePool)mo;
childVMs = Arrays.asList(rp.getVm());
owner = rp.getOwner();
parent = rp.getParent();
name = rp.getName();
isVApp = (rp instanceof VirtualApp);
if (isVApp) {
VirtualApp vapp = (VirtualApp)mo;
ProductInfo[] pInfo = vapp.getVAppConfig().getProduct();
version = pInfo[0].getVersion();
fullVersion = pInfo[0].getFullVersion();
}
ResourceConfigSpec config = rp.getConfig();
cpuAlloc = config.getCpuAllocation();
memAlloc = config.getMemoryAllocation();
// XXX: The cpuUsgae and memUsgae should really belong
// to the runtime info. We putting them into configuration category is
// to temporarily fix bug 865341 in Borealis. Should be refactorred later.
ResourcePool.RuntimeInfo runtime = rp.getRuntime();
cpuUsage = runtime.getCpu();
memUsage = runtime.getMemory();
for (ManagedObjectReference vmRef : childVMs) {
VcCache.putVmRpPair(vmRef, getMoRef());
}
updatePath();
}
@Override
protected void updateRuntime(ManagedObject mo) throws Exception {
ResourcePool rp = (ResourcePool)mo;
ResourcePool.RuntimeInfo runtime = rp.getRuntime();
cpuUsage = runtime.getCpu();
memUsage = runtime.getMemory();
}
protected VcResourcePoolImpl(ResourcePool rp) throws Exception {
super(rp);
update(rp);
updateRuntime(rp);
}
/**
* Slow way to load an RP, because we need to construct the RP paths
* from the VC RP tree and we cannot use VC cache to lookup parents.
* @param rp
* @return path to RP
* @throws Exception
*/
private static String calculatePathSlow(ResourcePool rp) throws Exception {
LinkedList<ResourcePool> rpStack = new LinkedList<ResourcePool>();
while (rp != null) {
ManagedEntity parent = MoUtil.getManagedObject(rp.getParent());
AuAssert.check(parent != null);
if (!(parent instanceof ResourcePool)) {
// skip the root RP's name in the path
break;
}
rpStack.addFirst(rp);
rp = (ResourcePool)parent;
}
// Path is encoded as: [cluster]/path/to/rpName
StringBuffer pathBuf = new StringBuffer();
ClusterComputeResource cluster = MoUtil.getManagedObject(rp.getOwner());
pathBuf.append('[').append(MoUtil.fromURLString(cluster.getName())).append(']');
for (ResourcePool r : rpStack) {
pathBuf.append("/").append(MoUtil.fromURLString(r.getName()));
}
return pathBuf.toString();
}
/*
* Calculate and update the path in the resource tree.
*
* Note: Cannot use VcCache.get() because this function is called by a
* CmsWorker thread.
*/
private void updatePath() throws Exception {
if (isRootRP()) {
VcCluster cluster = VcCache.lookup(owner);
if (cluster != null) {
path = '[' + cluster.getName() + ']';
return;
}
} else {
VcResourcePool parentRP = VcCache.lookup(parent);
if (parentRP != null) {
path = parentRP.getPath() + "/" + getName();
return;
}
}
path = calculatePathSlow((ResourcePool)getManagedObject());
return;
}
@Override
public String toString() {
Long cpuLimit = cpuAlloc.getLimit();
Long cpuReservation = cpuAlloc.getReservation();
Long memLimit = memAlloc.getLimit();
Long memReservation = memAlloc.getReservation();
return String.format("RP[%s](cpu:R=%d,L=%d,mem:R=%d,L=%d,#vm=%d)", path,
cpuReservation, cpuLimit, memReservation, memLimit, childVMs.size());
}
private List<ManagedObjectReference> getChildRps() {
ResourcePool rp = null;
if (VcContext.isInSession()) {
rp = getManagedObject();
} else {
rp = VcContext.inVcSessionDo(new VcSession<ResourcePool>() {
@Override
protected ResourcePool body() throws Exception {
return getManagedObject();
}
});
}
return Arrays.asList(rp.getResourcePool());
}
@Override
public boolean isLeaf() {
return getChildRps().isEmpty();
}
@Override
public boolean isVApp() {
return isVApp;
}
@Override
public String getVersion() {
return version;
}
@Override
public String getFullVersion() {
return fullVersion;
}
@Override
public VcResourcePool getAncestorVAppRp() {
VcResourcePool parentRp = this;
while ((parentRp = parentRp.getParent()) != null) {
if (parentRp.isVApp()) {
return parentRp;
}
}
return null;
}
/**
* Helper class to define a walker routine for traversing a ResourcePool tree.
*/
abstract static class RPWalker<T> {
/*
* The list that holds objects to be returned.
*/
public List<T> results;
public RPWalker() {
results = new ArrayList<T>();
}
/**
* @return true if needs to traverse child nodes
*/
abstract public boolean processRP(VcResourcePool rp) ;
}
/**
* Walk the resource pool in pre-order.
*
* @param <T> Class of data created by walker
* @param rp Root resource pool
* @param walker Tree traversing code
* @return the collection of data created by walker
* @throws Exception
*/
private static <T> List<T>
walkResourcePools(VcResourcePool rp, RPWalker<T> walker)
{
if (walker.processRP(rp)) {
for (VcResourcePool child : rp.getChildren()) {
walkResourcePools(child, walker);
}
}
return walker.results;
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcResourcePool#isHADRSCompatible()
*/
@Override
public boolean isHADRSCompatible() {
return getVcCluster().getHADRSIncompatReasonsForAlert().isEmpty();
}
@Override
public List<String> getIncompatReasonsForRBQual() {
List<String> reasons = VcUtil.getCPUMemAllocIncompatReasons(cpuAlloc, memAlloc);
reasons.addAll(getVcCluster().getHADRSIncompatReasonsForRBQual());
return reasons;
}
@Override
public boolean isQualifiedResourceBundleRP() {
return getIncompatReasonsForRBQual().isEmpty();
}
private List<VcResourcePool>
getQualifiedRPsWork(final boolean forBundle) {
return walkResourcePools(this, new RPWalker<VcResourcePool>() {
public boolean processRP(VcResourcePool rp) {
if (rp.isVApp()) {
// If RP is a vapp, skip the subtree.
logger.debug("Skip VirtualApp RP " + rp.getName());
return false;
} if (!rp.isLeaf()) {
// Not a leaf not, visit the child RPs.
return true;
} else {
if (!forBundle || rp.isQualifiedResourceBundleRP()) {
results.add(rp);
}
return false;
}
}
});
}
/**
* Get RPs in the subtree qualified for resource bundle.
*/
protected List<VcResourcePool> getQualifiedRPs() {
return getQualifiedRPsWork(true);
}
/**
* Get all leaf RPs in the subtree.
*/
protected List<VcResourcePool> getAllRPs() {
return getQualifiedRPsWork(false);
}
/**
* Search for a resource pool that matches the path.
* The path should be in the form: "[clusterName]/rp1/rp2".
* @param path
* @return the matching resource pool, null if not found
* @throws Exception
*/
protected VcResourcePool searchRP(final String path) {
List<VcResourcePool> result =
walkResourcePools(this, new RPWalker<VcResourcePool>() {
public boolean processRP(VcResourcePool rp) {
if (rp.getPath().equals(path)) {
results.add(rp);
return false;
}
if (path.startsWith(rp.getPath())) {
return true;
}
return false;
}
});
if (result.isEmpty()) {
return null;
}
return result.get(0);
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcResourcePool#getVcCluster()
*/
@Override
public VcCluster getVcCluster() {
return VcCache.get(owner);
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcResourcePool#getParent()
*/
@Override
public VcResourcePool getParent() {
AuAssert.check(VcContext.isInSession());
if (isRootRP()) {
return null;
}
return VcCache.get(parent);
}
public VcResourcePool createChild(final String name,
final ResourceAllocationInfo cpuAllocation,
final ResourceAllocationInfo memAllocation) throws Exception {
return createChild(name, cpuAllocation, memAllocation, false);
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcResourcePool#createChild(java.lang.String, com.vmware.vim.binding.vim.ResourceAllocationInfo, com.vmware.vim.binding.vim.ResourceAllocationInfo)
*/
@Override
public VcResourcePool createChild(final String name,
final ResourceAllocationInfo cpuAllocation,
final ResourceAllocationInfo memAllocation,
final boolean force) throws Exception
{
final ResourceConfigSpec spec = new ResourceConfigSpecImpl(
null, null, null, cpuAllocation, memAllocation);
ManagedObjectReference ref =
VcContext.getTaskMgr().execPseudoTask("ResourcePool.createResourcePool",
VcEventType.ResourcePoolCreated, getMoRef(),
new IVcPseudoTaskBody() {
@Override
public final ManagedObjectReference body() throws Exception {
final ResourcePool rp = getManagedObject();
ManagedObjectReference child = null;
//at least execute once
while (true) {
try {
child = rp.createResourcePool(name, spec);
break;
} catch (DuplicateName ex) {
if (force) {
//suppress this exception, and remove duplicated RP, then retry.
update();
for (VcResourcePool vcChildRP : getChildren()) {
String childName = vcChildRP.getName();
if (childName.equals(name)) {
vcChildRP.destroy();
break;
}
}
} else {
throw ex;
}
}
}
return child;
}
});
try {
return VcCache.get(ref);
} catch (Exception e) {
// XXX fix exception here
logger.error(this + ":race detected in creating RP " + name, e);
throw new Exception("bad moref");
}
}
/**
* Returns "target moRef" for an RP event. For createResourcePool operation,
* we use parent moRef as the key (child moRef not available at start) and the
* target for the corresponding event is RP parent. In all other cases, target
* moRef is RP itself.
* @param event
* @return target moRef
*/
protected static ManagedObjectReference getEventTargetMoRef(ResourcePoolEvent event) {
if (event instanceof ResourcePoolCreatedEvent) {
ResourcePoolCreatedEvent rpCreatedEvent = (ResourcePoolCreatedEvent) event;
if (rpCreatedEvent != null) {
return rpCreatedEvent.getParent().getResourcePool();
}
} else if (event.getResourcePool() != null) {
return event.getResourcePool().getResourcePool();
}
return null;
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcResourcePool#getChildren()
*
* This function is used to explore RPs in the wild while they
* are being concurrently created/deleted to find candidates for
* RBs. Skip over stale/deleted RPs.
*/
@Override
public List<VcResourcePool> getChildren() {
return VcCache.getPartialList(getChildRps(), getMoRef());
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcResourcePool#getChildVMs()
*/
@Override
public List<VcVirtualMachine> getChildVMs() {
return VcCache.getPartialList(childVMs, getMoRef());
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcResourcePool#importVApp(com.vmware.vim.binding.vim.ImportSpec)
*/
@Override
public HttpNfcLease importVApp(ImportSpec spec) throws Exception {
AuAssert.check(VcContext.isInTaskSession());
ResourcePool rp = getManagedObject();
VcDatacenter dc = getVcCluster().getDatacenter();
return MoUtil.getManagedObject(rp.importVApp(spec, dc.getVmFolderMoRef(), null));
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcResourcePool#createVm(com.vmware.vim.binding.vim.vm.ConfigSpec, com.vmware.aurora.vc.IVcTaskCallback)
*/
@Override
public VcTask createVm(final ConfigSpec config, final IVcTaskCallback callback, final Folder folder)
throws Exception {
final VcDatacenter dc = getVcCluster().getDatacenter();
VcTask task = VcContext.getTaskMgr().execute(new IVcTaskBody() {
public VcTask body() throws Exception {
Folder vmFolder = folder;
if (vmFolder == null)
vmFolder = dc.getVmFolder();
return new VcTask(TaskType.CreateVm,
vmFolder.createVm(config, moRef, null), callback);
}
});
logger.debug("create_vm task " + "VM " + config.getName() +
" under " + this + " created");
return task;
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcResourcePool#createVm(com.vmware.vim.binding.vim.vm.ConfigSpec)
*/
@Override
public VcVirtualMachine createVm(ConfigSpec config, Folder vmFolder) throws Exception {
VcTask task = createVm(config, VcCache.getRefreshVcTaskCB(this), vmFolder);
VcVirtualMachine vm = (VcVirtualMachine) task.waitForCompletion();
return vm;
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcResourcePool#createVm(com.vmware.vim.binding.vim.vm.ConfigSpec, com.vmware.aurora.vc.VcDatastore)
*/
@Override
public VcVirtualMachine createVm(ConfigSpec config, VcDatastore ds)
throws Exception {
return createVm(config, ds, null);
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcResourcePool#createVm(com.vmware.vim.binding.vim.vm.ConfigSpec, com.vmware.aurora.vc.VcDatastore, com.vmware.vim.binding.vim.Folder)
*/
@Override
public VcVirtualMachine createVm(ConfigSpec config, VcDatastore ds, Folder vmFolder)
throws Exception {
String vmPathName = String.format("[%s]", ds.getURLName());
FileInfo info = new com.vmware.vim.binding.impl.vim.vm.FileInfoImpl();
info.setVmPathName(vmPathName);
AuAssert.check(config.getFiles() == null);
config.setFiles(info);
return createVm(config, vmFolder);
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcResourcePool#destroyVm(java.lang.String)
*/
@Override
public void destroyVm(String vmName) throws Exception {
for (ManagedObjectReference vm : childVMs) {
VcVirtualMachine vcVm = VcCache.getIgnoreMissing(vm);
if (vcVm != null) {
String vcVmName = vcVm.getName();
if (vcVmName != null && vmName.equals(vcVmName)) {
vcVm.destroy();
return;
}
}
}
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcResourcePool#destroyChildren()
*/
@Override
public void destroyChildren() throws Exception {
AuAssert.check(VcContext.isInTaskSession());
ResourcePool rp = getManagedObject();
rp.destroyChildren();
for (ManagedObjectReference rpRef : getChildRps()) {
VcCache.purge(rpRef);
}
update();
}
/**
* Remove this resource pool.
* @param callback (optional) task callback
* @throws Exception
*/
private VcTask destroy(final IVcTaskCallback callback) throws Exception {
VcTask task = VcContext.getTaskMgr().execute(new IVcTaskBody() {
public VcTask body() throws Exception {
final ResourcePool rp = getManagedObject();
return new VcTask(TaskType.DestroyRp, rp.destroy(), callback);
}
});
logger.debug("destroy_rp task RP " + this + " created");
return task;
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcResourcePool#destroy()
*/
@Override
public void destroy() throws Exception {
final ManagedObjectReference oldParent = parent;
try {
VcTask task = destroy(new IVcTaskCallback() {
@Override
public void completeCB(VcTask task) {
VcCache.purge(getMoRef());
VcCache.refresh(oldParent);
}
@Override
public void syncCB() {
VcCache.sync(oldParent);
}});
task.waitForCompletion();
} catch (ManagedObjectNotFound e) {
logger.info("cannot destroy " + this + ", not found.");
}
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcResourcePool#updateConfig(java.lang.String, com.vmware.vim.binding.vim.ResourceAllocationInfo, com.vmware.vim.binding.vim.ResourceAllocationInfo)
*/
@Override
public void updateConfig(final String name,
final ResourceAllocationInfo cpuAllocation,
final ResourceAllocationInfo memAllocation) throws Exception {
VcContext.getTaskMgr().execPseudoTask("ResourcePool.updateConfig",
VcEventType.ResourcePoolReconfigured, getMoRef(),
new IVcPseudoTaskBody() {
@Override
public ManagedObjectReference body() throws Exception {
final ResourcePool rp = getManagedObject();
ResourceConfigSpec spec = null;
if (cpuAllocation != null || memAllocation != null) {
spec = new ResourceConfigSpecImpl(
null, null, null, cpuAllocation, memAllocation);
}
rp.updateConfig(MoUtil.toURLString(name), spec);
update();
VcCache.refresh(parent); // to refresh its parent's cpu/mem usage
return getMoRef();
}
});
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcResourcePool#updateConfig(java.lang.String, com.vmware.vim.binding.vim.ResourceAllocationInfo, com.vmware.vim.binding.vim.ResourceAllocationInfo)
*/
@Override
public void updateVAppConfig(final VAppConfigSpec spec) throws Exception {
// We're not using pseudotask but invoking one time synchronously as this is a short call
// and updateVAppConfig also does not generate a specific event. This is also a one-time
// call if the version does not match the CMS version, which will happen after vum update.
final VirtualApp vapp = (VirtualApp)getManagedObject();
vapp.updateVAppConfig(spec);
update();
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcResourcePool#getCpuAllocationInfo()
*/
@Override
public ResourceAllocationInfo getCpuAllocationInfo() {
return cpuAlloc;
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcResourcePool#getMemAllocationInfo()
*/
@Override
public ResourceAllocationInfo getMemAllocationInfo() {
return memAlloc;
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcResourcePool#getCpuUsageInfo()
*/
@Override
public ResourceUsage getCpuUsageInfo() {
return cpuUsage;
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcResourcePool#getMemUsageInfo()
*/
@Override
public ResourceUsage getMemUsageInfo() {
return memUsage;
}
@Override
public boolean isRootRP() {
return !(MoUtil.isOfType(parent, ResourcePool.class) ||
MoUtil.isOfType(parent, VirtualApp.class));
}
/* (non-Javadoc)
* @see com.vmware.aurora.vc.VcResourcePool#getName()
*/
@Override
public String getName() {
return isRootRP() ? getPath() :
MoUtil.fromURLString(name);
}
}