Merge branch 'master' into vim51_win8
Conflicts:
plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareContextFactory.java
Signed-off-by: Min Chen <[email protected]>
Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
Commit:
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/105bf713
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/105bf713
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/105bf713
Branch: refs/heads/master
Commit: 105bf7134ac9a8d80f818c928aae974af76a1a34
Parents: 1ce4d62 01d7fa4
Author: Min Chen <[email protected]>
Authored: Wed Feb 6 15:27:45 2013 -0800
Committer: Min Chen <[email protected]>
Committed: Wed Feb 6 15:27:45 2013 -0800
----------------------------------------------------------------------
.../user/firewall/CreateFirewallRuleCmd.java | 2 +-
client/tomcatconf/componentContext.xml.in | 1 +
core/src/com/cloud/storage/SnapshotVO.java | 10 +-
docs/en-US/console-proxy.xml | 160 ++++++++++++---
docs/en-US/prepare-system-vm-template.xml | 29 ++--
.../discovery/ApiDiscoveryServiceImpl.java | 16 +-
.../cloudstack/discovery/ApiDiscoveryTest.java | 18 +-
.../hypervisor/vmware/resource/VmwareResource.java | 52 +++++
.../server/auth/PlainTextUserAuthenticator.java | 3 -
scripts/vm/hypervisor/xenserver/vmops | 1 +
server/src/com/cloud/api/ApiServer.java | 3 +
server/src/com/cloud/network/NetworkModelImpl.java | 6 +-
.../src/com/cloud/server/ManagementServerImpl.java | 3 +-
.../src/com/cloud/storage/StorageManagerImpl.java | 7 +-
tools/cli/cloudmonkey/cloudmonkey.py | 4 +-
tools/git/prepare-commit-msg | 23 +-
ui/scripts/ui-custom/dashboard.js | 8 +-
.../cloud/utils/component/ComponentContext.java | 8 +
.../utils/crypt/EncryptionSecretKeyChecker.java | 5 +
utils/src/com/cloud/utils/db/Transaction.java | 6 +
utils/src/com/cloud/utils/net/NetUtils.java | 50 +++--
utils/test/com/cloud/utils/net/NetUtilsTest.java | 19 ++-
.../cloud/hypervisor/vmware/util/VmwareClient.java | 4 +-
23 files changed, 330 insertions(+), 108 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/105bf713/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
----------------------------------------------------------------------
diff --cc
plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
index 7b97d3d,841a535..51b463e
---
a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
+++
b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java
@@@ -493,7 -491,55 +497,55 @@@ public class VmwareResource implements
return answer;
}
-
+
+ private Answer execute(ResizeVolumeCommand cmd) {
+ String path = cmd.getPath();
+ String vmName = cmd.getInstanceName();
+ long newSize = cmd.getNewSize()/1024;
+
+ try {
+ VmwareHypervisorHost hyperHost =
getHyperHost(getServiceContext());
+ ManagedObjectReference morDc = hyperHost.getHyperHostDatacenter();
+ // find VM through datacenter (VM is not at the target host yet)
+ VirtualMachineMO vmMo = hyperHost.findVmOnPeerHyperHost(vmName);
+ if (vmMo == null) {
+ String msg = "VM " + vmName + " does not exist in VMware
datacenter";
+ s_logger.error(msg);
+ throw new Exception(msg);
+ }
+
+ Pair<VirtualDisk, String> vdisk = vmMo.getDiskDevice(path, false);
+ if(vdisk == null) {
+ if(s_logger.isTraceEnabled())
+ s_logger.trace("resize volume done (failed)");
+ throw new Exception("No such disk device: " + path);
+ }
+ VirtualDisk disk = vdisk.first();
+ long oldSize = disk.getCapacityInKB();
+ if (newSize < oldSize){
+ throw new Exception("VMware doesn't support shrinking volume
from larger size: " + oldSize+ " MB to a smaller size: " + newSize + " MB");
+ } else if(newSize == oldSize){
- return new ResizeVolumeAnswer(cmd, true, "success",
newSize*1024);
++ return new ResizeVolumeAnswer(cmd, true, "success",
newSize*1024);
+ }
+ disk.setCapacityInKB(newSize);
+
+ VirtualMachineConfigSpec vmConfigSpec = new
VirtualMachineConfigSpec();
+ VirtualDeviceConfigSpec deviceConfigSpec = new
VirtualDeviceConfigSpec();
+ deviceConfigSpec.setDevice(disk);
-
deviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.edit);
- vmConfigSpec.setDeviceChange(new VirtualDeviceConfigSpec[] {
deviceConfigSpec });
++
deviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.EDIT);
++ vmConfigSpec.getDeviceChange().add(deviceConfigSpec);
+ if (!vmMo.configureVm(vmConfigSpec)) {
+ throw new Exception("Failed to configure VM to resize disk.
vmName: " + vmName);
+ }
+
+ return new ResizeVolumeAnswer(cmd, true, "success", newSize*1024);
+ } catch (Exception e) {
+ s_logger.error("Unable to resize volume",e);
+ String error = "failed to resize volume:" +e;
+ return new ResizeVolumeAnswer(cmd, false, error );
+ }
+ }
+
protected Answer execute(CheckNetworkCommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource CheckNetworkCommand " +
_gson.toJson(cmd));
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/105bf713/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareClient.java
----------------------------------------------------------------------
diff --cc vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareClient.java
index 2e0238d,0000000..ae5f47f
mode 100644,000000..100644
--- a/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareClient.java
+++ b/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareClient.java
@@@ -1,510 -1,0 +1,512 @@@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF 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 com.cloud.hypervisor.vmware.util;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.HttpsURLConnection;
+import javax.xml.ws.BindingProvider;
+
+import com.vmware.vim25.DynamicProperty;
+import com.vmware.vim25.InvalidCollectorVersionFaultMsg;
+import com.vmware.vim25.InvalidPropertyFaultMsg;
+import com.vmware.vim25.LocalizedMethodFault;
+import com.vmware.vim25.ManagedObjectReference;
+import com.vmware.vim25.ObjectSpec;
+import com.vmware.vim25.ObjectUpdate;
+import com.vmware.vim25.ObjectUpdateKind;
+import com.vmware.vim25.PropertyChange;
+import com.vmware.vim25.PropertyChangeOp;
+import com.vmware.vim25.PropertyFilterSpec;
+import com.vmware.vim25.PropertyFilterUpdate;
+import com.vmware.vim25.PropertySpec;
+import com.vmware.vim25.RuntimeFaultFaultMsg;
+import com.vmware.vim25.SelectionSpec;
+import com.vmware.vim25.ServiceContent;
+import com.vmware.vim25.TaskInfoState;
+import com.vmware.vim25.TraversalSpec;
+import com.vmware.vim25.UpdateSet;
+import com.vmware.vim25.VimPortType;
+import com.vmware.vim25.VimService;
+import com.vmware.vim25.ObjectContent;
+
+/**
+ * A wrapper class to handle Vmware vsphere connection and disconnection.
+ *
+ * @author minc
+ *
+ */
+public class VmwareClient {
+
+ private ManagedObjectReference SVC_INST_REF = new
ManagedObjectReference();
+ private ManagedObjectReference propCollectorRef;
+ private ManagedObjectReference rootRef;
+ private VimService vimService;
+ private VimPortType vimPort;
+ private ServiceContent serviceContent;
+ private final String SVC_INST_NAME = "ServiceInstance";
+
+ private boolean isConnected = false;
+
+ public VmwareClient(String name) {
+
+ }
+
+ /**
+ * Establishes session with the virtual center server.
+ *
+ * @throws Exception
+ * the exception
+ */
+ public void connect(String url, String userName, String password) throws
Exception {
+
+ HostnameVerifier hv = new HostnameVerifier() {
+ @Override
+ public boolean verify(String urlHostName, SSLSession session) {
+ return true;
+ }
+ };
+ HttpsURLConnection.setDefaultHostnameVerifier(hv);
+
+ SVC_INST_REF.setType(SVC_INST_NAME);
+ SVC_INST_REF.setValue(SVC_INST_NAME);
+
+ vimService = new VimService();
+ vimPort = vimService.getVimPort();
+ Map<String, Object> ctxt = ((BindingProvider)
vimPort).getRequestContext();
+
+ ctxt.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url);
+ ctxt.put(BindingProvider.SESSION_MAINTAIN_PROPERTY, true);
- ctxt.put("com.sun.xml.internal.ws.request.timeout", 60000);
++
++ ctxt.put("com.sun.xml.internal.ws.request.timeout", 600000);
++ ctxt.put("com.sun.xml.internal.ws.connect.timeout", 600000);
+
+ serviceContent = vimPort.retrieveServiceContent(SVC_INST_REF);
+ vimPort.login(serviceContent.getSessionManager(), userName, password,
null);
+ isConnected = true;
+
+ propCollectorRef = serviceContent.getPropertyCollector();
+ rootRef = serviceContent.getRootFolder();
+ }
+
+ /**
+ * Disconnects the user session.
+ *
+ * @throws Exception
+ */
+ public void disconnect() throws Exception {
+ if (isConnected) {
+ vimPort.logout(serviceContent.getSessionManager());
+ }
+ isConnected = false;
+ }
+
+ /**
+ * @return Service instance
+ */
+ public VimPortType getService() {
+ return vimPort;
+ }
+
+ /**
+ * @return Service instance content
+ */
+ public ServiceContent getServiceContent() {
+ return serviceContent;
+ }
+
+ /**
+ * @return Service property collector
+ */
+ public ManagedObjectReference getPropCol() {
+ return propCollectorRef;
+ }
+
+ /**
+ * @return Root folder
+ */
+ public ManagedObjectReference getRootFolder() {
+ return rootRef;
+ }
+
+ /**
+ * Get the property value of a managed object.
+ *
+ * @param mor
+ * managed object reference
+ * @param propertyName
+ * property name.
+ * @return property value.
+ * @throws Exception
+ * in case of error.
+ */
+ public Object getDynamicProperty(ManagedObjectReference mor, String
propertyName) throws Exception {
+ List<String> props = new ArrayList<String>();
+ props.add(propertyName);
+ List<ObjectContent> objContent = this.getObjectProperties(mor, props);
+
+ Object propertyValue = null;
+ if (objContent != null && objContent.size() > 0) {
+ List<DynamicProperty> dynamicProperty =
objContent.get(0).getPropSet();
+ if (dynamicProperty != null && dynamicProperty.size() > 0) {
+ DynamicProperty dp = dynamicProperty.get(0);
+ propertyValue = dp.getVal();
+ /*
+ * If object is ArrayOfXXX object, then get the XXX[] by
+ * invoking getXXX() on the object.
+ * For Ex:
+ * ArrayOfManagedObjectReference.getManagedObjectReference()
+ * returns ManagedObjectReference[] array.
+ */
+ Class dpCls = propertyValue.getClass();
+ String dynamicPropertyName = dpCls.getName();
+ if (dynamicPropertyName.indexOf("ArrayOf") != -1) {
+ String methodName = "get"
+ + dynamicPropertyName
+
.substring(dynamicPropertyName.indexOf("ArrayOf") + "ArrayOf".length(),
dynamicPropertyName.length());
+
+ Method getMorMethod = dpCls.getDeclaredMethod(methodName,
null);
+ propertyValue = getMorMethod.invoke(propertyValue,
(Object[]) null);
+ }
+ }
+ }
+ return propertyValue;
+ }
+
+ private List<ObjectContent> getObjectProperties(ManagedObjectReference
mObj, List<String> props) throws Exception {
+ PropertySpec pSpec = new PropertySpec();
+ pSpec.setAll(false);
+ pSpec.setType(mObj.getType());
+ pSpec.getPathSet().addAll(props);
+
+ ObjectSpec oSpec = new ObjectSpec();
+ oSpec.setObj(mObj);
+ oSpec.setSkip(false);
+ PropertyFilterSpec spec = new PropertyFilterSpec();
+ spec.getPropSet().add(pSpec);
+ spec.getObjectSet().add(oSpec);
+ List<PropertyFilterSpec> specArr = new
ArrayList<PropertyFilterSpec>();
+ specArr.add(spec);
+
+ return vimPort.retrieveProperties(propCollectorRef, specArr);
+ }
+
+ /**
+ * This method returns a boolean value specifying whether the Task is
+ * succeeded or failed.
+ *
+ * @param task
+ * ManagedObjectReference representing the Task.
+ *
+ * @return boolean value representing the Task result.
+ * @throws InvalidCollectorVersionFaultMsg
+ * @throws RuntimeFaultFaultMsg
+ * @throws InvalidPropertyFaultMsg
+ */
+ public boolean waitForTask(ManagedObjectReference task) throws
InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, InvalidCollectorVersionFaultMsg {
+
+ boolean retVal = false;
+
+ // info has a property - state for state of the task
+ Object[] result = waitForValues(task, new String[] { "info.state",
"info.error" }, new String[] { "state" }, new Object[][] { new Object[] {
+ TaskInfoState.SUCCESS, TaskInfoState.ERROR } });
+
+ if (result[0].equals(TaskInfoState.SUCCESS)) {
+ retVal = true;
+ }
+ if (result[1] instanceof LocalizedMethodFault) {
+ throw new RuntimeException(((LocalizedMethodFault)
result[1]).getLocalizedMessage());
+ }
+ return retVal;
+ }
+
+ /**
+ * Handle Updates for a single object. waits till expected values of
+ * properties to check are reached Destroys the ObjectFilter when done.
+ *
+ * @param objmor
+ * MOR of the Object to wait for</param>
+ * @param filterProps
+ * Properties list to filter
+ * @param endWaitProps
+ * Properties list to check for expected values these be
+ * properties of a property in the filter properties list
+ * @param expectedVals
+ * values for properties to end the wait
+ * @return true indicating expected values were met, and false otherwise
+ * @throws RuntimeFaultFaultMsg
+ * @throws InvalidPropertyFaultMsg
+ * @throws InvalidCollectorVersionFaultMsg
+ */
+ private Object[] waitForValues(ManagedObjectReference objmor, String[]
filterProps, String[] endWaitProps, Object[][] expectedVals)
+ throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg,
InvalidCollectorVersionFaultMsg {
+ // version string is initially null
+ String version = "";
+ Object[] endVals = new Object[endWaitProps.length];
+ Object[] filterVals = new Object[filterProps.length];
+
+ PropertyFilterSpec spec = new PropertyFilterSpec();
+ ObjectSpec oSpec = new ObjectSpec();
+ oSpec.setObj(objmor);
+ oSpec.setSkip(Boolean.FALSE);
+ spec.getObjectSet().add(oSpec);
+
+ PropertySpec pSpec = new PropertySpec();
+ pSpec.getPathSet().addAll(Arrays.asList(filterProps));
+ pSpec.setType(objmor.getType());
+ spec.getPropSet().add(pSpec);
+
+ ManagedObjectReference filterSpecRef =
vimPort.createFilter(propCollectorRef, spec, true);
+
+ boolean reached = false;
+
+ UpdateSet updateset = null;
+ List<PropertyFilterUpdate> filtupary = null;
+ List<ObjectUpdate> objupary = null;
+ List<PropertyChange> propchgary = null;
+ while (!reached) {
+ updateset = vimPort.waitForUpdates(propCollectorRef, version);
+ if (updateset == null || updateset.getFilterSet() == null) {
+ continue;
+ }
+ version = updateset.getVersion();
+
+ // Make this code more general purpose when PropCol changes later.
+ filtupary = updateset.getFilterSet();
+
+ for (PropertyFilterUpdate filtup : filtupary) {
+ objupary = filtup.getObjectSet();
+ for (ObjectUpdate objup : objupary) {
+ // TODO: Handle all "kind"s of updates.
+ if (objup.getKind() == ObjectUpdateKind.MODIFY ||
objup.getKind() == ObjectUpdateKind.ENTER
+ || objup.getKind() == ObjectUpdateKind.LEAVE) {
+ propchgary = objup.getChangeSet();
+ for (PropertyChange propchg : propchgary) {
+ updateValues(endWaitProps, endVals, propchg);
+ updateValues(filterProps, filterVals, propchg);
+ }
+ }
+ }
+ }
+
+ Object expctdval = null;
+ // Check if the expected values have been reached and exit the
loop
+ // if done.
+ // Also exit the WaitForUpdates loop if this is the case.
+ for (int chgi = 0; chgi < endVals.length && !reached; chgi++) {
+ for (int vali = 0; vali < expectedVals[chgi].length &&
!reached; vali++) {
+ expctdval = expectedVals[chgi][vali];
+
+ reached = expctdval.equals(endVals[chgi]) || reached;
+ }
+ }
+ }
+
+ // Destroy the filter when we are done.
+ vimPort.destroyPropertyFilter(filterSpecRef);
+ return filterVals;
+ }
+
+ private void updateValues(String[] props, Object[] vals, PropertyChange
propchg) {
+ for (int findi = 0; findi < props.length; findi++) {
+ if (propchg.getName().lastIndexOf(props[findi]) >= 0) {
+ if (propchg.getOp() == PropertyChangeOp.REMOVE) {
+ vals[findi] = "";
+ } else {
+ vals[findi] = propchg.getVal();
+ }
+ }
+ }
+ }
+
+ private SelectionSpec getSelectionSpec(String name) {
+ SelectionSpec genericSpec = new SelectionSpec();
+ genericSpec.setName(name);
+ return genericSpec;
+ }
+
+ /*
+ * @return An array of SelectionSpec covering VM, Host, Resource pool,
+ * Cluster Compute Resource and Datastore.
+ */
+ private List<SelectionSpec> buildFullTraversal() {
+ // Terminal traversal specs
+
+ // RP -> VM
+ TraversalSpec rpToVm = new TraversalSpec();
+ rpToVm.setName("rpToVm");
+ rpToVm.setType("ResourcePool");
+ rpToVm.setPath("vm");
+ rpToVm.setSkip(Boolean.FALSE);
+
+ // vApp -> VM
+ TraversalSpec vAppToVM = new TraversalSpec();
+ vAppToVM.setName("vAppToVM");
+ vAppToVM.setType("VirtualApp");
+ vAppToVM.setPath("vm");
+
+ // HostSystem -> VM
+ TraversalSpec hToVm = new TraversalSpec();
+ hToVm.setType("HostSystem");
+ hToVm.setPath("vm");
+ hToVm.setName("hToVm");
+ hToVm.getSelectSet().add(getSelectionSpec("VisitFolders"));
+ hToVm.setSkip(Boolean.FALSE);
+
+ // DC -> DS
+ TraversalSpec dcToDs = new TraversalSpec();
+ dcToDs.setType("Datacenter");
+ dcToDs.setPath("datastore");
+ dcToDs.setName("dcToDs");
+ dcToDs.setSkip(Boolean.FALSE);
+
+ // Recurse through all ResourcePools
+ TraversalSpec rpToRp = new TraversalSpec();
+ rpToRp.setType("ResourcePool");
+ rpToRp.setPath("resourcePool");
+ rpToRp.setSkip(Boolean.FALSE);
+ rpToRp.setName("rpToRp");
+ rpToRp.getSelectSet().add(getSelectionSpec("rpToRp"));
+
+ TraversalSpec crToRp = new TraversalSpec();
+ crToRp.setType("ComputeResource");
+ crToRp.setPath("resourcePool");
+ crToRp.setSkip(Boolean.FALSE);
+ crToRp.setName("crToRp");
+ crToRp.getSelectSet().add(getSelectionSpec("rpToRp"));
+
+ TraversalSpec crToH = new TraversalSpec();
+ crToH.setSkip(Boolean.FALSE);
+ crToH.setType("ComputeResource");
+ crToH.setPath("host");
+ crToH.setName("crToH");
+
+ TraversalSpec dcToHf = new TraversalSpec();
+ dcToHf.setSkip(Boolean.FALSE);
+ dcToHf.setType("Datacenter");
+ dcToHf.setPath("hostFolder");
+ dcToHf.setName("dcToHf");
+ dcToHf.getSelectSet().add(getSelectionSpec("VisitFolders"));
+
+ TraversalSpec vAppToRp = new TraversalSpec();
+ vAppToRp.setName("vAppToRp");
+ vAppToRp.setType("VirtualApp");
+ vAppToRp.setPath("resourcePool");
+ vAppToRp.getSelectSet().add(getSelectionSpec("rpToRp"));
+
+ TraversalSpec dcToVmf = new TraversalSpec();
+ dcToVmf.setType("Datacenter");
+ dcToVmf.setSkip(Boolean.FALSE);
+ dcToVmf.setPath("vmFolder");
+ dcToVmf.setName("dcToVmf");
+ dcToVmf.getSelectSet().add(getSelectionSpec("VisitFolders"));
+
+ // For Folder -> Folder recursion
+ TraversalSpec visitFolders = new TraversalSpec();
+ visitFolders.setType("Folder");
+ visitFolders.setPath("childEntity");
+ visitFolders.setSkip(Boolean.FALSE);
+ visitFolders.setName("VisitFolders");
+ List<SelectionSpec> sspecarrvf = new ArrayList<SelectionSpec>();
+ sspecarrvf.add(getSelectionSpec("crToRp"));
+ sspecarrvf.add(getSelectionSpec("crToH"));
+ sspecarrvf.add(getSelectionSpec("dcToVmf"));
+ sspecarrvf.add(getSelectionSpec("dcToHf"));
+ sspecarrvf.add(getSelectionSpec("vAppToRp"));
+ sspecarrvf.add(getSelectionSpec("vAppToVM"));
+ sspecarrvf.add(getSelectionSpec("dcToDs"));
+ sspecarrvf.add(getSelectionSpec("hToVm"));
+ sspecarrvf.add(getSelectionSpec("rpToVm"));
+ sspecarrvf.add(getSelectionSpec("VisitFolders"));
+
+ visitFolders.getSelectSet().addAll(sspecarrvf);
+
+ List<SelectionSpec> resultspec = new ArrayList<SelectionSpec>();
+ resultspec.add(visitFolders);
+ resultspec.add(crToRp);
+ resultspec.add(crToH);
+ resultspec.add(dcToVmf);
+ resultspec.add(dcToHf);
+ resultspec.add(vAppToRp);
+ resultspec.add(vAppToVM);
+ resultspec.add(dcToDs);
+ resultspec.add(hToVm);
+ resultspec.add(rpToVm);
+ resultspec.add(rpToRp);
+
+ return resultspec;
+ }
+
+
+ /**
+ * Get the ManagedObjectReference for an item under the
+ * specified root folder that has the type and name specified.
+ *
+ * @param root a root folder if available, or null for default
+ * @param type type of the managed object
+ * @param name name to match
+ *
+ * @return First ManagedObjectReference of the type / name pair found
+ */
+ public ManagedObjectReference getDecendentMoRef(ManagedObjectReference
root, String type, String name) throws Exception {
+ if (name == null || name.length() == 0) {
+ return null;
+ }
+
+ // Create PropertySpecs
+ PropertySpec pSpec = new PropertySpec();
+ pSpec.setType(type);
+ pSpec.setAll(false);
+ pSpec.getPathSet().add(name);
+
+ ObjectSpec oSpec = new ObjectSpec();
+ oSpec.setObj(root);
+ oSpec.setSkip(false);
+ oSpec.getSelectSet().addAll(buildFullTraversal());
+
+ PropertyFilterSpec spec = new PropertyFilterSpec();
+ spec.getPropSet().add(pSpec);
+ spec.getObjectSet().add(oSpec);
+ List<PropertyFilterSpec> specArr = new
ArrayList<PropertyFilterSpec>();
+ specArr.add(spec);
+
+ List<ObjectContent> ocary =
vimPort.retrieveProperties(propCollectorRef, specArr);
+
+ if (ocary == null || ocary.size() == 0) {
+ return null;
+ }
+
+ for (ObjectContent oc : ocary) {
+ ManagedObjectReference mor = oc.getObj();
+ List<DynamicProperty> propary = oc.getPropSet();
+ if (type == null || type.equals(mor.getType())) {
+ if (propary.size() > 0) {
+ String propval = (String) propary.get(0).getVal();
+ if (propval != null && name.equals(propval))
+ return mor;
+ }
+ }
+ }
+ return null;
+ }
+}