You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by da...@apache.org on 2014/07/30 12:05:39 UTC

[1/4] Fixed windows line ending issues

Repository: cloudstack
Updated Branches:
  refs/heads/4.4 51c691f02 -> 920f39baa


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/920f39ba/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs
index 1c5a458..2f404ff 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs
@@ -1,261 +1,261 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//   http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied.  See the License for the
-// specific language governing permissions and limitations
-// under the License.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using CloudStack.Plugin.WmiWrappers.ROOT.VIRTUALIZATION.V2;
-using log4net;
-using System.Globalization;
-using System.Management;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using CloudStack.Plugin.WmiWrappers.ROOT.CIMV2;
-using System.IO;
-using System.Net.NetworkInformation;
-using System.Net;
-
-namespace HypervResource
-{
-    public class WmiCallsV2 : IWmiCallsV2
-    {
-        public static String CloudStackUserDataKey = "cloudstack-vm-userdata";
-
-        /// <summary>
-        /// Defines the migration types.
-        /// </summary>
-        public enum MigrationType
-        {
-            VirtualSystem = 32768,
-            Storage = 32769,
-            Staged = 32770,
-            VirtualSystemAndStorage = 32771
-        };
-
-        /// <summary>
-        /// Defines migration transport types.
-        /// </summary>
-        public enum TransportType
-        {
-            TCP = 5,
-            SMB = 32768
-        };
-
-        public static void Initialize()
-        {
-            // Trigger assembly load into curren appdomain
-        }
-
-        private static ILog logger = LogManager.GetLogger(typeof(WmiCallsV2));
-
-        /// <summary>
-        /// Returns ping status of the given ip
-        /// </summary>
-        public static String PingHost(String ip)
-        {
-            return "Success";
-        }
-
-        /// <summary>
-        /// Returns ComputerSystem lacking any NICs and VOLUMEs
-        /// </summary>
-        public ComputerSystem AddUserData(ComputerSystem vm, string userData)
-        {
-            // Obtain controller for Hyper-V virtualisation subsystem
-            VirtualSystemManagementService vmMgmtSvc = GetVirtualisationSystemManagementService();
-
-            // Create object to hold the data.
-            KvpExchangeDataItem kvpItem = KvpExchangeDataItem.CreateInstance();
-            kvpItem.LateBoundObject["Name"] = WmiCallsV2.CloudStackUserDataKey;
-            kvpItem.LateBoundObject["Data"] = userData;
-            kvpItem.LateBoundObject["Source"] = 0;
-            logger.Debug("VM " + vm.Name + " gets userdata " + userData);
-
-            // Update the resource settings for the VM.
-            System.Management.ManagementBaseObject kvpMgmtObj = kvpItem.LateBoundObject;
-            System.Management.ManagementPath jobPath;
-            String kvpStr = kvpMgmtObj.GetText(System.Management.TextFormat.CimDtd20);
-            uint ret_val = vmMgmtSvc.AddKvpItems(new String[] { kvpStr }, vm.Path, out jobPath);
-
-            // If the Job is done asynchronously
-            if (ret_val == ReturnCode.Started)
-            {
-                JobCompleted(jobPath);
-            }
-            else if (ret_val != ReturnCode.Completed)
-            {
-                var errMsg = string.Format(
-                    "Failed to update VM {0} (GUID {1}) due to {2} (ModifyVirtualSystem call), existing VM not deleted",
-                    vm.ElementName,
-                    vm.Name,
-                    ReturnCode.ToString(ret_val));
-                var ex = new WmiException(errMsg);
-                logger.Error(errMsg, ex);
-                throw ex;
-            }
-
-            return vm;
-        }
-		
-        /// <summary>
-        /// Returns ComputerSystem lacking any NICs and VOLUMEs
-        /// </summary>
-        public ComputerSystem CreateVM(string name, long memory_mb, int vcpus)
-        {
-            // Obtain controller for Hyper-V virtualisation subsystem
-            VirtualSystemManagementService vmMgmtSvc = GetVirtualisationSystemManagementService();
-
-            // Create VM with correct name and default resources
-            ComputerSystem vm = CreateDefaultVm(vmMgmtSvc, name);
-
-            // Update the resource settings for the VM.
-
-            // Resource settings are referenced through the Msvm_VirtualSystemSettingData object.
-            VirtualSystemSettingData vmSettings = GetVmSettings(vm);
-
-            // For memory settings, there is no Dynamic Memory, so reservation, limit and quantity are identical.
-            MemorySettingData memSettings = GetMemSettings(vmSettings);
-            memSettings.LateBoundObject["VirtualQuantity"] = memory_mb;
-            memSettings.LateBoundObject["Reservation"] = memory_mb;
-            memSettings.LateBoundObject["Limit"] = memory_mb;
-
-            // Update the processor settings for the VM, static assignment of 100% for CPU limit
-            ProcessorSettingData procSettings = GetProcSettings(vmSettings);
-            procSettings.LateBoundObject["VirtualQuantity"] = vcpus;
-            procSettings.LateBoundObject["Reservation"] = vcpus;
-            procSettings.LateBoundObject["Limit"] = 100000;
-
-            ModifyVmResources(vmMgmtSvc, vm, new String[] {
-                memSettings.LateBoundObject.GetText(TextFormat.CimDtd20),
-                procSettings.LateBoundObject.GetText(TextFormat.CimDtd20)
-                });
-            logger.InfoFormat("VM with display name {0} has GUID {1}", vm.ElementName, vm.Name);
-            logger.DebugFormat("Resources for vm {0}: {1} MB memory, {2} vcpus", name, memory_mb, vcpus);
-
-            return vm;
-        }
-
-        /// <summary>
-        /// Create a (synthetic) nic, and attach it to the vm
-        /// </summary>
-        /// <param name="vm"></param>
-        /// <param name="mac"></param>
-        /// <param name="vlan"></param>
-        /// <returns></returns>
-        public SyntheticEthernetPortSettingData CreateNICforVm(ComputerSystem vm, string mac)
-        {
-            logger.DebugFormat("Creating nic for VM {0} (GUID {1})", vm.ElementName, vm.Name);
-
-            // Obtain controller for Hyper-V networking subsystem
-            var vmNetMgmtSvc = GetVirtualSwitchManagementService();
-
-            // Create NIC resource by cloning the default NIC 
-            var synthNICsSettings = SyntheticEthernetPortSettingData.GetInstances(vmNetMgmtSvc.Scope, "InstanceID LIKE \"%Default\"");
-
-            // Assert
-            if (synthNICsSettings.Count != 1)
-            {
-                var errMsg = string.Format("Internal error, coudl not find default SyntheticEthernetPort instance");
-                var ex = new WmiException(errMsg);
-                logger.Error(errMsg, ex);
-                throw ex;
-            }
-            var defaultSynthNICSettings = synthNICsSettings.OfType<SyntheticEthernetPortSettingData>().First();
-
-            var newSynthNICSettings = new SyntheticEthernetPortSettingData((ManagementBaseObject)defaultSynthNICSettings.LateBoundObject.Clone());
-
-            //  Assign configuration to new NIC
-            string normalisedMAC = string.Join("", (mac.Split(new char[] { ':' })));
-            newSynthNICSettings.LateBoundObject["ElementName"] = vm.ElementName;
-            newSynthNICSettings.LateBoundObject["Address"] = normalisedMAC;
-            newSynthNICSettings.LateBoundObject["StaticMacAddress"] = "TRUE";
-            newSynthNICSettings.LateBoundObject["VirtualSystemIdentifiers"] = new string[] { "{" + Guid.NewGuid().ToString() + "}" };
-            newSynthNICSettings.CommitObject();
-
-            // Insert NIC into vm
-            string[] newResources = new string[] { newSynthNICSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20)};
-            ManagementPath[] newResourcePaths = AddVirtualResource(newResources, vm );
-
-            // assert
-            if (newResourcePaths.Length != 1)
-            {
-                var errMsg = string.Format(
-                    "Failed to properly insert a single NIC on VM {0} (GUID {1}): number of resource created {2}",
-                    vm.ElementName,
-                    vm.Name,
-                    newResourcePaths.Length);
-                var ex = new WmiException(errMsg);
-                logger.Error(errMsg, ex);
-                throw ex;
-            }
-
-            return new SyntheticEthernetPortSettingData(newResourcePaths[0]);
-        }
-
-        public const string IDE_CONTROLLER = "Microsoft:Hyper-V:Emulated IDE Controller";
-        public const string SCSI_CONTROLLER = "Microsoft:Hyper-V:Synthetic SCSI Controller";
-        public const string HARDDISK_DRIVE = "Microsoft:Hyper-V:Synthetic Disk Drive";
-        public const string ISO_DRIVE = "Microsoft:Hyper-V:Synthetic DVD Drive";
-
-        // TODO: names harvested from Msvm_ResourcePool, not clear how to create new instances
-        public const string ISO_DISK = "Microsoft:Hyper-V:Virtual CD/DVD Disk"; // For IDE_ISO_DRIVE
-        public const string HARDDISK_DISK = "Microsoft:Hyper-V:Virtual Hard Disk"; // For IDE_HARDDISK_DRIVE
-
-        /// <summary>
-        /// Create new VM.  By default we start it. 
-        /// </summary>
-        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);
-                }
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CloudStack.Plugin.WmiWrappers.ROOT.VIRTUALIZATION.V2;
+using log4net;
+using System.Globalization;
+using System.Management;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using CloudStack.Plugin.WmiWrappers.ROOT.CIMV2;
+using System.IO;
+using System.Net.NetworkInformation;
+using System.Net;
+
+namespace HypervResource
+{
+    public class WmiCallsV2 : IWmiCallsV2
+    {
+        public static String CloudStackUserDataKey = "cloudstack-vm-userdata";
+
+        /// <summary>
+        /// Defines the migration types.
+        /// </summary>
+        public enum MigrationType
+        {
+            VirtualSystem = 32768,
+            Storage = 32769,
+            Staged = 32770,
+            VirtualSystemAndStorage = 32771
+        };
+
+        /// <summary>
+        /// Defines migration transport types.
+        /// </summary>
+        public enum TransportType
+        {
+            TCP = 5,
+            SMB = 32768
+        };
+
+        public static void Initialize()
+        {
+            // Trigger assembly load into curren appdomain
+        }
+
+        private static ILog logger = LogManager.GetLogger(typeof(WmiCallsV2));
+
+        /// <summary>
+        /// Returns ping status of the given ip
+        /// </summary>
+        public static String PingHost(String ip)
+        {
+            return "Success";
+        }
+
+        /// <summary>
+        /// Returns ComputerSystem lacking any NICs and VOLUMEs
+        /// </summary>
+        public ComputerSystem AddUserData(ComputerSystem vm, string userData)
+        {
+            // Obtain controller for Hyper-V virtualisation subsystem
+            VirtualSystemManagementService vmMgmtSvc = GetVirtualisationSystemManagementService();
+
+            // Create object to hold the data.
+            KvpExchangeDataItem kvpItem = KvpExchangeDataItem.CreateInstance();
+            kvpItem.LateBoundObject["Name"] = WmiCallsV2.CloudStackUserDataKey;
+            kvpItem.LateBoundObject["Data"] = userData;
+            kvpItem.LateBoundObject["Source"] = 0;
+            logger.Debug("VM " + vm.Name + " gets userdata " + userData);
+
+            // Update the resource settings for the VM.
+            System.Management.ManagementBaseObject kvpMgmtObj = kvpItem.LateBoundObject;
+            System.Management.ManagementPath jobPath;
+            String kvpStr = kvpMgmtObj.GetText(System.Management.TextFormat.CimDtd20);
+            uint ret_val = vmMgmtSvc.AddKvpItems(new String[] { kvpStr }, vm.Path, out jobPath);
+
+            // If the Job is done asynchronously
+            if (ret_val == ReturnCode.Started)
+            {
+                JobCompleted(jobPath);
+            }
+            else if (ret_val != ReturnCode.Completed)
+            {
+                var errMsg = string.Format(
+                    "Failed to update VM {0} (GUID {1}) due to {2} (ModifyVirtualSystem call), existing VM not deleted",
+                    vm.ElementName,
+                    vm.Name,
+                    ReturnCode.ToString(ret_val));
+                var ex = new WmiException(errMsg);
+                logger.Error(errMsg, ex);
+                throw ex;
+            }
+
+            return vm;
+        }
+		
+        /// <summary>
+        /// Returns ComputerSystem lacking any NICs and VOLUMEs
+        /// </summary>
+        public ComputerSystem CreateVM(string name, long memory_mb, int vcpus)
+        {
+            // Obtain controller for Hyper-V virtualisation subsystem
+            VirtualSystemManagementService vmMgmtSvc = GetVirtualisationSystemManagementService();
+
+            // Create VM with correct name and default resources
+            ComputerSystem vm = CreateDefaultVm(vmMgmtSvc, name);
+
+            // Update the resource settings for the VM.
+
+            // Resource settings are referenced through the Msvm_VirtualSystemSettingData object.
+            VirtualSystemSettingData vmSettings = GetVmSettings(vm);
+
+            // For memory settings, there is no Dynamic Memory, so reservation, limit and quantity are identical.
+            MemorySettingData memSettings = GetMemSettings(vmSettings);
+            memSettings.LateBoundObject["VirtualQuantity"] = memory_mb;
+            memSettings.LateBoundObject["Reservation"] = memory_mb;
+            memSettings.LateBoundObject["Limit"] = memory_mb;
+
+            // Update the processor settings for the VM, static assignment of 100% for CPU limit
+            ProcessorSettingData procSettings = GetProcSettings(vmSettings);
+            procSettings.LateBoundObject["VirtualQuantity"] = vcpus;
+            procSettings.LateBoundObject["Reservation"] = vcpus;
+            procSettings.LateBoundObject["Limit"] = 100000;
+
+            ModifyVmResources(vmMgmtSvc, vm, new String[] {
+                memSettings.LateBoundObject.GetText(TextFormat.CimDtd20),
+                procSettings.LateBoundObject.GetText(TextFormat.CimDtd20)
+                });
+            logger.InfoFormat("VM with display name {0} has GUID {1}", vm.ElementName, vm.Name);
+            logger.DebugFormat("Resources for vm {0}: {1} MB memory, {2} vcpus", name, memory_mb, vcpus);
+
+            return vm;
+        }
+
+        /// <summary>
+        /// Create a (synthetic) nic, and attach it to the vm
+        /// </summary>
+        /// <param name="vm"></param>
+        /// <param name="mac"></param>
+        /// <param name="vlan"></param>
+        /// <returns></returns>
+        public SyntheticEthernetPortSettingData CreateNICforVm(ComputerSystem vm, string mac)
+        {
+            logger.DebugFormat("Creating nic for VM {0} (GUID {1})", vm.ElementName, vm.Name);
+
+            // Obtain controller for Hyper-V networking subsystem
+            var vmNetMgmtSvc = GetVirtualSwitchManagementService();
+
+            // Create NIC resource by cloning the default NIC 
+            var synthNICsSettings = SyntheticEthernetPortSettingData.GetInstances(vmNetMgmtSvc.Scope, "InstanceID LIKE \"%Default\"");
+
+            // Assert
+            if (synthNICsSettings.Count != 1)
+            {
+                var errMsg = string.Format("Internal error, coudl not find default SyntheticEthernetPort instance");
+                var ex = new WmiException(errMsg);
+                logger.Error(errMsg, ex);
+                throw ex;
+            }
+            var defaultSynthNICSettings = synthNICsSettings.OfType<SyntheticEthernetPortSettingData>().First();
+
+            var newSynthNICSettings = new SyntheticEthernetPortSettingData((ManagementBaseObject)defaultSynthNICSettings.LateBoundObject.Clone());
+
+            //  Assign configuration to new NIC
+            string normalisedMAC = string.Join("", (mac.Split(new char[] { ':' })));
+            newSynthNICSettings.LateBoundObject["ElementName"] = vm.ElementName;
+            newSynthNICSettings.LateBoundObject["Address"] = normalisedMAC;
+            newSynthNICSettings.LateBoundObject["StaticMacAddress"] = "TRUE";
+            newSynthNICSettings.LateBoundObject["VirtualSystemIdentifiers"] = new string[] { "{" + Guid.NewGuid().ToString() + "}" };
+            newSynthNICSettings.CommitObject();
+
+            // Insert NIC into vm
+            string[] newResources = new string[] { newSynthNICSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20)};
+            ManagementPath[] newResourcePaths = AddVirtualResource(newResources, vm );
+
+            // assert
+            if (newResourcePaths.Length != 1)
+            {
+                var errMsg = string.Format(
+                    "Failed to properly insert a single NIC on VM {0} (GUID {1}): number of resource created {2}",
+                    vm.ElementName,
+                    vm.Name,
+                    newResourcePaths.Length);
+                var ex = new WmiException(errMsg);
+                logger.Error(errMsg, ex);
+                throw ex;
+            }
+
+            return new SyntheticEthernetPortSettingData(newResourcePaths[0]);
+        }
+
+        public const string IDE_CONTROLLER = "Microsoft:Hyper-V:Emulated IDE Controller";
+        public const string SCSI_CONTROLLER = "Microsoft:Hyper-V:Synthetic SCSI Controller";
+        public const string HARDDISK_DRIVE = "Microsoft:Hyper-V:Synthetic Disk Drive";
+        public const string ISO_DRIVE = "Microsoft:Hyper-V:Synthetic DVD Drive";
+
+        // TODO: names harvested from Msvm_ResourcePool, not clear how to create new instances
+        public const string ISO_DISK = "Microsoft:Hyper-V:Virtual CD/DVD Disk"; // For IDE_ISO_DRIVE
+        public const string HARDDISK_DISK = "Microsoft:Hyper-V:Virtual Hard Disk"; // For IDE_HARDDISK_DRIVE
+
+        /// <summary>
+        /// Create new VM.  By default we start it. 
+        /// </summary>
+        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}",
@@ -267,898 +267,1845 @@ namespace HypervResource
                 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;
-                    Utils.ConnectToRemote(share.UncPath, share.Domain, share.User, share.Password);
-                    // 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;
+                        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;
+                    Utils.ConnectToRemote(share.UncPath, share.Domain, share.User, share.Password);
+                    // 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 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 ( (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;
+                        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);
                         }
-
-                        // 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;
-        }
-
-        public static Boolean pingResource(String ip)
-        {
-            PingOptions pingOptions = null;
-            PingReply pingReply = null;
-            IPAddress ipAddress = null;
-            Ping pingSender = new Ping();
-            int numberOfPings = 6;
-            int pingTimeout = 1000;
-            int byteSize = 32;
-            byte[] buffer = new byte[byteSize];
-            ipAddress = IPAddress.Parse(ip);
-            pingOptions = new PingOptions();
-            for (int i = 0; i < numberOfPings; i++)
-            {
-                pingReply = pingSender.Send(ipAddress, pingTimeout, buffer, pingOptions);
-                if (pingReply.Status == IPStatus.Success)
-                {
-                    System.Threading.Thread.Sleep(30000);
-                    return true;
-                }
-                else
-                {
-                    // wait for the second boot and then return with suces
-                    System.Threading.Thread.Sleep(30000);
-                }
-            }
-            return false;
-        }
-
-        private EthernetPortAllocationSettingData AttachNicToPort(ComputerSystem newVm, SyntheticEthernetPortSettingData newAdapter, String vSwitchName, int enableState)
-        {
-            // Get the virtual switch
-            VirtualEthernetSwitch vSwitch = GetExternalVirtSwitch(vSwitchName);
-            //check the the recevied vSwitch is the same as vSwitchName.
-            if (!vSwitchName.Equals("")  && !vSwitch.ElementName.Equals(vSwitchName))
-            {
-               var errMsg = string.Format("Internal error, coudl not find Virtual Switch with the name : " +vSwitchName);
-               var ex = new WmiException(errMsg);
-               logger.Error(errMsg, ex);
-               throw ex;
-            }
-
-            // Create port for adapter
-            var defaultEthernetPortSettings = EthernetPortAllocationSettingData.GetInstances(vSwitch.Scope, "InstanceID LIKE \"%Default\"");
-
-            // assert
-            if (defaultEthernetPortSettings.Count != 1)
-            {
-                var errMsg = string.Format("Internal error, coudl not find default EthernetPortAllocationSettingData instance");
-                var ex = new WmiException(errMsg);
-                logger.Error(errMsg, ex);
-                throw ex;
-            }
-
-            var defaultEthernetPortSettingsObj = defaultEthernetPortSettings.OfType<EthernetPortAllocationSettingData>().First();
-            var newEthernetPortSettings = new EthernetPortAllocationSettingData((ManagementBaseObject)defaultEthernetPortSettingsObj.LateBoundObject.Clone());
-            newEthernetPortSettings.LateBoundObject["Parent"] = newAdapter.Path.Path;
-            newEthernetPortSettings.LateBoundObject["HostResource"] = new string[] { vSwitch.Path.Path };
-            newEthernetPortSettings.LateBoundObject["EnabledState"] = enableState; //3 disabled 2 Enabled
-            // Insert NIC into vm
-            string[] newResources = new string[] { newEthernetPortSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20) };
-            ManagementPath[] newResourcePaths = AddVirtualResource(newResources, newVm);
-
-            // assert
-            if (newResourcePaths.Length != 1)
-            {
-                var errMsg = string.Format(
-                    "Failed to properly insert a single NIC on VM {0} (GUID {1}): number of resource created {2}",
-                    newVm.ElementName,
-                    newVm.Name,
-                    newResourcePaths.Length);
-                var ex = new WmiException(errMsg);
-                logger.Error(errMsg, ex);
-                throw ex;
-            }
-
-            return new EthernetPortAllocationSettingData(newResourcePaths[0]);
-        }
-
-        /// this method is to add a dvd drive and attach the systemvm iso.
-        /// 
-        public void patchSystemVmIso(String vmName, String systemVmIso)
-        {
-            ComputerSystem vmObject = GetComputerSystem(vmName);
-            AddDiskDriveToIdeController(vmObject, "", "1", ISO_DRIVE);
-            AttachIso(vmName, systemVmIso);
-        }
-
-        public void AttachDisk(string vmName, string diskPath, string addressOnController)
-        {
-            logger.DebugFormat("Got request to attach disk {0} to vm {1}", diskPath, vmName);
-
-            ComputerSystem vm = GetComputerSystem(vmName);
-            if (vm == null)
-            {
-                logger.DebugFormat("VM {0} not found", vmName);
-                return;
-            }
-            else
-            {
-                ManagementPath newDrivePath = GetDiskDriveOnScsiController(vm, addressOnController);
-                if (newDrivePath == null)
-                {
-                    newDrivePath = AttachDiskDriveToScsiController(vm, addressOnController);
-                }
-                InsertDiskImage(vm, diskPath, HARDDISK_DISK, newDrivePath);
-            }
-        }
-
-        /// </summary>
-        /// <param name="vm"></param>
-        /// <param name="cntrllerAddr"></param>
-        /// <param name="driveResourceType">IDE_HARDDISK_DRIVE or IDE_ISO_DRIVE</param>
-        public ManagementPath AddDiskDriveToIdeController(ComputerSystem vm, string vhdfile, string cntrllerAddr, string driveResourceType)
-        {
-            logger.DebugFormat("Creating DISK for VM {0} (GUID {1}) by attaching {2}", 
-                        vm.ElementName,
-                        vm.Name,
-                        vhdfile);
-
-            // Determine disk type for drive and assert drive type valid
-            string diskResourceSubType = null;
-            switch(driveResourceType) {
-                case HARDDISK_DRIVE:
-                    diskResourceSubType = HARDDISK_DISK;
-                    break;
-                case ISO_DRIVE: 
-                    diskResourceSubType = ISO_DISK;
-                    break;
-                default:
-                    var errMsg = string.Format(
-                        "Unrecognised disk drive type {0} for VM {1} (GUID {2})",
-                        string.IsNullOrEmpty(driveResourceType) ? "NULL": driveResourceType, 
-                        vm.ElementName,
-                        vm.Name);
-                    var ex = new WmiException(errMsg);
-                    logger.Error(errMsg, ex);
-                    throw ex;
-            }
-
-            ManagementPath newDrivePath = AttachNewDrive(vm, cntrllerAddr, driveResourceType);
-
-            // If there's not disk to insert, we are done.
-            if (String.IsNullOrEmpty(vhdfile))
-            {
-                logger.DebugFormat("No disk to be added to drive, disk drive {0} is complete", newDrivePath.Path);
-            }
-            else
-            {
-                InsertDiskImage(vm, vhdfile, diskResourceSubType, newDrivePath);
-            }
-            return newDrivePath;
-        }
-
-
-        public void DetachDisk(string displayName, string diskFileName)
-        {
-            logger.DebugFormat("Got request to detach virtual disk {0} from vm {1}", diskFileName, displayName);
-
-            ComputerSystem vm = GetComputerSystem(displayName);
-            if (vm == null)
-            {
-                logger.DebugFormat("VM {0} not found", displayName);
-                return;
-            }
-            else
-            {
-                RemoveStorageImage(vm, diskFileName);
-            }
-        }
-
-        /// <summary>
-        /// Removes a disk image from a drive, but does not remove the drive itself.
-        /// </summary>
-        /// <param name="vm"></param>
-        /// <param name="diskFileName"></param>
-        private void RemoveStorageImage(ComputerSystem vm, string diskFileName)
-        {
-            // Obtain StorageAllocationSettingData for disk
-            StorageAllocationSettingData.StorageAllocationSettingDataCollection storageSettingsObjs = StorageAllocationSettingData.GetInstances();
-
-            StorageAllocationSettingData imageToRemove = null;
-            foreach (StorageAllocationSettingData item in storageSettingsObjs)
-            {
-                if (item.HostResource == null || item.HostResource.Length != 1)
-                {
-                    continue;
-                }
-
-                string hostResource = item.HostResource[0];
-                if (Path.Equals(hostResource, diskFileName))
-                {
-                    imageToRemove = item;
-                    break;
-                }
-            }
-
-            // assert
-            if (imageToRemove  == null)
-            {
-                var errMsg = string.Format(
-                    "Failed to remove disk image {0} from VM {1} (GUID {2}): the disk image is not attached.",
-                    diskFileName,
-                    vm.ElementName,
-                    vm.Name);
-                var ex = new WmiException(errMsg);
-                logger.Error(errMsg, ex);
-                throw ex;
-            }
-
-            RemoveStorageResource(imageToRemove.Path, vm);
-
-            logger.InfoFormat("Removed disk image {0} from VM {1} (GUID {2}): the disk image is not attached.",
-                    diskFileName,
-                    vm.ElementName,
-                    vm.Name);
-        }
-
-        private ManagementPath AttachNewDrive(ComputerSystem vm, string cntrllerAddr, string driveType)
-        {
-            // Disk drives are attached to a 'Parent' IDE controller.  We IDE Controller's settings for the 'Path', which our new Disk drive will use to reference it.
-            VirtualSystemSettingData vmSettings = GetVmSettings(vm);
-            var ctrller = GetIDEControllerSettings(vmSettings, cntrllerAddr);
-
-            // A description of the drive is created by modifying a clone of the default ResourceAllocationSettingData for that drive type
-            string defaultDriveQuery = String.Format("ResourceSubType LIKE \"{0}\" AND InstanceID LIKE \"%Default\"", driveType);
-            var newDiskDriveSettings = CloneResourceAllocationSetting(defaultDriveQuery);
-
-            // Set IDE controller and address on the controller for the new drive
-            newDiskDriveSettings.LateBoundObject["Parent"] = ctrller.Path.ToString();
-            newDiskDriveSettings.LateBoundObject["AddressOnParent"] = "0";
-            newDiskDriveSettings.CommitObject();
-
-            // Add this new disk drive to the VM
-            logger.DebugFormat("Creating disk drive type {0}, parent IDE controller is {1} and address on controller is {2}",
-                newDiskDriveSettings.ResourceSubType,
-                newDiskDriveSettings.Parent,
-                newDiskDriveSettings.AddressOnParent);
-            string[] newDriveResource = new string[] { newDiskDriveSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20) };
-            ManagementPath[] newDrivePaths = AddVirtualResource(newDriveResource, vm);
-
-            // assert
-            if (newDrivePaths.Length != 1)
-            {
-                var errMsg = string.Format(
-                    "Failed to add disk drive type {3} to VM {0} (GUID {1}): number of resource created {2}",
-                    vm.ElementName,
-                    vm.Name,
-                    newDrivePaths.Length,
-                    driveType);
-                var ex = new WmiException(errMsg);
-                logger.Error(errMsg, ex);
-                throw ex;
-            }
-            logger.DebugFormat("New disk drive type {0} WMI path is {1}s",
-                newDiskDriveSettings.ResourceSubType,
-                newDrivePaths[0].Path);
-            return newDrivePaths[0];
-        }
-
-        private ManagementPath AddScsiController(ComputerSystem vm)
-        {
-            // A description of the controller is created by modifying a clone of the default ResourceAllocationSettingData for scsi controller
-            string scsiQuery = String.Format("ResourceSubType LIKE \"{0}\" AND InstanceID LIKE \"%Default\"", SCSI_CONTROLLER);
-            var scsiSettings = CloneResourceAllocationSetting(scsiQuery);
-
-            scsiSettings.LateBoundObject["ElementName"] = "SCSI Controller";
-            scsiSettings.CommitObject();
-
-            // Insert SCSI controller into vm
-            string[] newResources = new string[] { scsiSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20) };
-            ManagementPath[] newResourcePaths = AddVirtualResource(newResources, vm);
-
-            // assert
-            if (newResourcePaths.Length != 1)
-            {
-                var errMsg = string.Format(
-                    "Failed to add scsi controller to VM {0} (GUID {1}): number of resource created {2}",
-                    vm.ElementName,
-                    vm.Name,
-                    newResourcePaths.Length);
-                var ex = new WmiException(errMsg);
-                logger.Error(errMsg, ex);
-                throw ex;
-            }
-
-            logger.DebugFormat("New controller type {0} WMI path is {1}s",
-                scsiSettings.ResourceSubType,
-                newResourcePaths[0].Path);
-            return newResourcePaths[0];
-        }
-
-        private ManagementPath GetDiskDriveOnScsiController(ComputerSystem vm, string addrOnController)
-        {
-            VirtualSystemSettingData vmSettings = GetVmSettings(vm);
-            var wmiObjCollection = GetResourceAllocationSettings(vmSettings);
-            foreach (ResourceAllocationSettingData wmiObj in wmiObjCollection)
-            {
-                if (wmiObj.ResourceSubType == HARDDISK_DRIVE)
-                {
-                    ResourceAllocationSettingData parent = new ResourceAllocationSettingData(new ManagementObject(wmiObj.Parent));
-                    if (parent.ResourceSubType == SCSI_CONTROLLER && wmiObj.AddressOnParent == addrOnController)
-                    {
-                        return wmiObj.Path;
-                    }
-                }
-            }
-            return null;
-        }
-
-        private ManagementPath AttachDiskDriveToScsiController(ComputerSystem vm, string addrOnController)
-        {
-            // Disk drives are attached to a 'Parent' Scsi controller.
-            VirtualSystemSettingData vmSettings = GetVmSettings(vm);
-            var ctrller = GetScsiControllerSettings(vmSettings);
-
-            // A description of the drive is created by modifying a clone of the default ResourceAllocationSettingData for that drive type
-            string defaultDriveQuery = String.Format("ResourceSubType LIKE \"{0}\" AND InstanceID LIKE \"%Default\"", HARDDISK_DRIVE);
-            var newDiskDriveSettings = CloneResourceAllocationSetting(defaultDriveQuery);
-
-            // Set IDE controller and address on the controller for the new drive
-            newDiskDriveSettings.LateBoundObject["Parent"] = ctrller.Path.ToString();
-            newDiskDriveSettings.LateBoundObject["AddressOnParent"] = addrOnController;
-            newDiskDriveSettings.CommitObject();
-
-            // Add this new disk drive to the VM
-            logger.DebugFormat("Creating disk drive type {0}, parent IDE controller is {1} and address on controller is {2}",
-                newDiskDriveSettings.ResourceSubType,
-                newDiskDriveSettings.Parent,
-                newDiskDriveSettings.AddressOnParent);
-            string[] newDriveResource = new string[] { newDiskDriveSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20) };
-            ManagementPath[] newDrivePaths = AddVirtualResource(newDriveResource, vm);
-
-            // assert
-            if (newDrivePaths.Length != 1)
-            {
-                var errMsg = string.Format(
-                    "Failed to add disk drive type {3} to VM {0} (GUID {1}): number of resource created {2}",
-                    vm.ElementName,
-                    vm.Name,
-                    newDrivePaths.Length,
-                    HARDDISK_DRIVE);
-                var ex = new WmiException(errMsg);
-                logger.Error(errMsg, ex);
-                throw ex;
-            }
-            logger.DebugFormat("New disk drive type {0} WMI path is {1}s",
-                newDiskDriveSettings.ResourceSubType,
-                newDrivePaths[0].Path);
-            return newDrivePaths[0];
-        }
-
-
-        private void InsertDiskImage(ComputerSystem vm, string diskImagePath, string diskResourceSubType, ManagementPath drivePath)
-        {
-            // A description of the disk is created by modifying a clone of the default ResourceAllocationSettingData for that disk type
-            string defaultDiskQuery = String.Format("ResourceSubType LIKE \"{0}\" AND InstanceID LIKE \"%Default\"", diskResourceSubType);
-            var newDiskSettings = CloneStorageAllocationSetting(defaultDiskQuery);
-
-            // Set file containing the disk image
-            newDiskSettings.LateBoundObject["Parent"] = drivePath.Path;
-
-            // V2 API uses HostResource to specify image, see http://msdn.microsoft.com/en-us/library/hh859775(v=vs.85).aspx
-            newDiskSettings.LateBoundObject["HostResource"] = new string[] { diskImagePath };
-            newDiskSettings.CommitObject();
-
-            // Add the new Msvm_StorageAllocationSettingData object as a virtual hard disk to the vm.
-            string[] newDiskResource = new string[] { newDiskSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20) };
-            ManagementPath[] newDiskPaths = AddStorageResource(newDiskResource, vm);
-            // assert
-            if (newDiskPaths.Length != 1)
-            {
-                var errMsg = string.Format(
-                    "Failed to add disk image type {3} to VM {0} (GUID {1}): number of resource created {2}",
-                    vm.ElementName,
-                    vm.Name,
-                    newDiskPaths.Length,
-                    diskResourceSubType);
-                var ex = new WmiException(errMsg);
-                logger.Error(errMsg, ex);
-                throw ex;
-            }
-            logger.InfoFormat("Created disk {2} for VM {0} (GUID {1}), image {3} ",
-                    vm.ElementName,
-                    vm.Name,
-                    newDiskPaths[0].Path,
-                    diskImagePath);
-        }
-
-        /// <summary>
-        /// Create Msvm_StorageAllocationSettingData corresponding to the ISO image, and 
-        /// associate this with the VM's DVD drive.
-        /// </summary>
-        private void AttachIso(ComputerSystem vm, string isoPath)
-        {
-            // Disk drives are attached to a 'Parent' IDE controller.  We IDE Controller's settings for the 'Path', which our new Disk drive will use to reference it.
-            VirtualSystemSettingData vmSettings = GetVmSettings(vm);
-            var driveWmiObj = GetDvdDriveSettings(vmSettings);
-            InsertDiskImage(vm, isoPath, ISO_DISK, driveWmiObj.Path);
-        }
-
-        private static ResourceAllocationSettingData CloneResourceAllocationSetting(string wmiQuery)
-        {
-            var defaultDiskDriveSettingsObjs = ResourceAllocationSettingData.GetInstances(wmiQuery);
-
-            // assert
-            if (defaultDiskDriveSettingsObjs.Count != 1)
-            {
-                var errMsg = string.Format("Failed to find Msvm_ResourceAllocationSettingData for the query {0}", wmiQuery);
-                var ex = new WmiException(errMsg);
-                logger.Error(errMsg, ex);
-                throw ex;
-            }
-
-            ResourceAllocationSettingData defaultDiskDriveSettings = defaultDiskDriveSettingsObjs.OfType<ResourceAllocationSettingData>().First();
-            return new ResourceAllocationSettingData((ManagementBaseObject)defaultDiskDriveSettings.LateBoundObject.Clone());
-        }
-
-        // Modify the systemvm nic's VLAN id
-        public void ModifyVmVLan(string vmName, String vlanid, String mac)
-        {
-            int enableState = 2;
-            bool enable = true;
-            ComputerSystem vm = GetComputerSystem(vmName);
-            SyntheticEthernetPortSettingData[] nicSettingsViaVm = GetEthernetPortSettings(vm);
+                        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;
+        }
+
+        public static Boolean pingResource(String ip)
+        {
+            PingOptions pingOptions = null;
+            PingReply pingReply = null;
+            IPAddress ipAddress = null;
+            Ping pingSender = new Ping();
+            int numberOfPings = 6;
+            int pingTimeout = 1000;
+            int byteSize = 32;
+            byte[] buffer = new byte[byteSize];
+            ipAddress = IPAddress.Parse(ip);
+            pingOptions = new PingOptions();
+            for (int i = 0; i < numberOfPings; i++)
+            {
+                pingReply = pingSender.Send(ipAddress, pingTimeout, buffer, pingOptions);
+                if (pingReply.Status == IPStatus.Success)
+                {
+                    System.Threading.Thread.Sleep(30000);
+                    return true;
+                }
+                else
+                {
+                    // wait for the second boot and then return with suces
+                    System.Threading.Thread.Sleep(30000);
+                }
+            }
+            return false;
+        }
+
+        private EthernetPortAllocationSettingData AttachNicToPort(ComputerSystem newVm, SyntheticEthernetPortSettingData newAdapter, String vSwitchName, int enableState)
+        {
+            // Get the virtual switch
+            VirtualEthernetSwitch vSwitch = GetExternalVirtSwitch(vSwitchName);
+            //check the the recevied vSwitch is the same as vSwitchName.
+            if (!vSwitchName.Equals("")  && !vSwitch.ElementName.Equals(vSwitchName))
+            {
+               var errMsg = string.Format("Internal error, coudl not find Virtual Switch with the name : " +vSwitchName);
+               var ex = new WmiException(errMsg);
+               logger.Error(errMsg, ex);
+               throw ex;
+            }
+
+            // Create port for adapter
+            var defaultEthernetPortSettings = EthernetPortAllocationSettingData.GetInstances(vSwitch.Scope, "InstanceID LIKE \"%Default\"");
+
+            // assert
+            if (defaultEthernetPortSettings.Count != 1)
+            {
+                var errMsg = string.Format("Internal error, coudl not find default EthernetPortAllocationSettingData instance");
+                var ex = new WmiException(errMsg);
+                logger.Error(errMsg, ex);
+                throw ex;
+            }
+
+            var defaultEthernetPortSettingsObj = defaultEthernetPortSettings.OfType<EthernetPortAllocationSettingData>().First();
+            var newEthernetPortSettings = new EthernetPortAllocationSettingData((ManagementBaseObject)defaultEthernetPortSettingsObj.LateBoundObject.Clone());
+            newEthernetPortSettings.LateBoundObject["Parent"] = newAdapter.Path.Path;
+            newEthernetPortSettings.LateBoundObject["HostResource"] = new string[] { vSwitch.Path.Path };
+            newEthernetPortSettings.LateBoundObject["EnabledState"] = enableState; //3 disabled 2 Enabled
+            // Insert NIC into vm
+            string[] newResources = new string[] { newEthernetPortSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20) };
+            ManagementPath[] newResourcePaths = AddVirtualResource(newResources, newVm);
+
+            // assert
+            if (newResourcePaths.Length != 1)
+            {
+                var errMsg = string.Format(
+                    "Failed to properly insert a single NIC on VM {0} (GUID {1}): number of resource created {2}",
+                    newVm.ElementName,
+                    newVm.Name,
+                    newResourcePaths.Length);
+                var ex = new WmiException(errMsg);
+                logger.Error(errMsg, ex);
+                throw ex;
+            }
+
+            return new EthernetPortAllocationSettingData(newResourcePaths[0]);
+        }
+
+        /// this method is to add a dvd drive and attach the systemvm iso.
+        /// 
+        public void patchSystemVmIso(String vmName, String systemVmIso)
+        {
+            ComputerSystem vmObject = GetComputerSystem(vmName);
+            AddDiskDriveToIdeController(vmObject, "", "1", ISO_DRIVE);
+            AttachIso(vmName, systemVmIso);
+        }
+
+        public void AttachDisk(string vmName, string diskPath, string addressOnController)
+        {
+            logger.DebugFormat("Got request to attach disk {0} to vm {1}", diskPath, vmName);
+
+            ComputerSystem vm = GetComputerSystem(vmName);
+            if (vm == null)
+            {
+                logger.DebugFormat("VM {0} not found", vmName);
+                return;
+            }
+            else
+            {
+                ManagementPath newDrivePath = GetDiskDriveOnScsiController(vm, addressOnController);
+                if (newDrivePath == null)
+                {
+                    newDrivePath = AttachDiskDriveToScsiController(vm, addressOnController);
+                }
+                InsertDiskImage(vm, diskPath, HARDDISK_DISK, newDrivePath);
+            }
+        }
+
+        /// </summary>
+        /// <param name="vm"></param>
+        /// <param name="cntrllerAddr"></param>
+        /// <param name="driveResourceType">IDE_HARDDISK_DRIVE or IDE_ISO_DRIVE</param>
+        public ManagementPath AddDiskDriveToIdeController(ComputerSystem vm, string vhdfile, string cntrllerAddr, string driveResourceType)
+        {
+            logger.DebugFormat("Creating DISK for VM {0} (GUID {1}) by attaching {2}", 
+                        vm.ElementName,
+                        vm.Name,
+                        vhdfile);
+
+            // Determine disk type for drive and assert drive type valid
+            string diskResourceSubType = null;
+            switch(driveResourceType) {
+                case HARDDISK_DRIVE:
+                    diskResourceSubType = HARDDISK_DISK;
+                    break;
+                case ISO_DRIVE: 
+                    diskResourceSubType = ISO_DISK;
+                    break;
+                default:
+                    var errMsg = string.Format(
+                        "Unrecognised disk drive type {0} for VM {1} (GUID {2})",
+                        string.IsNullOrEmpty(driveResourceType) ? "NULL": driveResourceType, 
+                        vm.ElementName,
+                        vm.Name);
+                    var ex = new WmiException(errMsg);
+                    logger.Error(errMsg, ex);
+                    throw ex;
+            }
+
+            ManagementPath newDrivePath = AttachNewDrive(vm, cntrllerAddr, driveResourceType);
+
+            // If there's not disk to insert, we are done.
+            if (String.IsNullOrEmpty(vhdfile))
+            {
+                logger.DebugFormat("No disk to be added to drive, disk drive {0} is complete", newDrivePath.Path);
+            }
+            else
+            {
+                InsertDiskImage(vm, vhdfile, diskResourceSubType, newDrivePath);
+            }
+            return newDrivePath;
+        }
+
+
+        public void DetachDisk(string displayName, string diskFileName)
+        {
+            logger.DebugFormat("Got request to detach virtual disk {0} from vm {1}", diskFileName, displayName);
+
+            ComputerSystem vm = GetComputerSystem(displayName);
+            if (vm == null)
+            {
+                logger.DebugFormat("VM {0} not found", displayName);
+                return;
+            }
+            else
+            {
+                RemoveStorageImage(vm, diskFileName);
+            }
+        }
+
+        /// <summary>
+        /// Removes a disk image from a drive, but does not remove the drive itself.
+        /// </summary>
+        /// <param name="vm"></param>
+        /// <param name="diskFileName"></param>
+        private void RemoveStorageImage(ComputerSystem vm, string diskFileName)
+        {
+            // Obtain StorageAllocationSettingData for disk
+            StorageAllocationSettingData.StorageAllocationSettingDataCollection storageSettingsObjs = StorageAllocationSettingData.GetInstances();
+
+            StorageAllocationSettingData imageToRemove = null;
+            foreach (StorageAllocationSettingData item in storageSettingsObjs)
+            {
+                if (item.HostResource == null || item.HostResource.Length != 1)
+                {
+                    continue;
+                }
+
+                string hostResource = item.HostResource[0];
+                if (Path.Equals(hostResource, diskFileName))
+                {
+                    imageToRemove = item;
+                    break;
+                }
+            }
+
+            // assert
+            if (imageToRemove  == null)
+            {
+                var errMsg = string.Format(
+                    "Failed to remove disk image {0} from VM {1} (GUID {2}): the disk image is not attached.",
+                    diskFileName,
+                    vm.ElementName,
+                    vm.Name);
+                var ex = new WmiException(errMsg);
+                logger.Error(errMsg, ex);
+                throw ex;
+            }
+
+            RemoveStorageResource(imageToRemove.Path, vm);
+
+            logger.InfoFormat("Removed disk image {0} from VM {1} (GUID {2}): the disk image is not attached.",
+                    diskFileName,
+                    vm.ElementName,
+                    vm.Name);
+        }
+
+        private ManagementPath AttachNewDrive(ComputerSystem vm, string cntrllerAddr, string driveType)
+        {
+            // Disk drives are attached to a 'Parent' IDE controller.  We IDE Controller's settings for the 'Path', which our new Disk drive will use to reference it.
+            VirtualSystemSettingData vmSettings = GetVmSettings(vm);
+            var ctrller = GetIDEControllerSettings(vmSettings, cntrllerAddr);
+
+            // A description of the drive is created by modifying a clone of the default ResourceAllocationSettingData for that drive type
+            string defaultDriveQuery = String.Format("ResourceSubType LIKE \"{0}\" AND InstanceID LIKE \"%Default\"", driveType);
+            var newDiskDriveSettings = CloneResourceAllocationSetting(defaultDriveQuery);
+
+            // Set IDE controller and address on the controller for the new drive
+            newDiskDriveSettings.LateBoundObject["Parent"] = ctrller.Path.ToString();
+            newDiskDriveSettings.LateBoundObject["AddressOnParent"] = "0";
+            newDiskDriveSettings.CommitObject();
+
+            // Add this new disk drive to the VM
+            logger.DebugFormat("Creating disk drive type {0}, parent IDE controller is {1} and address on controller is {2}",
+                newDiskDriveSettings.ResourceSubType,
+                newDiskDriveSettings.Parent,
+                newDiskDriveSettings.AddressOnParent);
+            string[] newDriveResource = new string[] { newDiskDriveSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20) };
+            ManagementPath[] newDrivePaths = AddVirtualResource(newDriveResource, vm);
+
+            // assert
+            if (newDrivePaths.Length != 1)
+            {
+                var errMsg = string.Format(
+                    "Failed to add disk drive type {3} to VM {0} (GUID {1}): number of resource created {2}",
+                    vm.ElementName,
+                    vm.Name,
+                    newDrivePaths.Length,
+                    driveType);
+                var ex = new WmiException(errMsg);
+                logger.Error(errMsg, ex);
+                throw ex;
+            }
+            logger.DebugFormat("New disk drive type {0} WMI path is {1}s",
+                newDiskDriveSettings.ResourceSubType,
+                newDrivePaths[0].Path);
+            return newDrivePaths[0];
+        }
+
+        private ManagementPath AddScsiController(ComputerSystem vm)
+        {
+            // A description of the controller is created by modifying a clone of the default ResourceAllocationSettingData for scsi controller
+            string scsiQuery = String.Format("ResourceSubType LIKE \"{0}\" AND InstanceID LIKE \"%Default\"", SCSI_CONTROLLER);
+            var scsiSettings = CloneResourceAllocationSetting(scsiQuery);
+
+            scsiSettings.LateBoundObject["ElementName"] = "SCSI Controller";
+            scsiSettings.CommitObject();
+
+            // Insert SCSI controller into vm
+            string[] newResources = new string[] { scsiSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20) };
+            ManagementPath[] newResourcePaths = AddVirtualResource(newResources, vm);
+
+            // assert
+            if (newResourcePaths.Length != 1)
+            {
+                var errMsg = string.Format(
+                    "Failed to add scsi controller to VM {0} (GUID {1}): number of resource created {2}",
+                    vm.ElementName,
+                    vm.Name,
+                    newResourcePaths.Length);
+                var ex = new WmiException(errMsg);
+                logger.Error(errMsg, ex);
+                throw ex;
+            }
+
+            logger.DebugFormat("New controller type {0} WMI path is {1}s",
+                scsiSettings.ResourceSubType,
+                newResourcePaths[0].Path);
+            return newResourcePaths[0];
+        }
+
+        private ManagementPath GetDiskDriveOnScsiController(ComputerSystem vm, string addrOnController)
+        {
+            VirtualSystemSettingData vmSettings = GetVmSettings(vm);
+            var wmiObjCollection = GetResourceAllocationSettings(vmSettings);
+            foreach (ResourceAllocationSettingData wmiObj in wmiObjCollection)
+            {
+                if (wmiObj.ResourceSubType == HARDDISK_DRIVE)
+                {
+                    ResourceAllocationSettingData parent = new ResourceAllocationSettingData(new ManagementObject(wmiObj.Parent));
+                    if (parent.ResourceSubType == SCSI_CONTROLLER && wmiObj.AddressOnParent == addrOnController)
+                    {
+                        return wmiObj.Path;
+                    }
+                }
+            }
+            return null;
+        }
+
+        private ManagementPath AttachDiskDriveToScsiController(ComputerSystem vm, string addrOnController)
+        {
+            // Disk drives are attached to a 'Parent' Scsi controller.
+            VirtualSystemSettingData vmSettings = GetVmSettings(vm);
+            var ctrller = GetScsiControllerSettings(vmSettings);
+
+            // A description of the drive is created by modifying a clone of the default ResourceAllocationSettingData for that drive type
+            string defaultDriveQuery = String.Format("ResourceSubType LIKE \"{0}\" AND InstanceID LIKE \"%Default\"", HARDDISK_DRIVE);
+            var newDiskDriveSettings = CloneResourceAllocationSetting(defaultDriveQuery);
+
+            // Set IDE controller and address on the controller for the new drive
+            newDiskDriveSettings.LateBoundObject["Parent"] = ctrller.Path.ToString();
+            newDiskDriveSettings.LateBoundObject["AddressOnParent"] = addrOnController;
+            newDiskDriveSettings.CommitObject();
+
+            // Add this new disk drive to the VM
+            logger.DebugFormat("Creating disk drive type {0}, parent IDE controller is {1} and address on controller is {2}",
+                newDiskDriveSettings.ResourceSubType,
+                newDiskDriveSettings.Parent,
+                newDiskDriveSettings.AddressOnParent);
+            string[] newDriveResource = new string[] { newDiskDriveSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20) };
+            ManagementPath[] newDrivePaths = AddVirtualResource(newDriveResource, vm);
+
+            // assert
+            if (newDrivePaths.Length != 1)
+            {
+                var errMsg = string.Format(
+                    "Failed to add disk drive type {3} to VM {0} (GUID {1}): number of resource created {2}",
+                    vm.ElementName,
+                    vm.Name,
+                    newDrivePaths.Length,
+                    HARDDISK_DRIVE);
+                var ex = new WmiException(errMsg);
+                logger.Error(errMsg, ex);
+                throw ex;
+            }
+            logger.DebugFormat("New disk drive type {0} WMI path is {1}s",
+                newDiskDriveSettings.ResourceSubType,
+                newDrivePaths[0].Path);
+            return newDrivePaths[0];
+        }
+
+
+        private void InsertDiskImage(ComputerSystem vm, string diskImagePath, string diskResourceSubType, ManagementPath drivePath)
+        {
+            // A description of the disk is created by modifying a clone of the default ResourceAllocationSettingData for that disk type
+            string defaultDiskQuery = String.Format("ResourceSubType LIKE \"{0}\" AND InstanceID LIKE \"%Default\"", diskResourceSubType);
+            var newDiskSettings = CloneStorageAllocationSetting(defaultDiskQuery);
+
+            // Set file containing the disk image
+            newDiskSettings.LateBoundObject["Parent"] = drivePath.Path;
+
+            // V2 API uses HostResource to specify image, see http://msdn.microsoft.com/en-us/library/hh859775(v=vs.85).aspx
+            newDiskSettings.LateBoundObject["HostResource"] = new string[] { diskImagePath };
+            newDiskSettings.CommitObject();
+
+            // Add the new Msvm_StorageAllocationSettingData object as a virtual hard disk to the vm.
+            string[] newDiskResource = new string[] { newDiskSettings.LateBoundObject.GetText(System.Management.TextFormat.CimDtd20) };
+            ManagementPath[] newDiskPaths = AddStorageResource(newDiskResource, vm);
+            // assert
+            if (newDiskPaths.Length != 1)
+            {
+                var errMsg = string.Format(
+                    "Failed to add disk image type {3} to VM {0} (GUID {1}): number of resource created {2}",
+                    vm.ElementName,
+                    vm.Name,
+                    newDiskPaths.Length,
+                    diskResourceSubType);
+                var ex = new WmiException(errMsg);
+                logger.Error(errMsg, ex);
+                throw ex;
+            }
+            logger.InfoFormat("Created disk {2} for VM {0} (GUID {1}), image {3} ",
+                    vm.ElementName,
+                    vm.Name,
+                    newDiskPaths[0].Path,
+                    diskImagePath);
+        }
+
+        /// <summary>
+        /// Create Msvm_StorageAllocationSettingData corresponding to the ISO image, and 
+        /// associate this with the VM's DVD drive.
+        /// </summary>
+        private void AttachIso(ComputerSystem vm, string isoPath)
+        {
+            // Disk drives are attached to a 'Parent' IDE controller.  We IDE Controller's settings for the 'Path', which our new Disk drive will use to reference it.
+            VirtualSystemSettingData vmSettings = GetVmSettings(vm);
+            var driveWmiObj = GetDvdDriveSettings(vmSettings);
+            InsertDiskImage(vm, isoPath, ISO_DISK, driveWmiObj.Path);
+        }
+
+        private static ResourceAllocationSettingData CloneResourceAllocationSetting(string wmiQuery)
+        {
+            var defaultDiskDriveSettingsObjs = ResourceAllocationSettingData.GetInstances(wmiQuery);
+
+            // assert
+            if (defaultDiskDriveSettingsObjs.Count != 1)
+            {
+                var errMsg = string.Format("Failed to find Msvm_ResourceAllocationSettingData for the query {0}", wmiQuery);
+                var ex = new WmiException(errMsg);
+                logger.Error(errMsg, ex);
+                throw ex;
+            }
+
+            ResourceAllocationSettingData defaultDiskDriveSettings = defaultDiskDriveSettingsObjs.OfType<ResourceAllocationSettingData>().First();
+            return new ResourceAllocationSettingData((ManagementBaseObject)defaultDiskDriveSettings.LateBoundObject.Clone());
+        }
+
+        // Modify the systemvm nic's VLAN id
+        public void ModifyVmVLan(string vmName, String vlanid, String mac)
+        {
+            int enableState = 2;
+            bool enable = true;
+            ComputerSystem vm = GetComputerSystem(vmName);
+            SyntheticEthernetPortSettingData[] nicSettingsViaVm = GetEthernetPortSettings(vm);
+            // Obtain controller for Hyper-V virtualisation subsystem
+            VirtualSystemManagementService vmMgmtSvc = GetVirtualisationSystemManagementService();
+            EthernetPortAllocationSettingData networkAdapter = null;
+            string normalisedMAC = string.Join("", (mac.Split(new char[] { ':' })));
+            int index = 0;
+            foreach (SyntheticEthernetPortSettingData item in nicSettingsViaVm)
+            {
+                if (normalisedMAC.ToLower().Equals(item.Address.ToLower()))
+                {
+                    break;
+                }
+                index++;
+            }
+            String vSwitchName = "";
+            VirtualEthernetSwitch vSwitch = GetExternalVirtSwitch(vSwitchName);
+            EthernetPortAllocationSettingData[] ethernetConnections = GetEthernetConnections(vm);
+            networkAdapter = ethernetConnections[index];
+            networkAdapter.LateBoundObject["EnabledState"] = enableState; //3 disabled 2 Enabled
+            networkAdapter.LateBoundObject["HostResource"] = new string[] { vSwitch.Path.Path };
+
+            ModifyVmResources(vmMgmtSvc, vm, new String[] {
+                networkAdapter.LateBoundObject.GetText(TextFormat.CimDtd20)
+                });
+
+            EthernetSwitchPortVlanSettingData vlanSettings = GetVlanSettings(ethernetConnections[index]);
+
+            if (vlanSettings == null)
+            {
+                // when modifying  nic to not connected dont create vlan
+                if (enable)
+                {
+                    if (vlanid != null)
+                    {
+                        SetPortVlan(vlanid, networkAdapter);
+                    }
+                }
+            }
+            else
+            {
+                if (enable)
+                {
+                    if (vlanid != null)
+                    {
+                        //Assign vlan configuration to nic
+                        vlanSettings.LateBoundObject["AccessVlanId"] = vlanid;
+                        vlanSettings.LateBoundObject["OperationMode"] = 1;
+                        ModifyFeatureVmResources(vmMgmtSvc, vm, new String[] {
+                            vlanSettings.LateBoundObject.GetText(TextFormat.CimDtd20)});
+                    }
+                }
+                else
+                {
+                    var virtSysMgmtSvc = GetVirtualisationSystemManagementService();
+
+                    // This method will remove the vlan settings present on the Nic
+                    ManagementPath jobPath;
+                    var ret_val = virtSysMgmtSvc.RemoveFeatureSettings(new ManagementPath[] { vlanSettings.Path },
+                        out jobPath);
+
+                    // If the Job is done asynchronously
+                    if (ret_val == ReturnCode.Started)
+                    {
+                        JobCompleted(jobPath);
+                    }
+                    else if (ret_val != ReturnCode.Completed)
+                    {
+                        var errMsg = string.Format(
+                            "Failed to remove vlan resource {0} from VM {1} (GUID {2}) due to {3}",
+                            vlanSettings.Path,
+                            vm.ElementName,
+                            v

<TRUNCATED>

[2/4] Fixed windows line ending issues

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/920f39ba/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/IWmiCallsV2.cs
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/IWmiCallsV2.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/IWmiCallsV2.cs
index 896a287..0a64f4b 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/IWmiCallsV2.cs
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/IWmiCallsV2.cs
@@ -71,8 +71,8 @@ namespace HypervResource
         Dictionary<String, VmState> GetVmSync(String privateIpAddress);
         string GetVmNote(System.Management.ManagementPath sysPath);
         void ModifyVmVLan(string vmName, String vlanid, string mac);
-        void ModifyVmVLan(string vmName, String vlanid, uint pos, bool enable, string switchLabelName);
-        void DisableVmNics();
+        void ModifyVmVLan(string vmName, String vlanid, uint pos, bool enable, string switchLabelName);
+        void DisableVmNics();
         void DisableNicVlan(String mac, String vmName);
-    }
-}
+    }
+}


[4/4] git commit: updated refs/heads/4.4 to 920f39b

Posted by da...@apache.org.
Fixed windows line ending issues

(cherry picked from commit 648a724dfc49222873124089464ccda92278fa9f)

Conflicts:
	plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
	plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/920f39ba
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/920f39ba
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/920f39ba

Branch: refs/heads/4.4
Commit: 920f39baafded1d8431cf53fdcc137ed182edadf
Parents: 51c691f
Author: Rajesh Battala <ra...@citrix.com>
Authored: Wed May 7 15:13:06 2014 +0530
Committer: Daan Hoogland <da...@onecht.net>
Committed: Wed Jul 30 12:04:54 2014 +0200

----------------------------------------------------------------------
 .../HypervResource/HypervResourceController.cs  | 3796 ++++++++-------
 .../HypervResource/IWmiCallsV2.cs               |    8 +-
 .../ServerResource/HypervResource/WmiCallsV2.cs | 4562 +++++++++---------
 3 files changed, 4266 insertions(+), 4100 deletions(-)
----------------------------------------------------------------------



[3/4] Fixed windows line ending issues

Posted by da...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/920f39ba/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
index 40ac159..0ad95b8 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
@@ -189,607 +189,1877 @@ namespace HypervResource
             using (log4net.NDC.Push(Guid.NewGuid().ToString()))
             {
                 logger.Info(CloudStackTypes.SetupCommand + Utils.CleanString(cmd.ToString()));
-
-                string details = null;
-                bool result = false;
-
-                try
-                {
-                    result = true;
-                }
-                catch (Exception sysEx)
-                {
-                    details = CloudStackTypes.SetupCommand + " failed due to " + sysEx.Message;
-                    logger.Error(details, sysEx);
-                }
-
-                object ansContent = new
-                {
-                    result = result,
-                    details = "success - NOP",
-                    _reconnect = false,
-                    contextMap = contextMap
-                };
-
-                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.SetupAnswer);
-            }
-        }
-
-        // POST api/HypervResource/AttachCommand
-        [HttpPost]
-        [ActionName(CloudStackTypes.AttachCommand)]
-        public JContainer AttachCommand([FromBody]dynamic cmd)
-        {
-            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
-            {
-                logger.Info(CloudStackTypes.AttachCommand + Utils.CleanString(cmd.ToString()));
-
-                string details = null;
-                bool result = false;
-
-                try
-                {
-                    string vmName = (string)cmd.vmName;
-                    DiskTO disk = DiskTO.ParseJson(cmd.disk);
-
-                    if (disk.type.Equals("ISO"))
-                    {
-                        TemplateObjectTO dataStore = disk.templateObjectTO;
-                        NFSTO share = dataStore.nfsDataStoreTO;
-                        Utils.ConnectToRemote(share.UncPath, share.Domain, share.User, share.Password);
-                        string diskPath = Utils.NormalizePath(Path.Combine(share.UncPath, dataStore.path));
-                        wmiCallsV2.AttachIso(vmName, diskPath);
-                        result = true;
-                    }
-                    else if (disk.type.Equals("DATADISK"))
-                    {
-                        VolumeObjectTO volume = disk.volumeObjectTO;
-                        PrimaryDataStoreTO primary = volume.primaryDataStore;
-                        if (!primary.isLocal)
-                        {
-                            Utils.ConnectToRemote(primary.UncPath, primary.Domain, primary.User, primary.Password);
-                        }
-                        string diskPath = Utils.NormalizePath(volume.FullFileName);
-                        wmiCallsV2.AttachDisk(vmName, diskPath, disk.diskSequence);
-                        result = true;
-                    }
-                    else
-                    {
-                        details = "Invalid disk type to be attached to vm " + vmName;
-                    }
-                }
-                catch (Exception sysEx)
-                {
-                    details = CloudStackTypes.AttachCommand + " failed due to " + sysEx.Message;
-                    logger.Error(details, sysEx);
-                }
-
-                object ansContent = new
-                {
-                    result = result,
-                    details = details,
-                    disk = cmd.disk,
-                    contextMap = contextMap
-                };
-
-                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.AttachAnswer);
-            }
-        }
-
-        // POST api/HypervResource/DetachCommand
-        [HttpPost]
-        [ActionName(CloudStackTypes.DettachCommand)]
-        public JContainer DetachCommand([FromBody]dynamic cmd)
-        {
-            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
-            {
-                logger.Info(CloudStackTypes.DettachCommand + Utils.CleanString(cmd.ToString()));
-
-                string details = null;
-                bool result = false;
-
-                try
-                {
-                    string vmName = (string)cmd.vmName;
-                    DiskTO disk = DiskTO.ParseJson(cmd.disk);
-
-                    if (disk.type.Equals("ISO"))
-                    {
-                        TemplateObjectTO dataStore = disk.templateObjectTO;
-                        NFSTO share = dataStore.nfsDataStoreTO;
-                        string diskPath = Utils.NormalizePath(Path.Combine(share.UncPath, dataStore.path));
-                        wmiCallsV2.DetachDisk(vmName, diskPath);
-                        result = true;
-                    }
-                    else if (disk.type.Equals("DATADISK"))
-                    {
-                        VolumeObjectTO volume = disk.volumeObjectTO;
-                        string diskPath = Utils.NormalizePath(volume.FullFileName);
-                        wmiCallsV2.DetachDisk(vmName, diskPath);
-                        result = true;
-                    }
-                    else
-                    {
-                        details = "Invalid disk type to be dettached from vm " + vmName;
-                    }
-                }
-                catch (Exception sysEx)
-                {
-                    details = CloudStackTypes.DettachCommand + " failed due to " + sysEx.Message;
-                    logger.Error(details, sysEx);
-                }
-
-                object ansContent = new
-                {
-                    result = result,
-                    details = details,
-                    contextMap = contextMap
-                };
-
-                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.DettachAnswer);
-            }
-        }
-
-        // POST api/HypervResource/RebootCommand
-        [HttpPost]
-        [ActionName(CloudStackTypes.RebootCommand)]
-        public JContainer RebootCommand([FromBody]dynamic cmd)
-        {
-            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
-            {
+
+                string details = null;
+                bool result = false;
+
+                try
+                {
+                    result = true;
+                }
+                catch (Exception sysEx)
+                {
+                    details = CloudStackTypes.SetupCommand + " failed due to " + sysEx.Message;
+                    logger.Error(details, sysEx);
+                }
+
+                object ansContent = new
+                {
+                    result = result,
+                    details = "success - NOP",
+                    _reconnect = false,
+                    contextMap = contextMap
+                };
+
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.SetupAnswer);
+            }
+        }
+
+        // POST api/HypervResource/AttachCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.AttachCommand)]
+        public JContainer AttachCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.AttachCommand + Utils.CleanString(cmd.ToString()));
+
+                string details = null;
+                bool result = false;
+
+                try
+                {
+                    string vmName = (string)cmd.vmName;
+                    DiskTO disk = DiskTO.ParseJson(cmd.disk);
+
+                    if (disk.type.Equals("ISO"))
+                    {
+                        TemplateObjectTO dataStore = disk.templateObjectTO;
+                        NFSTO share = dataStore.nfsDataStoreTO;
+                        Utils.ConnectToRemote(share.UncPath, share.Domain, share.User, share.Password);
+                        string diskPath = Utils.NormalizePath(Path.Combine(share.UncPath, dataStore.path));
+                        wmiCallsV2.AttachIso(vmName, diskPath);
+                        result = true;
+                    }
+                    else if (disk.type.Equals("DATADISK"))
+                    {
+                        VolumeObjectTO volume = disk.volumeObjectTO;
+                        PrimaryDataStoreTO primary = volume.primaryDataStore;
+                        if (!primary.isLocal)
+                        {
+                            Utils.ConnectToRemote(primary.UncPath, primary.Domain, primary.User, primary.Password);
+                        }
+                        string diskPath = Utils.NormalizePath(volume.FullFileName);
+                        wmiCallsV2.AttachDisk(vmName, diskPath, disk.diskSequence);
+                        result = true;
+                    }
+                    else
+                    {
+                        details = "Invalid disk type to be attached to vm " + vmName;
+                    }
+                }
+                catch (Exception sysEx)
+                {
+                    details = CloudStackTypes.AttachCommand + " failed due to " + sysEx.Message;
+                    logger.Error(details, sysEx);
+                }
+
+                object ansContent = new
+                {
+                    result = result,
+                    details = details,
+                    disk = cmd.disk,
+                    contextMap = contextMap
+                };
+
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.AttachAnswer);
+            }
+        }
+
+        // POST api/HypervResource/DetachCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.DettachCommand)]
+        public JContainer DetachCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.DettachCommand + Utils.CleanString(cmd.ToString()));
+
+                string details = null;
+                bool result = false;
+
+                try
+                {
+                    string vmName = (string)cmd.vmName;
+                    DiskTO disk = DiskTO.ParseJson(cmd.disk);
+
+                    if (disk.type.Equals("ISO"))
+                    {
+                        TemplateObjectTO dataStore = disk.templateObjectTO;
+                        NFSTO share = dataStore.nfsDataStoreTO;
+                        string diskPath = Utils.NormalizePath(Path.Combine(share.UncPath, dataStore.path));
+                        wmiCallsV2.DetachDisk(vmName, diskPath);
+                        result = true;
+                    }
+                    else if (disk.type.Equals("DATADISK"))
+                    {
+                        VolumeObjectTO volume = disk.volumeObjectTO;
+                        string diskPath = Utils.NormalizePath(volume.FullFileName);
+                        wmiCallsV2.DetachDisk(vmName, diskPath);
+                        result = true;
+                    }
+                    else
+                    {
+                        details = "Invalid disk type to be dettached from vm " + vmName;
+                    }
+                }
+                catch (Exception sysEx)
+                {
+                    details = CloudStackTypes.DettachCommand + " failed due to " + sysEx.Message;
+                    logger.Error(details, sysEx);
+                }
+
+                object ansContent = new
+                {
+                    result = result,
+                    details = details,
+                    contextMap = contextMap
+                };
+
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.DettachAnswer);
+            }
+        }
+
+        // POST api/HypervResource/RebootCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.RebootCommand)]
+        public JContainer RebootCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
                 logger.Info(CloudStackTypes.RebootCommand + Utils.CleanString(cmd.ToString()));
 
-                string details = null;
-                bool result = false;
+                string details = null;
+                bool result = false;
+
+                try
+                {
+                    string vmName = (string)cmd.vmName;
+                    var sys = wmiCallsV2.GetComputerSystem(vmName);
+                    if (sys == null)
+                    {
+                        details = CloudStackTypes.RebootCommand + " requested unknown VM " + vmName;
+                        logger.Error(details);
+                    }
+                    else
+                    {
+                        wmiCallsV2.SetState(sys, RequiredState.Reset);
+                        result = true;
+                    }
+                }
+                catch (Exception sysEx)
+                {
+                    details = CloudStackTypes.RebootCommand + " failed due to " + sysEx.Message;
+                    logger.Error(details, sysEx);
+                }
+
+                object ansContent = new
+                {
+                    result = result,
+                    details = details,
+                    contextMap = contextMap
+                };
+
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.RebootAnswer);
+            }
+        }
+
+        // POST api/HypervResource/DestroyCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.DestroyCommand)]
+        public JContainer DestroyCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.DestroyCommand + Utils.CleanString(cmd.ToString()));
+
+                string details = null;
+                bool result = false;
+
+                try
+                {
+                    // Assert
+                    String errMsg = "No 'volume' details in " + CloudStackTypes.DestroyCommand + " " + Utils.CleanString(cmd.ToString());
+                    if (cmd.volume == null)
+                    {
+                        logger.Error(errMsg);
+                        throw new ArgumentException(errMsg);
+                    }
+
+                    // Assert
+                    errMsg = "No valide path in DestroyCommand in " + CloudStackTypes.DestroyCommand + " " + (String)cmd.ToString();
+                    if (cmd.volume.path == null)
+                    {
+                        logger.Error(errMsg);
+                        throw new ArgumentException(errMsg);
+                    }
+
+                    String path = (string)cmd.volume.path;
+                    if (!File.Exists(path))
+                    {
+                        logger.Info(CloudStackTypes.DestroyCommand + ", but volume at pass already deleted " + path);
+                    }
+
+                    string vmName = (string)cmd.vmName;
+                    if (!string.IsNullOrEmpty(vmName) && File.Exists(path))
+                    {
+                        // Make sure that this resource is removed from the VM
+                        wmiCallsV2.DetachDisk(vmName, path);
+                    }
+
+                    File.Delete(path);
+                    result = true;
+                }
+                catch (Exception sysEx)
+                {
+                    details = CloudStackTypes.DestroyCommand + " failed due to " + sysEx.Message;
+                    logger.Error(details, sysEx);
+                }
+
+                object ansContent = new
+                    {
+                        result = result,
+                        details = details,
+                        contextMap = contextMap
+                    };
+
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.Answer);
+            }
+        }
+
+        // POST api/HypervResource/DeleteCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.DeleteCommand)]
+        public JContainer DeleteCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.DestroyCommand + Utils.CleanString(cmd.ToString()));
+
+                string details = null;
+                bool result = false;
+
+                try
+                {
+                    // Assert
+                    String errMsg = "No 'volume' details in " + CloudStackTypes.DestroyCommand + " " + Utils.CleanString(cmd.ToString());
+                    VolumeObjectTO destVolumeObjectTO = VolumeObjectTO.ParseJson(cmd.data);
+
+                    if (destVolumeObjectTO.name == null)
+                    {
+                        logger.Error(errMsg);
+                        throw new ArgumentException(errMsg);
+                    }
+
+                    String path = destVolumeObjectTO.FullFileName;
+                    if (!File.Exists(path))
+                    {
+                        logger.Info(CloudStackTypes.DestroyCommand + ", but volume at pass already deleted " + path);
+                    }
+
+                    string vmName = (string)cmd.vmName;
+                    if (!string.IsNullOrEmpty(vmName) && File.Exists(path))
+                    {
+                        // Make sure that this resource is removed from the VM
+                        wmiCallsV2.DetachDisk(vmName, path);
+                    }
+
+                    File.Delete(path);
+                    result = true;
+                }
+                catch (Exception sysEx)
+                {
+                    details = CloudStackTypes.DestroyCommand + " failed due to " + sysEx.Message;
+                    logger.Error(details, sysEx);
+                }
+
+                object ansContent = new
+                {
+                    result = result,
+                    details = details,
+                    contextMap = contextMap
+                };
+
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.Answer);
+            }
+        }
+
+        
+        private static JArray ReturnCloudStackTypedJArray(object ansContent, string ansType)
+        {
+            JObject ansObj = Utils.CreateCloudStackObject(ansType, ansContent);
+            JArray answer = new JArray(ansObj);
+            logger.Info(Utils.CleanString(ansObj.ToString()));
+            return answer;
+        }
+
+        // POST api/HypervResource/CreateCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.CreateCommand)]
+        public JContainer CreateCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.CreateCommand + Utils.CleanString(cmd.ToString()));
+
+                string details = null;
+                bool result = false;
+                VolumeInfo volume = new VolumeInfo();
+
+                try
+                {
+                    string diskType = cmd.diskCharacteristics.type;
+                    ulong disksize = cmd.diskCharacteristics.size;
+                    string templateUri = cmd.templateUrl;
+
+                    // assert: valid storagepool?
+                    string poolTypeStr = cmd.pool.type;
+                    string poolLocalPath = cmd.pool.path;
+                    string poolUuid = cmd.pool.uuid;
+                    string newVolPath = null;
+                    long volId = cmd.volId;
+                    string newVolName = null;
+
+                    if (ValidStoragePool(poolTypeStr, poolLocalPath, poolUuid, ref details))
+                    {
+                        // No template URI?  Its a blank disk.
+                        if (string.IsNullOrEmpty(templateUri))
+                        {
+                            // assert
+                            VolumeType volType;
+                            if (!Enum.TryParse<VolumeType>(diskType, out volType) && volType != VolumeType.DATADISK)
+                            {
+                                details = "Cannot create volumes of type " + (string.IsNullOrEmpty(diskType) ? "NULL" : diskType);
+                            }
+                            else
+                            {
+                                newVolName = cmd.diskCharacteristics.name;
+                                newVolPath = Path.Combine(poolLocalPath, newVolName, diskType.ToLower());
+                                // TODO: make volume format and block size configurable
+                                wmiCallsV2.CreateDynamicVirtualHardDisk(disksize, newVolPath);
+                                if (File.Exists(newVolPath))
+                                {
+                                    result = true;
+                                }
+                                else
+                                {
+                                    details = "Failed to create DATADISK with name " + newVolName;
+                                }
+                            }
+                        }
+                        else
+                        {
+                            // TODO:  Does this always work, or do I need to download template at times?
+                            if (templateUri.Contains("/") || templateUri.Contains("\\"))
+                            {
+                                details = "Problem with templateURL " + templateUri +
+                                                " the URL should be volume UUID in primary storage created by previous PrimaryStorageDownloadCommand";
+                                logger.Error(details);
+                            }
+                            else
+                            {
+                                logger.Debug("Template's name in primary store should be " + templateUri);
+                                //            HypervPhysicalDisk BaseVol = primaryPool.getPhysicalDisk(tmplturl);
+                                FileInfo srcFileInfo = new FileInfo(templateUri);
+                                newVolName = Guid.NewGuid() + srcFileInfo.Extension;
+                                newVolPath = Path.Combine(poolLocalPath, newVolName);
+                                logger.Debug("New volume will be at " + newVolPath);
+                                string oldVolPath = Path.Combine(poolLocalPath, templateUri);
+                                File.Copy(oldVolPath, newVolPath);
+                                if (File.Exists(newVolPath))
+                                {
+                                    result = true;
+                                }
+                                else
+                                {
+                                    details = "Failed to create DATADISK with name " + newVolName;
+                                }
+                            }
+                            volume = new VolumeInfo(
+                                      volId, diskType,
+                                    poolTypeStr, poolUuid, newVolName,
+                                    newVolPath, newVolPath, (long)disksize, null);
+                        }
+                    }
+                }
+                catch (Exception sysEx)
+                {
+                    // TODO: consider this as model for error processing in all commands
+                    details = CloudStackTypes.CreateCommand + " failed due to " + sysEx.Message;
+                    logger.Error(details, sysEx);
+                }
+
+                object ansContent = new
+                {
+                    result = result,
+                    details = details,
+                    volume = volume,
+                    contextMap = contextMap
+                };
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.CreateAnswer);
+            }
+        }
+
+        // POST api/HypervResource/PrimaryStorageDownloadCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.PrimaryStorageDownloadCommand)]
+        public JContainer PrimaryStorageDownloadCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.PrimaryStorageDownloadCommand + Utils.CleanString(cmd.ToString()));
+                string details = null;
+                bool result = false;
+                long size = 0;
+                string newCopyFileName = null;
+
+                string poolLocalPath = cmd.localPath;
+                if (!Directory.Exists(poolLocalPath))
+                {
+                    details = "None existent local path " + poolLocalPath;
+                }
+                else
+                {
+                    // Compose name for downloaded file.
+                    string sourceUrl = cmd.url;
+                    if (sourceUrl.ToLower().EndsWith(".vhd"))
+                    {
+                        newCopyFileName = Guid.NewGuid() + ".vhd";
+                    }
+                    if (sourceUrl.ToLower().EndsWith(".vhdx"))
+                    {
+                        newCopyFileName = Guid.NewGuid() + ".vhdx";
+                    }
+
+                    // assert
+                    if (newCopyFileName == null)
+                    {
+                        details = CloudStackTypes.PrimaryStorageDownloadCommand + " Invalid file extension for hypervisor type in source URL " + sourceUrl;
+                        logger.Error(details);
+                    }
+                    else
+                    {
+                        try
+                        {
+                            FileInfo newFile;
+                            if (CopyURI(sourceUrl, newCopyFileName, poolLocalPath, out newFile, ref details))
+                            {
+                                size = newFile.Length;
+                                result = true;
+                            }
+                        }
+                        catch (System.Exception ex)
+                        {
+                            details = CloudStackTypes.PrimaryStorageDownloadCommand + " Cannot download source URL " + sourceUrl + " due to " + ex.Message;
+                            logger.Error(details, ex);
+                        }
+                    }
+                }
+
+                object ansContent = new
+                {
+                    result = result,
+                    details = details,
+                    templateSize = size,
+                    installPath = newCopyFileName,
+                    contextMap = contextMap
+                };
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.PrimaryStorageDownloadAnswer);
+            }
+        }
+
+        private static bool ValidStoragePool(string poolTypeStr, string poolLocalPath, string poolUuid, ref string details)
+        {
+            StoragePoolType poolType;
+            if (!Enum.TryParse<StoragePoolType>(poolTypeStr, out poolType) || poolType != StoragePoolType.Filesystem)
+            {
+                details = "Primary storage pool " + poolUuid + " type " + poolType + " local path " + poolLocalPath + " has invalid StoragePoolType";
+                logger.Error(details);
+                return false;
+            }
+            else if (!Directory.Exists(poolLocalPath))
+            {
+                details = "Primary storage pool " + poolUuid + " type " + poolType + " local path " + poolLocalPath + " has invalid local path";
+                logger.Error(details);
+                return false;
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// Exceptions to watch out for:
+        /// Exceptions related to URI creation
+        /// System.SystemException
+        /// +-System.ArgumentNullException
+        /// +-System.FormatException
+        ///   +-System.UriFormatException
+        ///
+        /// Exceptions related to NFS URIs
+        /// System.SystemException
+        /// +-System.NotSupportedException
+        /// +-System.ArgumentException
+        /// +-System.ArgumentNullException
+        ///   +-System.Security.SecurityException;
+        /// +-System.UnauthorizedAccessException
+        /// +-System.IO.IOException
+        ///   +-System.IO.PathTooLongException
+        ///   
+        /// Exceptions related to HTTP URIs
+        /// System.SystemException
+        /// +-System.InvalidOperationException
+        ///    +-System.Net.WebException
+        /// +-System.NotSupportedException
+        /// +-System.ArgumentNullException
+        /// </summary>
+        /// <param name="sourceUri"></param>
+        /// <param name="newCopyFileName"></param>
+        /// <param name="poolLocalPath"></param>
+        /// <returns></returns>
+        private bool CopyURI(string sourceUri, string newCopyFileName, string poolLocalPath, out FileInfo newFile, ref string details)
+        {
+            Uri source = new Uri(sourceUri);
+            String destFilePath = Path.Combine(poolLocalPath, newCopyFileName);
+            string[] pathSegments = source.Segments;
+            String templateUUIDandExtension = pathSegments[pathSegments.Length - 1];
+            newFile = new FileInfo(destFilePath);
+
+            // NFS URI assumed to already be mounted locally.  Mount location given by settings.
+            if (source.Scheme.ToLower().Equals("nfs"))
+            {
+                String srcDiskPath = Path.Combine(HypervResourceController.config.LocalSecondaryStoragePath, templateUUIDandExtension);
+                String taskMsg = "Copy NFS url in " + sourceUri + " at " + srcDiskPath + " to pool " + poolLocalPath;
+                logger.Debug(taskMsg);
+                File.Copy(srcDiskPath, destFilePath);
+            }
+            else if (source.Scheme.ToLower().Equals("http") || source.Scheme.ToLower().Equals("https"))
+            {
+                System.Net.WebClient webclient = new WebClient();
+                webclient.DownloadFile(source, destFilePath);
+            }
+            else
+            {
+                details = "Unsupported URI scheme " + source.Scheme.ToLower() + " in source URI " + sourceUri;
+                logger.Error(details);
+                return false;
+            }
+
+            if (!File.Exists(destFilePath))
+            {
+                details = "Filed to copy " + sourceUri + " to primary pool destination " + destFilePath;
+                logger.Error(details);
+                return false;
+            }
+            return true;
+        }
+
+        // POST api/HypervResource/CheckHealthCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.CheckHealthCommand)]
+        public JContainer CheckHealthCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.CheckHealthCommand + Utils.CleanString(cmd.ToString()));
+                object ansContent = new
+                {
+                    result = true,
+                    details = "resource is alive",
+                    contextMap = contextMap
+                };
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.CheckHealthAnswer);
+            }
+        }
+
+        // POST api/HypervResource/CheckOnHostCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.CheckOnHostCommand)]
+        public JContainer CheckOnHostCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.CheckOnHostCommand + Utils.CleanString(cmd.ToString()));
+                string details = "host is not alive";
+                bool result = true;
+                try
+                {
+                    foreach (string poolPath in config.getAllPrimaryStorages())
+                    {
+                        if (IsHostAlive(poolPath, (string)cmd.host.privateNetwork.ip))
+                        {
+                            result = false;
+                            details = "host is alive";
+                            break;
+                        }
+                    }
+                }
+                catch (Exception e)
+                {
+                    logger.Error("Error Occurred in " + CloudStackTypes.CheckOnHostCommand + " : " + e.Message);
+                }
+
+                object ansContent = new
+                {
+                    result = result,
+                    details = details,
+                    contextMap = contextMap
+                };
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.CheckOnHostAnswer);
+            }
+        }
+
+        private bool IsHostAlive(string poolPath, string privateIp)
+        {
+            bool hostAlive = false;
+            try
+            {
+                string hbFile = Path.Combine(poolPath, "hb-" + privateIp);
+                FileInfo file = new FileInfo(hbFile);
+                using (StreamReader sr = file.OpenText())
+                {
+                    string epoch = sr.ReadLine();
+                    string[] dateTime = epoch.Split('@');
+                    string[] date = dateTime[0].Split('-');
+                    string[] time = dateTime[1].Split(':');
+                    DateTime epochTime = new DateTime(Convert.ToInt32(date[0]), Convert.ToInt32(date[1]), Convert.ToInt32(date[2]), Convert.ToInt32(time[0]),
+                        Convert.ToInt32(time[1]), Convert.ToInt32(time[2]), DateTimeKind.Utc);
+                    DateTime currentTime = DateTime.UtcNow;
+                    DateTime ThreeMinuteLaterEpoch = epochTime.AddMinutes(3);
+                    if (currentTime.CompareTo(ThreeMinuteLaterEpoch) < 0)
+                    {
+                        hostAlive = true;
+                    }
+                    sr.Close();
+                }
+            }
+            catch (Exception e)
+            {
+                logger.Info("Exception occurred in verifying host " + e.Message);
+            }
+
+            return hostAlive;
+        }
+
+        // POST api/HypervResource/CheckSshCommand
+        // TODO: create test
+        [HttpPost]
+        [ActionName(CloudStackTypes.CheckSshCommand)]
+        public JContainer CheckSshCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.CheckSshCommand + Utils.CleanString(cmd.ToString()));
+                object ansContent = new
+                {
+                    result = true,
+                    details = "NOP, TODO: implement properly",
+                    contextMap = contextMap
+                };
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.CheckSshAnswer);
+            }
+        }
+
+        // POST api/HypervResource/CheckVirtualMachineCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.CheckVirtualMachineCommand)]
+        public JContainer CheckVirtualMachineCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.CheckVirtualMachineCommand + Utils.CleanString(cmd.ToString()));
+                string details = null;
+                bool result = false;
+                string vmName = cmd.vmName;
+                string state = null;
+
+                // TODO: Look up the VM, convert Hyper-V state to CloudStack version.
+                var sys = wmiCallsV2.GetComputerSystem(vmName);
+                if (sys == null)
+                {
+                    details = CloudStackTypes.CheckVirtualMachineCommand + " requested unknown VM " + vmName;
+                    logger.Error(details);
+                }
+                else
+                {
+                    state = EnabledState.ToCloudStackState(sys.EnabledState); // TODO: V2 changes?
+                    result = true;
+                }
+
+                object ansContent = new
+                {
+                    result = result,
+                    details = details,
+                    state = state,
+                    contextMap = contextMap
+                };
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.CheckVirtualMachineAnswer);
+            }
+        }
+
+        // POST api/HypervResource/DeleteStoragePoolCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.DeleteStoragePoolCommand)]
+        public JContainer DeleteStoragePoolCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.DeleteStoragePoolCommand + Utils.CleanString(cmd.ToString()));
+                object ansContent = new
+                {
+                    result = true,
+                    details = "Current implementation does not delete local path corresponding to storage pool!",
+                    contextMap = contextMap
+                };
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.Answer);
+            }
+        }
+
+        /// <summary>
+        /// NOP - legacy command -
+        /// POST api/HypervResource/CreateStoragePoolCommand
+        /// </summary>
+        /// <param name="cmd"></param>
+        /// <returns></returns>
+        [HttpPost]
+        [ActionName(CloudStackTypes.CreateStoragePoolCommand)]
+        public JContainer CreateStoragePoolCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.CreateStoragePoolCommand + Utils.CleanString(cmd.ToString()));
+                object ansContent = new
+                {
+                    result = true,
+                    details = "success - NOP",
+                    contextMap = contextMap
+                };
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.Answer);
+            }
+        }
+
+        // POST api/HypervResource/ModifyStoragePoolCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.ModifyStoragePoolCommand)]
+        public JContainer ModifyStoragePoolCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.ModifyStoragePoolCommand + Utils.CleanString(cmd.ToString()));
+                string details = null;
+                string localPath;
+                StoragePoolType poolType;
+                object ansContent;
+
+                bool result = ValidateStoragePoolCommand(cmd, out localPath, out poolType, ref details);
+                if (!result)
+                {
+                    ansContent = new
+                    {
+                        result = result,
+                        details = details,
+                        contextMap = contextMap
+                    };
+                    return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.Answer);
+                }
+
+                var tInfo = new Dictionary<string, string>();
+                long capacityBytes = 0;
+                long availableBytes = 0;
+                string hostPath = null;
+                if (poolType == StoragePoolType.Filesystem)
+                {
+                    GetCapacityForLocalPath(localPath, out capacityBytes, out availableBytes);
+                    hostPath = localPath;
+                }
+                else if (poolType == StoragePoolType.NetworkFilesystem ||
+                    poolType == StoragePoolType.SMB)
+                {
+                    NFSTO share = new NFSTO();
+                    String uriStr = "cifs://" + (string)cmd.pool.host + (string)cmd.pool.path;
+                    share.uri = new Uri(uriStr);
+                    hostPath = Utils.NormalizePath(share.UncPath);
+
+                    // Check access to share.
+                    Utils.ConnectToRemote(share.UncPath, share.Domain, share.User, share.Password);
+                    Utils.GetShareDetails(share.UncPath, out capacityBytes, out availableBytes);
+                    config.setPrimaryStorage((string)cmd.pool.uuid, hostPath);
+                }
+                else
+                {
+                    result = false;
+                }
+
+                String uuid = null;
+                var poolInfo = new
+                {
+                    uuid = uuid,
+                    host = cmd.pool.host,
+                    hostPath = cmd.pool.path,
+                    localPath = hostPath,
+                    poolType = cmd.pool.type,
+                    capacityBytes = capacityBytes,
+                    availableBytes = availableBytes
+                };
+
+                ansContent = new
+                {
+                    result = result,
+                    details = details,
+                    localPath = hostPath,
+                    templateInfo = tInfo,
+                    poolInfo = poolInfo,
+                    contextMap = contextMap
+                };
+
+                if (result)
+                {
+                    try
+                    {
+                        if ((bool)cmd.add)
+                        {
+                            logger.Info("Adding HeartBeat Task to task scheduler for pool " + (string)cmd.pool.uuid);
+                            Utils.AddHeartBeatTask((string)cmd.pool.uuid, hostPath, config.PrivateIpAddress);
+                        }
+                        else
+                        {
+                            logger.Info("Deleting HeartBeat Task from task scheduler for pool " + (string)cmd.pool.uuid);
+                            Utils.RemoveHeartBeatTask(cmd.pool.uuid);
+                        }
+                    }
+                    catch (Exception e)
+                    {
+                        logger.Error("Error occurred in adding/delete HeartBeat Task to/from Task Scheduler : " + e.Message);
+                    }
+                }
+
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.ModifyStoragePoolAnswer);
+            }
+        }
+
+        private bool ValidateStoragePoolCommand(dynamic cmd, out string localPath, out StoragePoolType poolType, ref string details)
+        {
+            dynamic pool = cmd.pool;
+            string poolTypeStr = pool.type;
+            localPath = cmd.localPath;
+            if (!Enum.TryParse<StoragePoolType>(poolTypeStr, out poolType))
+            {
+                details = "Request to create / modify unsupported pool type: " + (poolTypeStr == null ? "NULL" : poolTypeStr) + "in cmd " + JsonConvert.SerializeObject(cmd);
+                logger.Error(details);
+                return false;
+            }
+
+            if (poolType != StoragePoolType.Filesystem &&
+                poolType != StoragePoolType.NetworkFilesystem &&
+                poolType != StoragePoolType.SMB)
+            {
+                details = "Request to create / modify unsupported pool type: " + (poolTypeStr == null ? "NULL" : poolTypeStr) + "in cmd " + JsonConvert.SerializeObject(cmd);
+                logger.Error(details);
+                return false;
+            }
+
+            return true;
+        }
+
+        // POST api/HypervResource/PlugNicCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.PlugNicCommand)]
+        public JContainer PlugNicCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.PlugNicCommand + Utils.CleanString(cmd.ToString()));
+                object ansContent = new
+                {
+                    result = true,
+                    details = "Hot Nic plug not supported, change any empty virtual network adapter network settings",
+                    contextMap = contextMap
+                };
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.PlugNicAnswer);
+            }
+        }
+
+
+        // POST api/HypervResource/CleanupNetworkRulesCmd
+        [HttpPost]
+        [ActionName(CloudStackTypes.CleanupNetworkRulesCmd)]
+        public JContainer CleanupNetworkRulesCmd([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.CleanupNetworkRulesCmd + Utils.CleanString(cmd.ToString()));
+                object ansContent = new
+                 {
+                     result = false,
+                     details = "nothing to cleanup in our current implementation",
+                     contextMap = contextMap
+                 };
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.Answer);
+            }
+        }
+
+        // POST api/HypervResource/CheckNetworkCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.CheckNetworkCommand)]
+        public JContainer CheckNetworkCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.CheckNetworkCommand + Utils.CleanString(cmd.ToString()));
+                object ansContent = new
+                {
+                    result = true,
+                    details = (string)null,
+                    contextMap = contextMap
+                };
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.CheckNetworkAnswer);
+            }
+        }
+
+        // POST api/HypervResource/ReadyCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.ReadyCommand)]
+        public JContainer ReadyCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.ReadyCommand + Utils.CleanString(cmd.ToString()));
+                object ansContent = new
+                {
+                    result = true,
+                    details = (string)null,
+                    contextMap = contextMap
+                };
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.ReadyAnswer);
+            }
+
+        }
+
+        // POST api/HypervResource/StartCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.StartCommand)]
+        public JContainer StartCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.StartCommand + Utils.CleanString(cmd.ToString()));
+                string details = null;
+                bool result = false;
+
+                try
+                {
+                    string systemVmIsoPath = systemVmIso;
+                    lock (systemVmIso)
+                    {
+                        systemVmIsoPath = systemVmIso;
+                        String uriStr = (String)cmd.secondaryStorage;
+                        if (!String.IsNullOrEmpty(uriStr))
+                        {
+                            if (String.IsNullOrEmpty(systemVmIsoPath) || !File.Exists(systemVmIsoPath))
+                            {
+                                NFSTO share = new NFSTO();
+                                share.uri = new Uri(uriStr);
+                                string defaultDataPath = wmiCallsV2.GetDefaultDataRoot();
+
+                                string secondaryPath = Utils.NormalizePath(Path.Combine(share.UncPath, "systemvm"));
+                                string[] choices = Directory.GetFiles(secondaryPath, "systemvm*.iso");
+                                if (choices.Length != 1)
+                                {
+                                    String errMsg = "Couldn't locate the systemvm iso on " + secondaryPath;
+                                    logger.Debug(errMsg);
+                                }
+                                else
+                                {
+                                    systemVmIsoPath = Utils.NormalizePath(Path.Combine(defaultDataPath, Path.GetFileName(choices[0])));
+                                    if (!File.Exists(systemVmIsoPath))
+                                    {
+                                        Utils.DownloadCifsFileToLocalFile(choices[0], share, systemVmIsoPath);
+                                    }
+                                    systemVmIso = systemVmIsoPath;
+                                }
+                            }
+                        }
+                    }
+
+                    wmiCallsV2.DeployVirtualMachine(cmd, systemVmIsoPath);
+                    result = true;
+                }
+                catch (Exception wmiEx)
+                {
+                    details = CloudStackTypes.StartCommand + " fail on exception" + wmiEx.Message;
+                    logger.Error(details, wmiEx);
+                }
+
+                object ansContent = new
+                {
+                    result = result,
+                    details = details,
+                    vm = cmd.vm,
+                    contextMap = contextMap
+                };
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.StartAnswer);
+            }
+        }
+
+        // POST api/HypervResource/StopCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.StopCommand)]
+        public JContainer StopCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.StopCommand + Utils.CleanString(cmd.ToString()));
+                string details = null;
+                bool result = false;
+                bool checkBeforeCleanup = cmd.checkBeforeCleanup;
+                String vmName = cmd.vmName;
+
+                if (checkBeforeCleanup == true)
+                {
+                    ComputerSystem vm = wmiCallsV2.GetComputerSystem(vmName);
+                    if (vm == null || vm.EnabledState == 2)
+                    {
+                        // VM is not available or vm in running state
+                        return ReturnCloudStackTypedJArray(new { result = false, details = "VM is running on host, bailing out", vm = vmName, contextMap = contextMap }, CloudStackTypes.StopAnswer);
+                    }
+                }
+                try
+                {
+                    wmiCallsV2.DestroyVm(cmd);
+                    result = true;
+                }
+                catch (Exception wmiEx)
+                {
+                    details = CloudStackTypes.StopCommand + " fail on exception" + wmiEx.Message;
+                    logger.Error(details, wmiEx);
+                }
+
+                object ansContent = new
+                {
+                    result = result,
+                    details = details,
+                    vm = cmd.vm,
+                    contextMap = contextMap
+                };
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.StopAnswer);
+            }
+        }
+
+        // POST api/HypervResource/CreateObjectCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.CreateObjectCommand)]
+        public JContainer CreateObjectCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.CreateObjectCommand + Utils.CleanString(cmd.ToString()));
+
+                bool result = false;
+                string details = null;
+                object newData = null;
+                try
+                {
+                    VolumeObjectTO volume = VolumeObjectTO.ParseJson(cmd.data);
+                    PrimaryDataStoreTO primary = volume.primaryDataStore;
+                    ulong volumeSize = volume.size;
+                    string volumeName = volume.uuid + ".vhdx";
+                    string volumePath = null;
+
+                    if (primary.isLocal)
+                    {
+                        volumePath = Path.Combine(primary.Path, volumeName);
+                    }
+                    else
+                    {
+                        volumePath = @"\\" + primary.uri.Host + primary.uri.LocalPath + @"\" + volumeName;
+                        volumePath = Utils.NormalizePath(volumePath);
+                        Utils.ConnectToRemote(primary.UncPath, primary.Domain, primary.User, primary.Password);
+                    }
+                    volume.path = volume.uuid;
+                    wmiCallsV2.CreateDynamicVirtualHardDisk(volumeSize, volumePath);
+                    if (File.Exists(volumePath))
+                    {
+                        result = true;
+                        JObject ansObj = Utils.CreateCloudStackObject(CloudStackTypes.VolumeObjectTO, volume);
+                        newData = ansObj;
+                    }
+                    else
+                    {
+                        details = "Failed to create disk with name " + volumePath;
+                    }
+                }
+                catch (Exception ex)
+                {
+                    // Test by providing wrong key
+                    details = CloudStackTypes.CreateObjectCommand + " failed on exception, " + ex.Message;
+                    logger.Error(details, ex);
+                }
+
+                object ansContent = new
+                {
+                    result = result,
+                    details = details,
+                    data = newData,
+                    contextMap = contextMap
+                };
+
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.CreateObjectAnswer);
+            }
+        }
+
+        // POST api/HypervResource/MaintainCommand
+        // TODO: should this be a NOP?
+        [HttpPost]
+        [ActionName(CloudStackTypes.MaintainCommand)]
+        public JContainer MaintainCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.MaintainCommand + Utils.CleanString(cmd.ToString()));
+
+                object ansContent = new
+                {
+                    result = true,
+                    willMigrate = true,
+                    details = "success - NOP for MaintainCommand",
+                    _reconnect = false,
+                    contextMap = contextMap
+                };
+
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.MaintainAnswer);
+            }
+        }
+
+        // POST api/HypervResource/PingRoutingCommand
+        // TODO: should this be a NOP?
+        [HttpPost]
+        [ActionName(CloudStackTypes.PingRoutingCommand)]
+        public JContainer PingRoutingCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.PingRoutingCommand + Utils.CleanString(cmd.ToString()));
+
+                object ansContent = new
+                {
+                    result = true,
+                    details = "success - NOP for PingRoutingCommand",
+                    _reconnect = false,
+                    contextMap = contextMap
+                };
+
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.Answer);
+            }
+        }
+
+        // POST api/HypervResource/PingCommand
+        // TODO: should this be a NOP?
+        [HttpPost]
+        [ActionName(CloudStackTypes.PingCommand)]
+        public JContainer PingCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.PingCommand + Utils.CleanString(cmd.ToString()));
+
+                object ansContent = new
+                {
+                    result = true,
+                    details = "success - NOP for PingCommand",
+                    _reconnect = false,
+                    contextMap = contextMap
+                };
+
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.Answer);
+            }
+        }
+
+        // POST api/HypervResource/ModifyVmVnicVlanCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.ModifyVmNicConfigCommand)]
+        public JContainer ModifyVmNicConfigCommand([FromBody]dynamic cmd)
+        {
+
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.ModifyVmNicConfigCommand + Utils.CleanString(cmd.ToString()));
+                bool result = false;
+                String vmName = cmd.vmName;
+                String vlan = cmd.vlan;
+                string macAddress = cmd.macAddress;
+                uint pos = cmd.index;
+                bool enable = cmd.enable;
+                string switchLableName = cmd.switchLableName;
+                if (macAddress != null)
+                {
+                    wmiCallsV2.ModifyVmVLan(vmName, vlan, macAddress);
+                    result = true;
+                }
+                else if (pos >= 1)
+                {
+                    wmiCallsV2.ModifyVmVLan(vmName, vlan, pos, enable, switchLableName);
+                    result = true;
+                }
+
+                object ansContent = new
+                {
+                    vmName = vmName,
+                    result = result,
+                    contextMap = contextMap
+                };
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.ModifyVmNicConfigAnswer);
+            }
+
+        }
+
+        // POST api/HypervResource/GetVmConfigCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.GetVmConfigCommand)]
+        public JContainer GetVmConfigCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.GetVmConfigCommand + Utils.CleanString(cmd.ToString()));
+                bool result = false;
+                String vmName = cmd.vmName;
+                ComputerSystem vm = wmiCallsV2.GetComputerSystem(vmName);
+                List<NicDetails> nicDetails = new List<NicDetails>();
+                var nicSettingsViaVm = wmiCallsV2.GetEthernetPortSettings(vm);
+                NicDetails nic = null;
+                int index = 0;
+                int[] nicStates = new int[8];
+                int[] nicVlan = new int[8];
+                int vlanid = 1;
+
+                var ethernetConnections = wmiCallsV2.GetEthernetConnections(vm);
+                foreach (EthernetPortAllocationSettingData item in ethernetConnections)
+                {
+                    EthernetSwitchPortVlanSettingData vlanSettings = wmiCallsV2.GetVlanSettings(item);
+                    if (vlanSettings == null)
+                    {
+                        vlanid = -1;
+                    }
+                    else
+                    {
+                        vlanid = vlanSettings.AccessVlanId;
+                    }
+                    nicStates[index] = (Int32)(item.EnabledState);
+                    nicVlan[index] = vlanid;
+                    index++;
+                }
+
+                index = 0;
+                foreach (SyntheticEthernetPortSettingData item in nicSettingsViaVm)
+                {
+                    nic = new NicDetails(item.Address, nicVlan[index], nicStates[index]);
+                    index++;
+                    nicDetails.Add(nic);
+                }
+
+
+                result = true;
+
+                object ansContent = new
+                {
+                    vmName = vmName,
+                    nics = nicDetails,
+                    result = result,
+                    contextMap = contextMap
+                };
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.GetVmConfigAnswer);
+            }
+        }
+
+
+
+        // POST api/HypervResource/GetVmStatsCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.GetVmStatsCommand)]
+        public JContainer GetVmStatsCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.GetVmStatsCommand + Utils.CleanString(cmd.ToString()));
+                bool result = false;
+                JArray vmNamesJson = cmd.vmNames;
+                string[] vmNames = vmNamesJson.ToObject<string[]>();
+                Dictionary<string, VmStatsEntry> vmProcessorInfo = new Dictionary<string, VmStatsEntry>(vmNames.Length);
+
+                var vmsToInspect = new List<System.Management.ManagementPath>();
+                foreach (var vmName in vmNames)
+                {
+                    var sys = wmiCallsV2.GetComputerSystem(vmName);
+                    if (sys == null)
+                    {
+                        logger.InfoFormat("GetVmStatsCommand requested unknown VM {0}", vmNames);
+                        continue;
+                    }
+                    var sysInfo = wmiCallsV2.GetVmSettings(sys);
+                    vmsToInspect.Add(sysInfo.Path);
+                }
+
+                wmiCallsV2.GetSummaryInfo(vmProcessorInfo, vmsToInspect);
+
+                // TODO: Network usage comes from Performance Counter API; however it is only available in kb/s, and not in total terms.
+                // Curious about these?  Use perfmon to inspect them, e.g. http://msdn.microsoft.com/en-us/library/xhcx5a20%28v=vs.100%29.aspx
+                // Recent post on these counter at http://blogs.technet.com/b/cedward/archive/2011/07/19/hyper-v-networking-optimizations-part-6-of-6-monitoring-hyper-v-network-consumption.aspx
+                result = true;
+
+                object ansContent = new
+                {
+                    vmStatsMap = vmProcessorInfo,
+                    result = result,
+                    contextMap = contextMap
+                };
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.GetVmStatsAnswer);
+            }
+        }
+
+        // POST api/HypervResource/CopyCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.CopyCommand)]
+        public JContainer CopyCommand(dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                // Log command *after* we've removed security details from the command.
+                logger.Info(CloudStackTypes.CopyCommand + Utils.CleanString(cmd.ToString()));
+
+                bool result = false;
+                string details = null;
+                object newData = null;
+                TemplateObjectTO destTemplateObjectTO = null;
+                VolumeObjectTO destVolumeObjectTO = null;
+                VolumeObjectTO srcVolumeObjectTO = null;
+                TemplateObjectTO srcTemplateObjectTO = null;
+
+                try
+                {
+                    srcTemplateObjectTO = TemplateObjectTO.ParseJson(cmd.srcTO);
+                    destTemplateObjectTO = TemplateObjectTO.ParseJson(cmd.destTO);
+                    srcVolumeObjectTO = VolumeObjectTO.ParseJson(cmd.srcTO);
+                    destVolumeObjectTO = VolumeObjectTO.ParseJson(cmd.destTO);
+
+                    string destFile = null;
+                    if (destTemplateObjectTO != null)
+                    {
+                        if (destTemplateObjectTO.primaryDataStore != null)
+                        {
+                            destFile = destTemplateObjectTO.FullFileName;
+                            if (!destTemplateObjectTO.primaryDataStore.isLocal)
+                            {
+                                PrimaryDataStoreTO primary = destTemplateObjectTO.primaryDataStore;
+                                Utils.ConnectToRemote(primary.UncPath, primary.Domain, primary.User, primary.Password);
+                            }
+                        }
+                        else if (destTemplateObjectTO.nfsDataStoreTO != null)
+                        {
+                            destFile = destTemplateObjectTO.FullFileName;
+                            NFSTO store = destTemplateObjectTO.nfsDataStoreTO;
+                            Utils.ConnectToRemote(store.UncPath, store.Domain, store.User, store.Password);
+                        }
+                    }
+
+                    // Template already downloaded?
+                    if (destFile != null && File.Exists(destFile) &&
+                        !String.IsNullOrEmpty(destTemplateObjectTO.checksum))
+                    {
+                        // TODO: checksum fails us, because it is of the compressed image.
+                        // ASK: should we store the compressed or uncompressed version or is the checksum not calculated correctly?
+                        logger.Debug(CloudStackTypes.CopyCommand + " calling VerifyChecksum to see if we already have the file at " + destFile);
+                        result = VerifyChecksum(destFile, destTemplateObjectTO.checksum);
+                        if (!result)
+                        {
+                            result = true;
+                            logger.Debug(CloudStackTypes.CopyCommand + " existing file has different checksum " + destFile);
+                        }
+                    }
+
+                    // Do we have to create a new one?
+                    if (!result)
+                    {
+                        // Create local copy of a template?
+                        if (srcTemplateObjectTO != null && destTemplateObjectTO != null)
+                        {
+                            // S3 download to primary storage?
+                            // NFS provider download to primary storage?
+                            if ((srcTemplateObjectTO.s3DataStoreTO != null || srcTemplateObjectTO.nfsDataStoreTO != null) && destTemplateObjectTO.primaryDataStore != null)
+                            {
+                                if (File.Exists(destFile))
+                                {
+                                    logger.Info("Deleting existing file " + destFile);
+                                    File.Delete(destFile);
+                                }
+
+                                if (srcTemplateObjectTO.s3DataStoreTO != null)
+                                {
+                                    // Download from S3 to destination data storage
+                                    DownloadS3ObjectToFile(srcTemplateObjectTO.path, srcTemplateObjectTO.s3DataStoreTO, destFile);
+                                }
+                                else if (srcTemplateObjectTO.nfsDataStoreTO != null)
+                                {
+                                    // Download from S3 to destination data storage
+                                    Utils.DownloadCifsFileToLocalFile(srcTemplateObjectTO.path, srcTemplateObjectTO.nfsDataStoreTO, destFile);
+                                }
+
+                                // Uncompress, as required
+                                if (srcTemplateObjectTO.path.EndsWith(".bz2"))
+                                {
+                                    String uncompressedFile = destFile + ".tmp";
+                                    String compressedFile = destFile;
+                                    using (var uncompressedOutStrm = new FileStream(uncompressedFile, FileMode.CreateNew, FileAccess.Write))
+                                    {
+                                        using (var compressedInStrm = new FileStream(destFile, FileMode.Open, FileAccess.Read))
+                                        {
+                                            using (var bz2UncompressorStrm = new Ionic.BZip2.BZip2InputStream(compressedInStrm, true) /* outer 'using' statement will close FileStream*/ )
+                                            {
+                                                int count = 0;
+                                                int bufsize = 1024 * 1024;
+                                                byte[] buf = new byte[bufsize];
+
+                                                // EOF returns -1, see http://dotnetzip.codeplex.com/workitem/16069 
+                                                while (0 < (count = bz2UncompressorStrm.Read(buf, 0, bufsize)))
+                                                {
+                                                    uncompressedOutStrm.Write(buf, 0, count);
+                                                }
+                                            }
+                                        }
+                                    }
+                                    File.Delete(compressedFile);
+                                    File.Move(uncompressedFile, compressedFile);
+                                    if (File.Exists(uncompressedFile))
+                                    {
+                                        String errMsg = "Extra file left around called " + uncompressedFile + " when creating " + destFile;
+                                        logger.Error(errMsg);
+                                        throw new IOException(errMsg);
+                                    }
+                                }
+
+                                // assert
+                                if (!File.Exists(destFile))
+                                {
+                                    String errMsg = "Failed to create " + destFile + " , because the file is missing";
+                                    logger.Error(errMsg);
+                                    throw new IOException(errMsg);
+                                }
+
+                                newData = cmd.destTO;
+                                result = true;
+                            }
+                            else
+                            {
+                                details = "Data store combination not supported";
+                            }
+                        }
+                        // Create volume from a template?
+                        else if (srcTemplateObjectTO != null && destVolumeObjectTO != null)
+                        {
+                            // VolumeObjectTO guesses file extension based on existing files
+                            // this can be wrong if the previous file had a different file type
+                            var guessedDestFile = destVolumeObjectTO.FullFileName;
+                            if (File.Exists(guessedDestFile))
+                            {
+                                logger.Info("Deleting existing file " + guessedDestFile);
+                                File.Delete(guessedDestFile);
+                            }
+
+                            destVolumeObjectTO.format = srcTemplateObjectTO.format;
+                            destFile = destVolumeObjectTO.FullFileName;
+                            if (File.Exists(destFile))
+                            {
+                                logger.Info("Deleting existing file " + destFile);
+                                File.Delete(destFile);
+                            }
+
+                            string srcFile = srcTemplateObjectTO.FullFileName;
+                            if (!File.Exists(srcFile))
+                            {
+                                details = "Local template file missing from " + srcFile;
+                            }
+                            else
+                            {
+                                // TODO: thin provision instead of copying the full file.
+                                File.Copy(srcFile, destFile);
+                                destVolumeObjectTO.path = destVolumeObjectTO.uuid;
+                                JObject ansObj = Utils.CreateCloudStackObject(CloudStackTypes.VolumeObjectTO, destVolumeObjectTO);
+                                newData = ansObj;
+                                result = true;
+                            }
+                        }
+                        else if (srcVolumeObjectTO != null && destVolumeObjectTO != null)
+                        {
+                            var guessedDestFile = destVolumeObjectTO.FullFileName;
+                            if (File.Exists(guessedDestFile))
+                            {
+                                logger.Info("Deleting existing file " + guessedDestFile);
+                                File.Delete(guessedDestFile);
+                            }
+
+                            destVolumeObjectTO.format = srcVolumeObjectTO.format;
+                            destFile = destVolumeObjectTO.FullFileName;
+                            if (File.Exists(destFile))
+                            {
+                                logger.Info("Deleting existing file " + destFile);
+                                File.Delete(destFile);
+                            }
+
+                            string srcFile = srcVolumeObjectTO.FullFileName;
+                            if (!File.Exists(srcFile))
+                            {
+                                details = "Local template file missing from " + srcFile;
+                            }
+                            else
+                            {
+                                // Create the directory before copying the files. CreateDirectory
+                                // doesn't do anything if the directory is already present.
+                                Directory.CreateDirectory(Path.GetDirectoryName(destFile));
+                                File.Copy(srcFile, destFile);
+
+                                if (srcVolumeObjectTO.nfsDataStore != null && srcVolumeObjectTO.primaryDataStore == null)
+                                {
+                                    logger.Info("Copied volume from secondary data store to primary. Path: " + destVolumeObjectTO.path);
+                                }
+                                else if (srcVolumeObjectTO.primaryDataStore != null && srcVolumeObjectTO.nfsDataStore == null)
+                                {
+                                    destVolumeObjectTO.path = destVolumeObjectTO.path + "/" + destVolumeObjectTO.uuid;
+                                    if (destVolumeObjectTO.format != null)
+                                    {
+                                        destVolumeObjectTO.path += "." + destVolumeObjectTO.format.ToLower();
+                                    }
+                                }
+                                else
+                                {
+                                    logger.Error("Destination volume path wasn't set. Unsupported source volume data store.");
+                                }
+
+                                // Create volumeto object deserialize and send it
+                                JObject ansObj = Utils.CreateCloudStackObject(CloudStackTypes.VolumeObjectTO, destVolumeObjectTO);
+                                newData = ansObj;
+                                result = true;
+                            }
+                        }
+                        else if (srcVolumeObjectTO != null && destTemplateObjectTO != null)
+                        {
+                            var guessedDestFile = destTemplateObjectTO.FullFileName;
+                            if (File.Exists(guessedDestFile))
+                            {
+                                logger.Info("Deleting existing file " + guessedDestFile);
+                                File.Delete(guessedDestFile);
+                            }
+
+                            destTemplateObjectTO.format = srcVolumeObjectTO.format;
+                            destFile = destTemplateObjectTO.FullFileName;
+                            if (File.Exists(destFile))
+                            {
+                                logger.Info("Deleting existing file " + destFile);
+                                File.Delete(destFile);
+                            }
+
+                            string srcFile = srcVolumeObjectTO.FullFileName;
+                            if (!File.Exists(srcFile))
+                            {
+                                details = "Local template file missing from " + srcFile;
+                            }
+                            else
+                            {
+                                // Create the directory before copying the files. CreateDirectory
+                                // doesn't do anything if the directory is already present.
+                                Directory.CreateDirectory(Path.GetDirectoryName(destFile));
+                                File.Copy(srcFile, destFile);
+
+                                FileInfo destFileInfo = new FileInfo(destFile);
+                                // Write the template.properties file
+                                PostCreateTemplate(Path.GetDirectoryName(destFile), destTemplateObjectTO.id, destTemplateObjectTO.name,
+                                    destFileInfo.Length.ToString(), srcVolumeObjectTO.size.ToString(), destTemplateObjectTO.format);
+
+                                TemplateObjectTO destTemplateObject = new TemplateObjectTO();
+                                destTemplateObject.size = srcVolumeObjectTO.size.ToString();
+                                destTemplateObject.format = srcVolumeObjectTO.format;
+                                destTemplateObject.path = destTemplateObjectTO.path + "/" + destTemplateObjectTO.uuid;
+                                if (destTemplateObject.format != null)
+                                {
+                                    destTemplateObject.path += "." + destTemplateObject.format.ToLower();
+                                }
+                                destTemplateObject.nfsDataStoreTO = destTemplateObjectTO.nfsDataStoreTO;
+                                destTemplateObject.checksum = destTemplateObjectTO.checksum;
+                                newData = destTemplateObject;
+                                JObject ansObj = Utils.CreateCloudStackObject(CloudStackTypes.TemplateObjectTO, destTemplateObject);
+                                newData = ansObj;
+                                result = true;
+                            }
+                        }
+                        else
+                        {
+                            details = "Data store combination not supported";
+                        }
+                    }
+                }
+                catch (Exception ex)
+                {
+                    // Test by providing wrong key
+                    details = CloudStackTypes.CopyCommand + " failed on exception, " + ex.Message;
+                    logger.Error(details, ex);
+                }
+
+                object ansContent = new
+                {
+                    result = result,
+                    details = details,
+                    newData = newData,
+                    contextMap = contextMap
+                };
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.CopyCmdAnswer);
+            }
+        }
+
+        private static void PostCreateTemplate(string path, string templateId, string templateUuid, string physicalSize, string virtualSize, string format)
+        {
+            string templatePropFile = Path.Combine(path, "template.properties");
+            using (StreamWriter sw = new StreamWriter(File.Open(templatePropFile, FileMode.Create), Encoding.GetEncoding("iso-8859-1")))
+            {
+                if (format != null)
+                {
+                    format = format.ToLower();
+                }
+
+                sw.NewLine = "\n";
+                sw.WriteLine("id=" + templateId);
+                sw.WriteLine("filename=" + templateUuid + "." + format);
+                sw.WriteLine(format + ".filename=" + templateUuid + "." + format);
+                sw.WriteLine("uniquename=" + templateUuid);
+                sw.WriteLine(format + "=true");
+                sw.WriteLine("virtualsize=" + virtualSize);
+                sw.WriteLine(format + ".virtualsize=" + virtualSize);
+                sw.WriteLine("size=" + physicalSize);
+                sw.WriteLine(format + ".size=" + physicalSize);
+                sw.WriteLine("public=false");
+            }
+        }
+
+        private static bool VerifyChecksum(string destFile, string checksum)
+        {
+            string localChecksum = BitConverter.ToString(CalcFileChecksum(destFile)).Replace("-", "").ToLower();
+            logger.Debug("Checksum of " + destFile + " is " + checksum);
+            if (checksum.Equals(localChecksum))
+            {
+                return true;
+            }
+            return false;
+        }
+
+        /// <summary>
+        /// Match implmentation of DownloadManagerImpl.computeCheckSum
+        /// </summary>
+        /// <param name="destFile"></param>
+        /// <returns></returns>
+        private static byte[] CalcFileChecksum(string destFile)
+        {
+            // TODO:  Add unit test to verify that checksum algorithm has not changed.
+            using (MD5 md5 = MD5.Create())
+            {
+                using (FileStream stream = File.OpenRead(destFile))
+                {
+                    return md5.ComputeHash(stream);
+                }
+            }
+        }
+
+        private static void DownloadS3ObjectToFile(string srcObjectKey, S3TO srcS3TO, string destFile)
+        {
+            AmazonS3Config S3Config = new AmazonS3Config
+            {
+                ServiceURL = srcS3TO.endpoint,
+                CommunicationProtocol = Amazon.S3.Model.Protocol.HTTP
+            };
+
+            if (srcS3TO.httpsFlag)
+            {
+                S3Config.CommunicationProtocol = Protocol.HTTPS;
+            }
+
+            try
+            {
+                using (AmazonS3 client = Amazon.AWSClientFactory.CreateAmazonS3Client(srcS3TO.accessKey, srcS3TO.secretKey, S3Config))
+                {
+                    GetObjectRequest getObjectRequest = new GetObjectRequest().WithBucketName(srcS3TO.bucketName).WithKey(srcObjectKey);
+
+                    using (S3Response getObjectResponse = client.GetObject(getObjectRequest))
+                    {
+                        using (Stream s = getObjectResponse.ResponseStream)
+                        {
+                            using (FileStream fs = new FileStream(destFile, FileMode.Create, FileAccess.Write))
+                            {
+                                byte[] data = new byte[524288];
+                                int bytesRead = 0;
+                                do
+                                {
+                                    bytesRead = s.Read(data, 0, data.Length);
+                                    fs.Write(data, 0, bytesRead);
+                                }
+                                while (bytesRead > 0);
+                                fs.Flush();
+                            }
+                        }
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                string errMsg = "Download from S3 url" + srcS3TO.endpoint + " said: " + ex.Message;
+                logger.Error(errMsg, ex);
+                throw new Exception(errMsg, ex);
+            }
+        }
 
+        // POST api/HypervResource/GetStorageStatsCommand
+        [HttpPost]
+        [ActionName(CloudStackTypes.GetStorageStatsCommand)]
+        public JContainer GetStorageStatsCommand([FromBody]dynamic cmd)
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                logger.Info(CloudStackTypes.GetStorageStatsCommand + Utils.CleanString(cmd.ToString()));
+                bool result = false;
+                string details = null;
+                long capacity = 0;
+                long available = 0;
+                long used = 0;
                 try
                 {
-                    string vmName = (string)cmd.vmName;
-                    var sys = wmiCallsV2.GetComputerSystem(vmName);
-                    if (sys == null)
+                    StoragePoolType poolType;
+                    string hostPath = null;
+                    if (!Enum.TryParse<StoragePoolType>((string)cmd.pooltype, out poolType))
                     {
-                        details = CloudStackTypes.RebootCommand + " requested unknown VM " + vmName;
+                        details = "Request to get unsupported pool type: " + ((string)cmd.pooltype == null ? "NULL" : (string)cmd.pooltype) + "in cmd " +
+                            JsonConvert.SerializeObject(cmd);
                         logger.Error(details);
                     }
-                    else
+                    else if (poolType == StoragePoolType.Filesystem)
                     {
-                        wmiCallsV2.SetState(sys, RequiredState.Reset);
+                        hostPath = (string)cmd.localPath;;
+                        GetCapacityForLocalPath(hostPath, out capacity, out available);
+                        used = capacity - available;
                         result = true;
                     }
+                    else if (poolType == StoragePoolType.NetworkFilesystem || poolType == StoragePoolType.SMB)
+                    {
+                        string sharePath = config.getPrimaryStorage((string)cmd.id);
+                        if (sharePath != null)
+                        {
+                            hostPath = sharePath;
+                            Utils.GetShareDetails(sharePath, out capacity, out available);
+                            used = capacity - available;
+                            result = true;
+                        }
+                    }
+                    else
+                    {
+                        result = false;
+                    }
+
+                    if (result)
+                    {
+                        logger.Debug(CloudStackTypes.GetStorageStatsCommand + " set used bytes for " + hostPath + " to " + used);
+                    }
                 }
-                catch (Exception sysEx)
+                catch (Exception ex)
                 {
-                    details = CloudStackTypes.RebootCommand + " failed due to " + sysEx.Message;
-                    logger.Error(details, sysEx);
+                    details = CloudStackTypes.GetStorageStatsCommand + " failed on exception" + ex.Message;
+                    logger.Error(details, ex);
                 }
 
                 object ansContent = new
                 {
                     result = result,
                     details = details,
+                    capacity = capacity,
+                    used = used,
                     contextMap = contextMap
                 };
-
-                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.RebootAnswer);
+                return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.GetStorageStatsAnswer);
             }
         }
 
-        // POST api/HypervResource/DestroyCommand
+        // POST api/HypervResource/GetHostStatsCommand
         [HttpPost]
-        [ActionName(CloudStackTypes.DestroyCommand)]
-        public JContainer DestroyCommand([FromBody]dynamic cmd)
+        [ActionName(CloudStackTypes.GetHostStatsCommand)]
+        public JContainer GetHostStatsCommand([FromBody]dynamic cmd)
         {
             using (log4net.NDC.Push(Guid.NewGuid().ToString()))
             {
-                logger.Info(CloudStackTypes.DestroyCommand + Utils.CleanString(cmd.ToString()));
-
-                string details = null;
+                logger.Info(CloudStackTypes.GetHostStatsCommand + Utils.CleanString(cmd.ToString()))

<TRUNCATED>