Skip to content

Instantly share code, notes, and snippets.

@vmwarecode
Created June 27, 2016 20:52
Show Gist options
  • Save vmwarecode/8a7fbeb32d41ee5222e52321f0972f38 to your computer and use it in GitHub Desktop.
Save vmwarecode/8a7fbeb32d41ee5222e52321f0972f38 to your computer and use it in GitHub Desktop.
VMLinkedClone
/*
* ****************************************************************************
* 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.util.*;
/**
* <pre>
* VMLinkedClone
*
* This sample creates a linked clone from an existing snapshot
*
* Each independent disk needs a DiskLocator with
* diskmovetype as moveAllDiskBackingsAndDisallowSharing
*
* <b>Parameters:</b>
* url [required] : url of the web service
* username [required] : username for the authentication
* password [required] : password for the authentication
* vmname [required] : Name of the virtual machine
* snapshotname [required] : Name of the snaphot
* clonename [required] : Name of the cloneName
*
* <b>Command Line:</b>
* Create a linked clone
* run.bat com.vmware.vm.VMLinkedClone --url [webserviceurl]
* --username [username] --password [password] --vmname [myVM]
* --snapshotname [snapshot name] --clonename [clone name]
* </pre>
*/
@Sample(
name = "vm-linked-clone",
description =
"This sample creates a linked clone from an existing snapshot\n" +
"Each independent disk needs a DiskLocator with\n" +
"diskmovetype as moveAllDiskBackingsAndDisallowSharing\n"
)
public class VMLinkedClone extends ConnectedVimServiceBase {
String cloneName;
String virtualMachineName;
String snapshotName;
@Option(name = "vmname", description = "Name of the virtual machine")
public void setVirtualMachineName(String virtualMachineName) {
this.virtualMachineName = virtualMachineName;
}
@Option(name = "snapshotname", description = "Name of the snaphot")
public void setSnapshotName(String snapshotName) {
this.snapshotName = snapshotName;
}
@Option(name = "clonename", description = "Name of the cloneName")
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;
}
/**
* Creates the linked clone.
*
* @throws Exception the exception
*/
void createLinkedClone() throws RuntimeFaultFaultMsg, InvalidPropertyFaultMsg, CustomizationFaultFaultMsg, TaskInProgressFaultMsg, VmConfigFaultFaultMsg, InsufficientResourcesFaultFaultMsg, InvalidDatastoreFaultMsg, FileFaultFaultMsg, MigrationFaultFaultMsg, InvalidStateFaultMsg, InvalidCollectorVersionFaultMsg {
ManagedObjectReference propCol = connection.getServiceContent().getPropertyCollector();
ManagedObjectReference vmMOR = getMOREFs.vmByVMname(virtualMachineName, propCol);
if (vmMOR != null) {
ManagedObjectReference snapMOR =
getSnapshotReference(vmMOR, snapshotName);
if (snapMOR != null) {
ArrayList<Integer> independentVirtualDiskKeys =
getIndependenetVirtualDiskKeys(vmMOR);
VirtualMachineRelocateSpec rSpec = new VirtualMachineRelocateSpec();
if (independentVirtualDiskKeys.size() > 0) {
List<ManagedObjectReference> ds =
((ArrayOfManagedObjectReference) getMOREFs.entityProps(vmMOR,
new String[]{"datastore"}).get("datastore"))
.getManagedObjectReference();
List<VirtualMachineRelocateSpecDiskLocator> diskLocator =
new ArrayList<VirtualMachineRelocateSpecDiskLocator>();
for (Integer iDiskKey : independentVirtualDiskKeys) {
VirtualMachineRelocateSpecDiskLocator diskloc =
new VirtualMachineRelocateSpecDiskLocator();
diskloc.setDatastore(ds.get(0));
diskloc
.setDiskMoveType(VirtualMachineRelocateDiskMoveOptions.MOVE_ALL_DISK_BACKINGS_AND_DISALLOW_SHARING
.value());
diskloc.setDiskId(iDiskKey);
diskLocator.add(diskloc);
}
rSpec.setDiskMoveType(VirtualMachineRelocateDiskMoveOptions.CREATE_NEW_CHILD_DISK_BACKING
.value());
rSpec.getDisk().addAll(diskLocator);
} else {
rSpec.setDiskMoveType(VirtualMachineRelocateDiskMoveOptions.CREATE_NEW_CHILD_DISK_BACKING
.value());
}
VirtualMachineCloneSpec cloneSpec = new VirtualMachineCloneSpec();
cloneSpec.setPowerOn(false);
cloneSpec.setTemplate(false);
cloneSpec.setLocation(rSpec);
cloneSpec.setSnapshot(snapMOR);
ManagedObjectReference parentMOR =
(ManagedObjectReference) getMOREFs.entityProps(vmMOR,
new String[]{"parent"}).get("parent");
if (parentMOR == null) {
throw new RuntimeException(
"The selected VM is a part of vAPP. This sample only "
+ "works with virtual machines that are not a part "
+ "of any vAPP");
}
ManagedObjectReference cloneTask =
vimPort
.cloneVMTask(vmMOR, parentMOR, cloneName, cloneSpec);
if (getTaskResultAfterDone(cloneTask)) {
System.out.printf(" Cloning Successful");
} else {
System.out.printf(" Cloning Failure");
}
} else {
System.out.println("Snapshot " + snapshotName + " doesn't exist");
}
} else {
System.out.println("Virtual Machine " + virtualMachineName
+ " doesn't exist");
}
}
/**
* Gets the independenet virtual disk keys.
*
* @param vmMOR the vm mor
* @return the independent virtual disk keys
* @throws RuntimeFaultFaultMsg
* @throws InvalidPropertyFaultMsg
*/
ArrayList<Integer> getIndependenetVirtualDiskKeys(
ManagedObjectReference vmMOR) throws InvalidPropertyFaultMsg,
RuntimeFaultFaultMsg {
ArrayList<Integer> independenetVirtualDiskKeys = new ArrayList<Integer>();
VirtualHardware hw =
(VirtualHardware) getMOREFs.entityProps(vmMOR,
new String[]{"config.hardware"}).get("config.hardware");
List<VirtualDevice> listvd = hw.getDevice();
for (VirtualDevice vDisk : listvd) {
if (vDisk instanceof VirtualDisk) {
String diskMode = "";
if (vDisk.getBacking() instanceof VirtualDiskFlatVer1BackingInfo) {
diskMode =
((VirtualDiskFlatVer1BackingInfo) vDisk.getBacking())
.getDiskMode();
} else if (vDisk.getBacking() instanceof VirtualDiskFlatVer2BackingInfo) {
diskMode =
((VirtualDiskFlatVer2BackingInfo) vDisk.getBacking())
.getDiskMode();
} else if (vDisk.getBacking() instanceof VirtualDiskRawDiskMappingVer1BackingInfo) {
diskMode =
((VirtualDiskRawDiskMappingVer1BackingInfo) vDisk
.getBacking()).getDiskMode();
} else if (vDisk.getBacking() instanceof VirtualDiskSparseVer1BackingInfo) {
diskMode =
((VirtualDiskSparseVer1BackingInfo) vDisk.getBacking())
.getDiskMode();
} else if (vDisk.getBacking() instanceof VirtualDiskSparseVer2BackingInfo) {
diskMode =
((VirtualDiskSparseVer2BackingInfo) vDisk.getBacking())
.getDiskMode();
}
if (diskMode.indexOf("independent") != -1) {
independenetVirtualDiskKeys.add(vDisk.getKey());
}
}
}
return independenetVirtualDiskKeys;
}
/**
* Gets the snapshot reference.
*
* @param vmmor the vmmor
* @param snapName the snap name
* @return the snapshot reference
* @throws Exception the exception
*/
ManagedObjectReference getSnapshotReference(
ManagedObjectReference vmmor, String snapName) throws RuntimeFaultFaultMsg, InvalidPropertyFaultMsg {
VirtualMachineSnapshotInfo snapInfo =
(VirtualMachineSnapshotInfo) getMOREFs.entityProps(vmmor,
new String[]{"snapshot"}).get("snapshot");
ManagedObjectReference snapmor = null;
if (snapInfo != null) {
List<VirtualMachineSnapshotTree> listvmsst =
snapInfo.getRootSnapshotList();
List<VirtualMachineSnapshotTree> snapTree = listvmsst;
snapmor = traverseSnapshotInTree(snapTree, snapName);
}
return snapmor;
}
/**
* Traverse snapshot in tree.
*
* @param snapTree the snap tree
* @param findName the find name
* @return the managed object reference
*/
ManagedObjectReference traverseSnapshotInTree(
List<VirtualMachineSnapshotTree> snapTree, String findName) {
ManagedObjectReference snapmor = null;
if (snapTree == null) {
return snapmor;
}
for (int i = 0; i < snapTree.size() && snapmor == null; i++) {
VirtualMachineSnapshotTree node = snapTree.get(i);
if (findName != null && node.getName().equals(findName)) {
snapmor = node.getSnapshot();
} else {
List<VirtualMachineSnapshotTree> childTree =
node.getChildSnapshotList();
snapmor = traverseSnapshotInTree(childTree, findName);
}
}
return snapmor;
}
@Action
public void run() throws CustomizationFaultFaultMsg, RuntimeFaultFaultMsg, TaskInProgressFaultMsg, InsufficientResourcesFaultFaultMsg, VmConfigFaultFaultMsg, InvalidDatastoreFaultMsg, InvalidPropertyFaultMsg, FileFaultFaultMsg, InvalidStateFaultMsg, MigrationFaultFaultMsg, InvalidCollectorVersionFaultMsg {
createLinkedClone();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment