in plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs [222:497]
public ComputerSystem DeployVirtualMachine(dynamic jsonObj, string systemVmIso)
{
var vmInfo = jsonObj.vm;
string vmName = vmInfo.name;
var nicInfo = vmInfo.nics;
int vcpus = vmInfo.cpus;
int memSize = vmInfo.maxRam / 1048576;
string errMsg = vmName;
var diskDrives = vmInfo.disks;
var bootArgs = vmInfo.bootArgs;
// assert
errMsg = vmName + ": missing disk information, array empty or missing, agent expects *at least* one disk for a VM";
if (diskDrives == null)
{
logger.Error(errMsg);
throw new ArgumentException(errMsg);
}
// assert
errMsg = vmName + ": missing NIC information, array empty or missing, agent expects at least an empty array.";
if (nicInfo == null )
{
logger.Error(errMsg);
throw new ArgumentException(errMsg);
}
// For existing VMs, return when we spot one of this name not stopped. In the meantime, remove any existing VMs of same name.
ComputerSystem vmWmiObj = null;
while ((vmWmiObj = GetComputerSystem(vmName)) != null)
{
logger.WarnFormat("Create request for existing vm, name {0}", vmName);
if (vmWmiObj.EnabledState == EnabledState.Disabled)
{
logger.InfoFormat("Deleting existing VM with name {0}, before we go on to create a VM with the same name", vmName);
DestroyVm(vmName);
}
else if (vmWmiObj.EnabledState == EnabledState.Enabled)
{
string infoMsg = string.Format("Create VM discovered there exists a VM with name {0}, state {1}",
vmName,
EnabledState.ToString(vmWmiObj.EnabledState));
logger.Info(infoMsg);
return vmWmiObj;
}
else
{
errMsg = string.Format("Create VM failing, because there exists a VM with name {0}, state {1}",
vmName,
EnabledState.ToString(vmWmiObj.EnabledState));
var ex = new WmiException(errMsg);
logger.Error(errMsg, ex);
throw ex;
}
}
// Create vm carcase
logger.DebugFormat("Going ahead with create VM {0}, {1} vcpus, {2}MB RAM", vmName, vcpus, memSize);
var newVm = CreateVM(vmName, memSize, vcpus);
// Add a SCSI controller for attaching/detaching data volumes.
AddScsiController(newVm);
foreach (var diskDrive in diskDrives)
{
string vhdFile = null;
string diskName = null;
string isoPath = null;
VolumeObjectTO volInfo = VolumeObjectTO.ParseJson(diskDrive.data);
TemplateObjectTO templateInfo = TemplateObjectTO.ParseJson(diskDrive.data);
if (volInfo != null)
{
// assert
errMsg = vmName + ": volume missing primaryDataStore for disk " + diskDrive.ToString();
if (volInfo.primaryDataStore == null)
{
logger.Error(errMsg);
throw new ArgumentException(errMsg);
}
diskName = volInfo.name;
// assert
errMsg = vmName + ": can't deal with DataStore type for disk " + diskDrive.ToString();
if (volInfo.primaryDataStore == null)
{
logger.Error(errMsg);
throw new ArgumentException(errMsg);
}
errMsg = vmName + ": Malformed PrimaryDataStore for disk " + diskDrive.ToString();
if (String.IsNullOrEmpty(volInfo.primaryDataStore.Path))
{
logger.Error(errMsg);
throw new ArgumentException(errMsg);
}
errMsg = vmName + ": Missing folder PrimaryDataStore for disk " + diskDrive.ToString() + ", missing path: " + volInfo.primaryDataStore.Path;
if (!Directory.Exists(volInfo.primaryDataStore.Path))
{
logger.Error(errMsg);
throw new ArgumentException(errMsg);
}
vhdFile = volInfo.FullFileName;
if (!System.IO.File.Exists(vhdFile))
{
errMsg = vmName + ": non-existent volume, missing " + vhdFile + " for drive " + diskDrive.ToString();
logger.Error(errMsg);
throw new ArgumentException(errMsg);
}
logger.Debug("Going to create " + vmName + " with attached voluem " + diskName + " at " + vhdFile);
}
else if (templateInfo != null && templateInfo.nfsDataStoreTO != null)
{
NFSTO share = templateInfo.nfsDataStoreTO;
// The share is mapped, now attach the iso
isoPath = Utils.NormalizePath(Path.Combine(share.UncPath, templateInfo.path));
}
string driveType = diskDrive.type;
string ideCtrllr = "0";
string driveResourceType = null;
switch (driveType) {
case "ROOT":
ideCtrllr = "0";
driveResourceType = HARDDISK_DRIVE;
break;
case "ISO":
ideCtrllr = "1";
driveResourceType = ISO_DRIVE;
break;
case "DATADISK":
break;
default:
// TODO: double check exception type
errMsg = string.Format("Unknown disk type {0} for disk {1}, vm named {2}",
string.IsNullOrEmpty(driveType) ? "NULL" : driveType,
string.IsNullOrEmpty(diskName) ? "NULL" : diskName, vmName);
var ex = new WmiException(errMsg);
logger.Error(errMsg, ex);
throw ex;
}
logger.DebugFormat("Create disk type {1} (Named: {0}), on vm {2} {3}", diskName, driveResourceType, vmName,
string.IsNullOrEmpty(vhdFile) ? " no disk to insert" : ", inserting disk" + vhdFile);
if (driveType.Equals("DATADISK"))
{
AttachDisk(vmName, vhdFile, (string)diskDrive.diskSeq);
}
else
{
AddDiskDriveToIdeController(newVm, vhdFile, ideCtrllr, driveResourceType);
if (isoPath != null)
{
AttachIso(vmName, isoPath);
}
}
}
int nicCount = 0;
int enableState = 2;
// Add the Nics to the VM in the deviceId order.
foreach (var nc in nicInfo)
{
foreach (var nic in nicInfo)
{
int nicid = nic.deviceId;
Int32 networkRateMbps = nic.networkRateMbps;
string mac = nic.mac;
string vlan = null;
string isolationUri = nic.isolationUri;
string broadcastUri = nic.broadcastUri;
string nicIp = nic.ip;
string nicNetmask = nic.netmask;
if ( (broadcastUri != null ) || (isolationUri != null && isolationUri.StartsWith("vlan://")))
{
if (broadcastUri != null && broadcastUri.StartsWith("storage"))
{
vlan = broadcastUri.Substring("storage://".Length);
}
else
{
vlan = isolationUri.Substring("vlan://".Length);
}
int tmp;
if (vlan.Equals("untagged", StringComparison.CurrentCultureIgnoreCase) ) {
// recevied vlan is untagged, don't parse for the vlan in the isolation uri
vlan = null;
}
else if (!int.TryParse(vlan, out tmp))
{
// TODO: double check exception type
errMsg = string.Format("Invalid VLAN value {0} for on vm {1} for nic uuid {2}", isolationUri, vmName, nic.uuid);
var ex = new WmiException(errMsg);
logger.Error(errMsg, ex);
throw ex;
}
}
if (nicid == nicCount)
{
if (nicIp.Equals("0.0.0.0") && nicNetmask.Equals("255.255.255.255"))
{
// this is the extra nic added to VR.
vlan = null;
enableState = 3;
}
// Create network adapter
var newAdapter = CreateNICforVm(newVm, mac);
String switchName ="";
if (nic.name != null)
{
switchName = nic.name;
}
EthernetPortAllocationSettingData portSettings = null;
// connection to vswitch
portSettings = AttachNicToPort(newVm, newAdapter, switchName, enableState);
//reset the flag for other nics
enableState = 2;
// set vlan
if (vlan != null)
{
SetPortVlan(vlan, portSettings);
}
if (networkRateMbps > 0)
{
SetBandWidthLimit((ulong)networkRateMbps, portSettings);
}
logger.DebugFormat("Created adapter {0} on port {1}, {2}",
newAdapter.Path, portSettings.Path, (vlan == null ? "No VLAN" : "VLAN " + vlan));
// logger.DebugFormat("Created adapter {0} on port {1}, {2}",
// newAdapter.Path, portSettings.Path, (vlan == null ? "No VLAN" : "VLAN " + vlan));
}
}
nicCount++;
}
// pass the boot args for the VM using KVP component.
// We need to pass the boot args to system vm's to get them configured with cloudstack configuration.
// Add new user data
var vm = GetComputerSystem(vmName);
if (bootArgs != null && !String.IsNullOrEmpty((string)bootArgs))
{
String bootargs = bootArgs;
AddUserData(vm, bootargs);
}
// call patch systemvm iso only for systemvms
if (vmName.StartsWith("r-") || vmName.StartsWith("s-") || vmName.StartsWith("v-"))
{
if (systemVmIso != null && systemVmIso.Length != 0)
{
patchSystemVmIso(vmName, systemVmIso);
}
}
logger.DebugFormat("Starting VM {0}", vmName);
SetState(newVm, RequiredState.Enabled);
// Mark the VM as created by cloudstack tag
TagVm(newVm);
// we need to reboot to get the hv kvp daemon get started vr gets configured.
if (vmName.StartsWith("r-") || vmName.StartsWith("s-") || vmName.StartsWith("v-"))
{
System.Threading.Thread.Sleep(90000);
}
logger.InfoFormat("Started VM {0}", vmName);
return newVm;
}