public ComputerSystem DeployVirtualMachine()

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;
        }