CloneVM.cs
Copyright © 2008 VMware, Inc. All rights reserved.
// Copyright 2008 VMware, Inc. All rights reserved.
//
//#######################################################################################
//DISCLAIMER. THIS SCRIPT IS PROVIDED TO YOU "AS IS" WITHOUT WARRANTIES OR CONDITIONS
//OF ANY KIND, WHETHER ORAL OR WRITTEN, EXPRESS OR IMPLIED. THE AUTHOR SPECIFICALLY
//DISCLAIMS ANY IMPLIED WARRANTIES OR CONDITIONS OF MERCHANTABILITY, SATISFACTORY
//QUALITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
//#######################################################################################
//#######################################################################################
//
// Clone.cs
// Example script to clone a Virtual Machine from Vm\template.
// Parameters:
// -- args[0] Url of VC
// -- args[1] Userid
// -- args[2] Password
// -- args[3] Name of the datacenter
// -- args[4] Name of the source vm
// -- args[5] Name of the cloned vm
// This script works with VMware VirtualCenter 2.0 or later.
//#######################################################################################
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Net;
using System.Text;
using System.Web.Services;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Collections;
using VimApi;
namespace CloneVMApplication
{
public class CertPolicy : ICertificatePolicy
{
private enum CertificateProblem : uint
{
CertEXPIRED = 0x800B0101,
CertVALIDITYPERIODNESTING = 0x800B0102,
CertROLE = 0x800B0103,
CertPATHLENCONST = 0x800B0104,
CertCRITICAL = 0x800B0105,
CertPURPOSE = 0x800B0106,
CertISSUERCHAINING = 0x800B0107,
CertMALFORMED = 0x800B0108,
CertUNTRUSTEDROOT = 0x800B0109,
CertCHAINING = 0x800B010A,
CertREVOKED = 0x800B010C,
CertUNTRUSTEDTESTROOT = 0x800B010D,
CertREVOCATION_FAILURE = 0x800B010E,
CertCN_NO_MATCH = 0x800B010F,
CertWRONG_USAGE = 0x800B0110,
CertUNTRUSTEDCA = 0x800B0112
}
private static Hashtable problem2text_;
private Hashtable request2problems_; // WebRequest -> ArrayList of error codes
public CertPolicy()
{
if (problem2text_ == null)
{
problem2text_ = new Hashtable();
problem2text_.Add((uint)CertificateProblem.CertEXPIRED,
"A required certificate is not within its validity period.");
problem2text_.Add((uint)CertificateProblem.CertVALIDITYPERIODNESTING,
"The validity periods of the certification chain do not nest correctly.");
problem2text_.Add((uint)CertificateProblem.CertROLE,
"A certificate that can only be used as an end-entity is being used as a CA or visa versa.");
problem2text_.Add((uint)CertificateProblem.CertPATHLENCONST,
"A path length constraint in the certification chain has been violated.");
problem2text_.Add((uint)CertificateProblem.CertCRITICAL,
"An extension of unknown type that is labeled 'critical' is present in a certificate.");
problem2text_.Add((uint)CertificateProblem.CertPURPOSE,
"A certificate is being used for a purpose other than that for which it is permitted.");
problem2text_.Add((uint)CertificateProblem.CertISSUERCHAINING,
"A parent of a given certificate in fact did not issue that child certificate.");
problem2text_.Add((uint)CertificateProblem.CertMALFORMED,
"A certificate is missing or has an empty value for an important field, such as a subject or issuer name.");
problem2text_.Add((uint)CertificateProblem.CertUNTRUSTEDROOT,
"A certification chain processed correctly, but terminated in a root certificate which isn't trusted by the trust provider.");
problem2text_.Add((uint)CertificateProblem.CertCHAINING,
"A chain of certs didn't chain as they should in a certain application of chaining.");
problem2text_.Add((uint)CertificateProblem.CertREVOKED,
"A certificate was explicitly revoked by its issuer.");
problem2text_.Add((uint)CertificateProblem.CertUNTRUSTEDTESTROOT,
"The root certificate is a testing certificate and the policy settings disallow test certificates.");
problem2text_.Add((uint)CertificateProblem.CertREVOCATION_FAILURE,
"The revocation process could not continue - the certificate(s) could not be checked.");
problem2text_.Add((uint)CertificateProblem.CertCN_NO_MATCH,
"The certificate's CN name does not match the passed value.");
problem2text_.Add((uint)CertificateProblem.CertWRONG_USAGE,
"The certificate is not valid for the requested usage.");
problem2text_.Add((uint)CertificateProblem.CertUNTRUSTEDCA,
"Untrusted CA");
}
request2problems_ = new Hashtable();
}
// ICertificatePolicy
public bool CheckValidationResult(ServicePoint sp, X509Certificate cert, WebRequest request, int problem)
{
if (problem == 0)
{
// Check whether we have accumulated any problems so far:
ArrayList problemArray = (ArrayList)request2problems_[request];
if (problemArray == null)
{
// No problems so far
return true;
}
string problemList = "";
foreach (uint problemCode in problemArray)
{
string problemText = (string)problem2text_[problemCode];
if (problemText == null)
{
problemText = "Unknown problem";
}
problemList += "* " + problemText + "\n\n";
}
request2problems_.Remove(request);
System.Console.WriteLine("There were one or more problems with the server certificate:\n\n" + problemList);
return true;
}
else
{
// Stash the problem in the problem array:
ArrayList problemArray = (ArrayList)request2problems_[request];
if (problemArray == null)
{
problemArray = new ArrayList();
request2problems_[request] = problemArray;
}
problemArray.Add((uint)problem);
return true;
}
}
}
public class CloningVM
{
static VimService _service;
protected ManagedObjectReference _svcRef;
private UserSession _session;
private void CloneVM(string url, string usid, string pwd, string dcName, string tempVM, string cloneVM)
{
String datacenterName = dcName; // name of DataCenter
String srcName = tempVM; // name of source vm/template
String clonedName = cloneVM; // name of Virtual machine
System.Net.ServicePointManager.CertificatePolicy = new CertPolicy();
ManagedObjectReference _svcRef = new ManagedObjectReference();
//Gets service contents
_svcRef.type = "ServiceInstance";
_svcRef.Value = "ServiceInstance";
_service = new VimService();
_service.Url = url;
_service.CookieContainer = new CookieContainer();
ServiceContent _sic = _service.RetrieveServiceContent(_svcRef);
_service.LoginCompleted += new LoginCompletedEventHandler(_service_LoginCompleted);
_session = _service.Login(_sic.sessionManager, usid, pwd, null);
//MOR for searching datacenter in inventory
ManagedObjectReference searchIndex = new ManagedObjectReference();
searchIndex = _sic.searchIndex;
ManagedObjectReference datacenterRef = _service.FindByInventoryPath(searchIndex, datacenterName);
if (datacenterRef == null)
{
Console.WriteLine("The specified datacenter is not found");
return;
}
// Find the virtual machine folder for this datacenter.
ManagedObjectReference vmFolderRef = (ManagedObjectReference)getObjectProperty(datacenterRef, "vmFolder");
// Find the virtual machine list from the virtual machine folder found above.
ManagedObjectReference[] vmList = (ManagedObjectReference[])getObjectProperty(vmFolderRef, "childEntity");
//Searching for the template/virtual machine
ManagedObjectReference templateRef = null;
for (int i = 0; i < vmList.Length; i++)
{
if (vmList[i].type == "VirtualMachine")
{
Object[] vmProps = getProperties(vmList[i],
new String[] { "config.name", "config.template" });
if (((String)vmProps[0]).Equals(srcName))
{
templateRef = vmList[i];
}
}
}
//Create VirtualMachineCloneSpec & VirtualMachineRelocateSpec
VirtualMachineCloneSpec cloneSpec = new VirtualMachineCloneSpec();
VirtualMachineRelocateSpec relocSpec = new VirtualMachineRelocateSpec();
VirtualMachineConfigInfo vmConfigInfo
= (VirtualMachineConfigInfo)getObjectProperty(templateRef, "config");
if (vmConfigInfo.template.Equals(true))
{
VirtualMachineRuntimeInfo vmRuntimeInfo
= (VirtualMachineRuntimeInfo)getObjectProperty(templateRef, "runtime");
// getting the Managed Object Reference of host of the src template
ManagedObjectReference hostRef = vmRuntimeInfo.host;
if (hostRef == null)
{
Console.Write("Host not found for the template");
}
else
{
// getting the Managed Object Reference of root resource pool of host of the src template
ManagedObjectReference hostParentCompResRef
= (ManagedObjectReference)getObjectProperty(hostRef, "parent");
if (hostParentCompResRef.type.CompareTo("ComputeResource") == 0)
{
ManagedObjectReference resourcePoolRootRef = (ManagedObjectReference)getObjectProperty(hostParentCompResRef, "resourcePool");
if (resourcePoolRootRef == null)
{
Console.Write("Resource pool not found for the template");
return;
}
else
{
// Assigning the root resource pool of host of the src template as pool
relocSpec.pool = resourcePoolRootRef;
}
}
else
{
Console.Write("Parent of Host system was not of type ComputeResource");
}
}
}
cloneSpec.location = relocSpec;
cloneSpec.powerOn = false;
cloneSpec.template = false;
// Create VirtualMachineConfigSpec
VirtualMachineConfigSpec configSpec = new VirtualMachineConfigSpec();
cloneSpec.config = configSpec;
Console.WriteLine("Launching clone task to create a clone: " + clonedName);
// Performing CloneVM_Task
ManagedObjectReference cloneTask = _service.CloneVM_Task(templateRef, vmFolderRef, clonedName, cloneSpec);
}
public static Object getObjectProperty(ManagedObjectReference moRef, String propertyName)
{
return getProperties(moRef, new String[] { propertyName })[0];
}
/*
* getProperties --
*
* Retrieves the specified set of properties for the given managed object
* reference into an array of result objects (returned in the same oder
* as the property list).
*/
public static Object[] getProperties(ManagedObjectReference moRef, String[] properties)
{
// PropertySpec specifies what properties to
// retrieve and from type of Managed Object
PropertySpec pSpec = new PropertySpec();
pSpec.type = moRef.type;
pSpec.pathSet = properties;
// ObjectSpec specifies the starting object and
// any TraversalSpecs used to specify other objects
// for consideration
ObjectSpec oSpec = new ObjectSpec();
oSpec.obj = moRef;
// PropertyFilterSpec is used to hold the ObjectSpec and
// PropertySpec for the call
PropertyFilterSpec pfSpec = new PropertyFilterSpec();
pfSpec.propSet = new PropertySpec[] { pSpec };
pfSpec.objectSet = new ObjectSpec[] { oSpec };
ManagedObjectReference _svcRef1 = new ManagedObjectReference();
_svcRef1.type = "ServiceInstance";
_svcRef1.Value = "ServiceInstance";
ServiceContent sic1 = _service.RetrieveServiceContent(_svcRef1);
ObjectContent[] ocs = new ObjectContent[20];
ocs = _service.RetrieveProperties(sic1.propertyCollector, new PropertyFilterSpec[] { pfSpec });
// Return value, one object for each property specified
Object[] ret = new Object[properties.Length];
if (ocs != null)
{
for (int i = 0; i < ocs.Length; ++i)
{
ObjectContent oc = ocs[i];
DynamicProperty[] dps = oc.propSet;
if (dps != null)
{
for (int j = 0; j < dps.Length; ++j)
{
DynamicProperty dp = dps[j];
// find property path index
for (int p = 0; p < ret.Length; ++p)
{
if (properties[p].Equals(dp.name))
{
ret[p] = dp.val;
}
}
}
}
}
}
return ret;
}
public static void Main(String[] args)
{
CloningVM cv = new CloningVM();
cv.CloneVM(args[0], args[1], args[2], args[3], args[4], args[5]);
}
void _service_LoginCompleted(object sender, LoginCompletedEventArgs e)
{
}
}
}
The sample code is provided "AS-IS" for use, modification, and redistribution in source and binary forms, provided that the copyright notice and this following list of conditions are retained and/or reproduced in your distribution. To the maximum extent permitted by law, VMware, Inc., its subsidiaries and affiliates hereby disclaim all express, implied and/or statutory warranties, including duties or conditions of merchantability, fitness for a particular purpose, and non-infringement of intellectual property rights. IN NO EVENT WILL VMWARE, ITS SUBSIDIARIES OR AFFILIATES BE LIABLE TO ANY OTHER PARTY FOR THE COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT, INDIRECT, OR SPECIAL DAMAGES, ARISING OUT OF THIS OR ANY OTHER AGREEMENT RELATING TO THE SAMPLE CODE.
You agree to defend, indemnify and hold harmless VMware, and any of its directors, officers, employees, agents, affiliates, or subsidiaries from and against all losses, damages, costs and liabilities arising from your use, modification and distribution of the sample code.
VMware does not certify or endorse your use of the sample code, nor is any support or other service provided in connection with the sample code.