Title

Clone a VM from VM/Template

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.