Skip to content

Instantly share code, notes, and snippets.

@vmwarecode
Created June 27, 2016 20:52
Show Gist options
  • Save vmwarecode/92c817a62909a7e3fabab3b8ca114569 to your computer and use it in GitHub Desktop.
Save vmwarecode/92c817a62909a7e3fabab3b8ca114569 to your computer and use it in GitHub Desktop.
VMClone
/*
* ****************************************************************************
* Copyright VMware, Inc. 2010-2016. All Rights Reserved.
* ****************************************************************************
*
* This software is made available for use under the terms of the BSD
* 3-Clause license:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.vmware.vm;
import com.vmware.common.annotations.Action;
import com.vmware.common.annotations.Option;
import com.vmware.common.annotations.Sample;
import com.vmware.connection.ConnectedVimServiceBase;
import com.vmware.vim25.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* <pre>
* VMClone
*
* This sample makes a template of an existing VM and
* deploy multiple instances of this template onto a datacenter
*
* <b>Parameters:</b>
* url [required] : url of the web service
* username [required] : username for the authentication
* password [required] : password for the authentication
* datacentername [required] : name of Datacenter
* vmpath [required] : inventory path of the VM
* clonename [required] : name of the clone
*
* <b>Command Line:</b>
* java com.vmware.vm.VMClone --url [webserviceurl]
* --username [username] --password [password]
* --datacentername [DatacenterName]"
* --vmpath [vmPath] --clonename [CloneName]
* </pre>
*/
@Sample(
name = "vm-clone",
description = "This sample makes a template of an " +
"existing VM and deploy multiple instances of this " +
"template onto a datacenter"
)
public class VMClone extends ConnectedVimServiceBase {
private ManagedObjectReference propCollectorRef;
private String dataCenterName;
private String vmPathName;
private String cloneName;
@Option(name = "datacentername", description = "name of Datacenter")
public void setDataCenterName(String dataCenterName) {
this.dataCenterName = dataCenterName;
}
@Option(name = "vmpath", description = "inventory path of the VM")
public void setVmPathName(String vmPathName) {
this.vmPathName = vmPathName;
}
@Option(name = "clonename", description = "name of the clone")
public void setCloneName(String cloneName) {
this.cloneName = cloneName;
}
/**
* 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
*/
boolean getTaskResultAfterDone(ManagedObjectReference task)
throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg,
InvalidCollectorVersionFaultMsg {
boolean retVal = false;
// info has a property - state for state of the task
Object[] result =
waitForValues.wait(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;
}
void cloneVM() throws RuntimeFaultFaultMsg, InvalidPropertyFaultMsg, InvalidCollectorVersionFaultMsg, CustomizationFaultFaultMsg, TaskInProgressFaultMsg, VmConfigFaultFaultMsg, InsufficientResourcesFaultFaultMsg, InvalidDatastoreFaultMsg, FileFaultFaultMsg, MigrationFaultFaultMsg, InvalidStateFaultMsg, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
// Find the Datacenter reference by using findByInventoryPath().
ManagedObjectReference datacenterRef =
vimPort.findByInventoryPath(serviceContent.getSearchIndex(),
dataCenterName);
if (datacenterRef == null) {
System.out.printf("The specified datacenter [ %s ]is not found %n",
dataCenterName);
return;
}
// Find the virtual machine folder for this datacenter.
ManagedObjectReference vmFolderRef =
(ManagedObjectReference) getDynamicProperty(datacenterRef,
"vmFolder");
if (vmFolderRef == null) {
System.out.println("The virtual machine is not found");
return;
}
ManagedObjectReference vmRef =
vimPort.findByInventoryPath(serviceContent.getSearchIndex(),
vmPathName);
if (vmRef == null) {
System.out.printf("The VMPath specified [ %s ] is not found %n",
vmPathName);
return;
}
VirtualMachineCloneSpec cloneSpec = new VirtualMachineCloneSpec();
VirtualMachineRelocateSpec relocSpec = new VirtualMachineRelocateSpec();
cloneSpec.setLocation(relocSpec);
cloneSpec.setPowerOn(false);
cloneSpec.setTemplate(false);
System.out.printf("Cloning Virtual Machine [%s] to clone name [%s] %n",
vmPathName.substring(vmPathName.lastIndexOf("/") + 1), cloneName);
ManagedObjectReference cloneTask =
vimPort.cloneVMTask(vmRef, vmFolderRef, cloneName, cloneSpec);
if (getTaskResultAfterDone(cloneTask)) {
System.out
.printf(
"Successfully cloned Virtual Machine [%s] to clone name [%s] %n",
vmPathName.substring(vmPathName.lastIndexOf("/") + 1),
cloneName);
} else {
System.out.printf(
"Failure Cloning Virtual Machine [%s] to clone name [%s] %n",
vmPathName.substring(vmPathName.lastIndexOf("/") + 1),
cloneName);
}
}
/**
* Uses the new RetrievePropertiesEx method to emulate the now deprecated
* RetrieveProperties method
*
* @param listpfs
* @return list of object content
* @throws Exception
*/
List<ObjectContent> retrievePropertiesAllObjects(
List<PropertyFilterSpec> listpfs) throws RuntimeFaultFaultMsg, InvalidPropertyFaultMsg {
RetrieveOptions propObjectRetrieveOpts = new RetrieveOptions();
List<ObjectContent> listobjcontent = new ArrayList<ObjectContent>();
RetrieveResult rslts =
vimPort.retrievePropertiesEx(propCollectorRef, listpfs,
propObjectRetrieveOpts);
if (rslts != null && rslts.getObjects() != null
&& !rslts.getObjects().isEmpty()) {
listobjcontent.addAll(rslts.getObjects());
}
String token = null;
if (rslts != null && rslts.getToken() != null) {
token = rslts.getToken();
}
while (token != null && !token.isEmpty()) {
rslts =
vimPort.continueRetrievePropertiesEx(propCollectorRef, token);
token = null;
if (rslts != null) {
token = rslts.getToken();
if (rslts.getObjects() != null && !rslts.getObjects().isEmpty()) {
listobjcontent.addAll(rslts.getObjects());
}
}
}
return listobjcontent;
}
Object getDynamicProperty(ManagedObjectReference mor,
String propertyName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, RuntimeFaultFaultMsg, InvalidPropertyFaultMsg {
ObjectContent[] objContent =
getObjectProperties(mor, new String[]{propertyName});
Object propertyValue = null;
if (objContent != null) {
List<DynamicProperty> listdp = objContent[0].getPropSet();
if (listdp != null) {
/*
* Check the dynamic property for ArrayOfXXX object
*/
Object dynamicPropertyVal = listdp.get(0).getVal();
String dynamicPropertyName =
dynamicPropertyVal.getClass().getName();
if (dynamicPropertyName.indexOf("ArrayOf") != -1) {
String methodName =
dynamicPropertyName.substring(
dynamicPropertyName.indexOf("ArrayOf")
+ "ArrayOf".length(),
dynamicPropertyName.length());
/*
* If object is ArrayOfXXX object, then get the XXX[] by
* invoking getXXX() on the object.
* For Ex:
* ArrayOfManagedObjectReference.getManagedObjectReference()
* returns ManagedObjectReference[] array.
*/
if (methodExists(dynamicPropertyVal, "get" + methodName, null)) {
methodName = "get" + methodName;
} else {
/*
* Construct methodName for ArrayOf primitive types
* Ex: For ArrayOfInt, methodName is get_int
*/
methodName = "get_" + methodName.toLowerCase();
}
Method getMorMethod =
dynamicPropertyVal.getClass().getDeclaredMethod(
methodName, (Class[]) null);
propertyValue =
getMorMethod.invoke(dynamicPropertyVal, (Object[]) null);
} else if (dynamicPropertyVal.getClass().isArray()) {
/*
* Handle the case of an unwrapped array being deserialized.
*/
propertyValue = dynamicPropertyVal;
} else {
propertyValue = dynamicPropertyVal;
}
}
}
return propertyValue;
}
/**
* Retrieve contents for a single object based on the property collector
* registered with the service.
*
* @param mobj Managed Object Reference to get contents for
* @param properties names of properties of object to retrieve
* @return retrieved object contents
*/
ObjectContent[] getObjectProperties(
ManagedObjectReference mobj, String[] properties) throws RuntimeFaultFaultMsg, InvalidPropertyFaultMsg {
if (mobj == null) {
return null;
}
PropertyFilterSpec spec = new PropertyFilterSpec();
spec.getPropSet().add(new PropertySpec());
if ((properties == null || properties.length == 0)) {
spec.getPropSet().get(0).setAll(Boolean.TRUE);
} else {
spec.getPropSet().get(0).setAll(Boolean.FALSE);
}
spec.getPropSet().get(0).setType(mobj.getType());
spec.getPropSet().get(0).getPathSet().addAll(Arrays.asList(properties));
spec.getObjectSet().add(new ObjectSpec());
spec.getObjectSet().get(0).setObj(mobj);
spec.getObjectSet().get(0).setSkip(Boolean.FALSE);
List<PropertyFilterSpec> listpfs = new ArrayList<PropertyFilterSpec>(1);
listpfs.add(spec);
List<ObjectContent> listobjcont = retrievePropertiesAllObjects(listpfs);
return listobjcont.toArray(new ObjectContent[listobjcont.size()]);
}
/**
* Determines of a method 'methodName' exists for the Object 'obj'.
*
* @param obj The Object to check
* @param methodName The method name
* @param parameterTypes Array of Class objects for the parameter types
* @return true if the method exists, false otherwise
*/
@SuppressWarnings("rawtypes")
boolean methodExists(Object obj, String methodName,
Class[] parameterTypes) throws NoSuchMethodException {
boolean exists = false;
Method method = obj.getClass().getMethod(methodName, parameterTypes);
if (method != null) {
exists = true;
}
return exists;
}
@Action
public void run() throws RuntimeFaultFaultMsg, TaskInProgressFaultMsg, VmConfigFaultFaultMsg, InvalidDatastoreFaultMsg, FileFaultFaultMsg, NoSuchMethodException, MigrationFaultFaultMsg, InvalidStateFaultMsg, InvalidCollectorVersionFaultMsg, IllegalAccessException, CustomizationFaultFaultMsg, InsufficientResourcesFaultFaultMsg, InvocationTargetException, InvalidPropertyFaultMsg {
propCollectorRef = serviceContent.getPropertyCollector();
cloneVM();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment