Ben,
Here is my code to handle cloning a windows or linux vm from an existing vm. This appears to allow us to define network settings and hostname infromation which are the important bits for us. It will also pre-stage a computer account in our domain for the windows vm's.
I would very much consider this to be beta1 type code...lool...and take NO responsibility for it ;-) My only limitation here is that I'm hard-coding for a signle network card. We're really only hoping to use this to provision commodity type servers that have no crazy extra settings, and if so, this would get a working vm up and running and then it can be modified later.
The functions i'm calling are the ones from the using vmware.vim post.
(http://communities.vmware.com/message/2194869#2194869)
enjoy!
string dateCreated = (System.DateTime.Now).ToString();
Random rand = new Random();
if (txtVmName.Text == null || txtVmName.Text == "")
{
txtResult.Text = "Please enter a name for the virtual machine."; return;
}
IPAddress theIp;
bool ipResult = IPAddress.TryParse(txtIpAddress.Text, out theIp);
if (ipResult != true)
{
txtResult.Text = "Please enter a valid IP Address."; return;
}
IPAddress theGateway;
bool gwResult = IPAddress.TryParse(txtDefaultGateway.Text, out theGateway);
if (gwResult != true)
{
txtResult.Text = "Please entera valid IP Address for the default gateway."; return;
}
//
// Check for name conflict
//
VimClient vimClient = ConnectServer(Globals.sViServer, Globals.sUsername, Globals.sPassword);
List<VirtualMachine> chkVirtualMachines = GetVirtualMachines(vimClient, null, txtVmName.Text);
if (chkVirtualMachines != null)
{ vimClient.Disconnect(); txtResult.Text = "virtual machine " + txtVmName.Text + " already exists"; return;
}
if (cboCustomizations.SelectedItem.Value=="Windows")
{
// // Connect to directory and create computer object // string ldapPath = Globals.adServer + "/OU=" + cboSysadminOu.SelectedItem.ToString() + "," + Globals.adRootPath; DirectoryEntry dirEntry = new DirectoryEntry(); dirEntry.Username = Globals.sUsername; dirEntry.Password = Globals.sPassword; // // check to see if name exists // DirectorySearcher dirSearcher = new DirectorySearcher(dirEntry); dirSearcher.Filter = "(cn=" + txtVmName.Text + ")"; SearchResult dirResult = dirSearcher.FindOne(); if (dirResult == null) { // // Name not found, create new ad object // DirectoryEntry dirEntry1 = new DirectoryEntry(); dirEntry1.Path = ldapPath; dirEntry1.Username = Globals.sUsername; dirEntry1.Password = Globals.sPassword; DirectoryEntries dirEntries = dirEntry1.Children; DirectoryEntry newVm = dirEntries.Add("CN=" + txtVmName.Text.ToString(), "computer"); newVm.Properties["sAMAccountName"].Value = txtVmName.Text.ToString() + "$"; newVm.Properties["Description"].Value = Globals.sUsername + " created this object on " + DateTime.Now; newVm.Properties["userAccountControl"].Value = 4128; newVm.CommitChanges(); } else { txtResult.Text = "The server " + txtVmName.Text + " already exists in the Active Directory, please choose a different name."; return; }
}
//
// Get a list of hosts in the selected cluster
//
List<HostSystem> lstHosts = GetHosts(vimClient, cboClusters.SelectedValue);
//
// Randomly pick host
//
HostSystem selectedHost = lstHosts[rand.Next(0, lstHosts.Count)];
//
// Connect to selected vm to clone
//
List<VirtualMachine> lstVirtualMachines = GetVirtualMachines(vimClient, null, cboClones.SelectedItem.Text);
VirtualMachine itmVirtualMachine = lstVirtualMachines[0];
//
// Connect to the selected datastore
//
List<Datastore> lstDatastores = GetDataStore(vimClient, null, cboDatastores.SelectedItem.Text);
Datastore itmDatastore = lstDatastores[0];
//
// Connect to portgroup
//
List<DistributedVirtualPortgroup> lstDvPortGroups = GetDVPortGroups(vimClient, null, cboPortGroups.SelectedItem.Text);
DistributedVirtualPortgroup itmDvPortGroup = lstDvPortGroups[0];;
//
// Connect to the customizationspec
//
CustomizationSpecItem itmSpecItem = GetCustomizationSpecItem(vimClient, cboCustomizations.SelectedItem.Text);
//
// Create a new VirtualMachineCloneSpec
//
VirtualMachineCloneSpec mySpec = new VirtualMachineCloneSpec();
mySpec.Location = new VirtualMachineRelocateSpec();
mySpec.Location.Datastore = itmDatastore.MoRef;
mySpec.Location.Host = selectedHost.MoRef;
//
// Add selected CloneSpec customizations to this CloneSpec
//
mySpec.Customization = itmSpecItem.Spec;
//
// Handle hostname for either windows or linux
//
if (cboCustomizations.SelectedValue == "Windows")
{
// // Create a windows sysprep object // CustomizationSysprep winIdent = (CustomizationSysprep)itmSpecItem.Spec.Identity; CustomizationFixedName hostname = new CustomizationFixedName(); hostname.Name = txtVmName.Text; winIdent.UserData.ComputerName = hostname; // // Store identity in this CloneSpec // mySpec.Customization.Identity = winIdent;
}
if (cboCustomizations.SelectedValue == "Linux")
{
// // Create a Linux "sysprep" object // CustomizationLinuxPrep linIdent = (CustomizationLinuxPrep)itmSpecItem.Spec.Identity; CustomizationFixedName hostname = new CustomizationFixedName(); hostname.Name = txtVmName.Text; linIdent.HostName = hostname; // // Store identity in this CloneSpec // mySpec.Customization.Identity = linIdent;
}
//
// Create a new ConfigSpec
//
mySpec.Config = new VirtualMachineConfigSpec();
//
// Set number of CPU's
//
int numCpus = new int();
numCpus = Convert.ToInt16(cboCpuNum.SelectedValue);
mySpec.Config.NumCPUs = numCpus;
//
// Set amount of RAM
//
long memoryMb = new long();
memoryMb = (long)(Convert.ToInt16(cboRam.SelectedValue) * 1024);
mySpec.Config.MemoryMB = memoryMb;
//
// Only handle the first network card
//
mySpec.Customization.NicSettingMap = new CustomizationAdapterMapping[1];
mySpec.Customization.NicSettingMap[0] = new CustomizationAdapterMapping();
//
// Read in the DNS from web.config and assign
//
string[] ipDns = new string[1];
ipDns[0] = WebConfigurationManager.AppSettings["dnsServer"].ToString();
mySpec.Customization.GlobalIPSettings = new CustomizationGlobalIPSettings();
mySpec.Customization.GlobalIPSettings.DnsServerList = ipDns;
//
// Create a new networkDevice
//
VirtualDevice networkDevice = new VirtualDevice();
foreach (VirtualDevice vDevice in itmVirtualMachine.Config.Hardware.Device)
{
// // get nic on vm // if (vDevice.DeviceInfo.Label.Contains("Network")) { networkDevice = vDevice; }
}
//
// Create a DeviceSpec
//
VirtualDeviceConfigSpec[] devSpec = new VirtualDeviceConfigSpec[0];
mySpec.Config.DeviceChange = new VirtualDeviceConfigSpec[1];
mySpec.Config.DeviceChange[0] = new VirtualDeviceConfigSpec();
mySpec.Config.DeviceChange[0].Operation = VirtualDeviceConfigSpecOperation.edit;
mySpec.Config.DeviceChange[0].Device = networkDevice;
//
// Define network settings for the new vm
//
CustomizationFixedIp ipAddress = new CustomizationFixedIp();
ipAddress.IpAddress = txtIpAddress.Text;
mySpec.Customization.NicSettingMap[0].Adapter = new CustomizationIPSettings();
//
// Assign IP address
//
mySpec.Customization.NicSettingMap[0].Adapter.Ip = ipAddress;
mySpec.Customization.NicSettingMap[0].Adapter.SubnetMask = txtSubnetMask.Text;
//
// Assign default gateway
//
string[] ipGateway = new string[1];
ipGateway[0] = txtDefaultGateway.Text;
mySpec.Customization.NicSettingMap[0].Adapter.Gateway = ipGateway;
//
// Create network backing information
//
VirtualEthernetCardDistributedVirtualPortBackingInfo nicBack = new VirtualEthernetCardDistributedVirtualPortBackingInfo();
nicBack.Port = new DistributedVirtualSwitchPortConnection();
//
// Connect to the virtual switch
//
VmwareDistributedVirtualSwitch dvSwitch = GetDvSwitch(vimClient, itmDvPortGroup.Config.DistributedVirtualSwitch);
//
// Assign the proper switch port
//
nicBack.Port.SwitchUuid = dvSwitch.Uuid;
//
// Connect the network card to proper port group
//
nicBack.Port.PortgroupKey = itmDvPortGroup.MoRef.Value;
mySpec.Config.DeviceChange[0].Device.Backing = nicBack;
//
// Enable the network card at bootup
//
mySpec.Config.DeviceChange[0].Device.Connectable = new VirtualDeviceConnectInfo();
mySpec.Config.DeviceChange[0].Device.Connectable.StartConnected = true;
mySpec.Config.DeviceChange[0].Device.Connectable.AllowGuestControl = true;
mySpec.Config.DeviceChange[0].Device.Connectable.Connected = true;
//
// Get the vmfolder from the datacenter
//
List<ClusterComputeResource> lstClusters = GetClusters(vimClient, cboClusters.SelectedItem.Text);
List<Datacenter> lstDatacenters = GetDcFromCluster(vimClient, lstClusters[0].Parent.Value);
Datacenter itmDatacenter = lstDatacenters[0];
//
// Perform the clone
//
itmVirtualMachine.CloneVM_Task(itmDatacenter.VmFolder, txtVmName.Text, mySpec);
vimClient.Disconnect();