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

[3/4] Fixed windows line ending issues

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/dacb5419/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 37f5f53..0ad95b8 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
@@ -1,112 +1,112 @@
-// 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 Amazon;
-using Amazon.S3;
-using Amazon.S3.Model;
-using log4net;
-using Microsoft.CSharp.RuntimeBinder;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using System;
-using System.Collections;
-using System.Collections.Specialized;
-using System.Collections.Generic;
-using System.Configuration;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Net.Http;
-using System.Text;
-using System.Security.Cryptography;
-using System.Security.Principal;
-using System.Web.Http;
-using CloudStack.Plugin.WmiWrappers.ROOT.VIRTUALIZATION.V2;
-
-namespace HypervResource
-{
-
-    public struct HypervResourceControllerConfig
-    {
-        private string privateIpAddress;
-        private static ILog logger = LogManager.GetLogger(typeof(HypervResourceControllerConfig));
-
-        public string PrivateIpAddress
-        {
-            get
-            {
-                return privateIpAddress;
-            }
-            set
-            {
-                ValidateIpAddress(value);
-                privateIpAddress = value;
-                System.Net.NetworkInformation.NetworkInterface nic = HypervResourceController.GetNicInfoFromIpAddress(privateIpAddress, out PrivateNetmask);
-                PrivateMacAddress = nic.GetPhysicalAddress().ToString();
-            }
-        }
-
-        private static void ValidateIpAddress(string value)
-        {
-            // Convert to IP address
-            IPAddress ipAddress;
-            if (!IPAddress.TryParse(value, out ipAddress))
-            {
-                String errMsg = "Invalid PrivateIpAddress: " + value;
-                logger.Error(errMsg);
-                throw new ArgumentException(errMsg);
-            }
-        }
-        public string GatewayIpAddress;
-        public string PrivateMacAddress;
-        public string PrivateNetmask;
-        public string StorageNetmask;
-        public string StorageMacAddress;
-        public string StorageIpAddress;
-        public long RootDeviceReservedSpaceBytes;
-        public string RootDeviceName;
-        public ulong ParentPartitionMinMemoryMb;
-        public string LocalSecondaryStoragePath;
-        public string systemVmIso;
-
-        private string getPrimaryKey(string id)
-        {
-            return "primary_storage_" + id;
-        }
-
-        public string getPrimaryStorage(string id)
-        {
-            NameValueCollection settings = ConfigurationManager.AppSettings;
-            return settings.Get(getPrimaryKey(id));
-        }
-
-        public void setPrimaryStorage(string id, string path)
-        {
-            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
-            KeyValueConfigurationCollection settings = config.AppSettings.Settings;
-            string key = getPrimaryKey(id);
-            if (settings[key] != null)
-            {
-                settings.Remove(key);
-            }
-            settings.Add(key, path);
-            config.Save(ConfigurationSaveMode.Modified);
-            ConfigurationManager.RefreshSection("appSettings");
-        }
+// 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 Amazon;
+using Amazon.S3;
+using Amazon.S3.Model;
+using log4net;
+using Microsoft.CSharp.RuntimeBinder;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Collections.Generic;
+using System.Configuration;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Text;
+using System.Security.Cryptography;
+using System.Security.Principal;
+using System.Web.Http;
+using CloudStack.Plugin.WmiWrappers.ROOT.VIRTUALIZATION.V2;
+
+namespace HypervResource
+{
+
+    public struct HypervResourceControllerConfig
+    {
+        private string privateIpAddress;
+        private static ILog logger = LogManager.GetLogger(typeof(HypervResourceControllerConfig));
+
+        public string PrivateIpAddress
+        {
+            get
+            {
+                return privateIpAddress;
+            }
+            set
+            {
+                ValidateIpAddress(value);
+                privateIpAddress = value;
+                System.Net.NetworkInformation.NetworkInterface nic = HypervResourceController.GetNicInfoFromIpAddress(privateIpAddress, out PrivateNetmask);
+                PrivateMacAddress = nic.GetPhysicalAddress().ToString();
+            }
+        }
+
+        private static void ValidateIpAddress(string value)
+        {
+            // Convert to IP address
+            IPAddress ipAddress;
+            if (!IPAddress.TryParse(value, out ipAddress))
+            {
+                String errMsg = "Invalid PrivateIpAddress: " + value;
+                logger.Error(errMsg);
+                throw new ArgumentException(errMsg);
+            }
+        }
+        public string GatewayIpAddress;
+        public string PrivateMacAddress;
+        public string PrivateNetmask;
+        public string StorageNetmask;
+        public string StorageMacAddress;
+        public string StorageIpAddress;
+        public long RootDeviceReservedSpaceBytes;
+        public string RootDeviceName;
+        public ulong ParentPartitionMinMemoryMb;
+        public string LocalSecondaryStoragePath;
+        public string systemVmIso;
+
+        private string getPrimaryKey(string id)
+        {
+            return "primary_storage_" + id;
+        }
+
+        public string getPrimaryStorage(string id)
+        {
+            NameValueCollection settings = ConfigurationManager.AppSettings;
+            return settings.Get(getPrimaryKey(id));
+        }
+
+        public void setPrimaryStorage(string id, string path)
+        {
+            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
+            KeyValueConfigurationCollection settings = config.AppSettings.Settings;
+            string key = getPrimaryKey(id);
+            if (settings[key] != null)
+            {
+                settings.Remove(key);
+            }
+            settings.Add(key, path);
+            config.Save(ConfigurationSaveMode.Modified);
+            ConfigurationManager.RefreshSection("appSettings");
+        }
 
         public List<string> getAllPrimaryStorages()
         {
@@ -122,2267 +122,2267 @@ namespace HypervResource
             }
             return poolPaths;
         }
-    }
-
-    /// <summary>
-    /// Supports one HTTP GET and multiple HTTP POST URIs
-    /// </summary>
-    /// <remarks>
-    /// <para>
-    /// POST takes dynamic to allow it to receive JSON without concern for what is the underlying object.
-    /// E.g. http://stackoverflow.com/questions/14071715/passing-dynamic-json-object-to-web-api-newtonsoft-example 
-    /// and http://stackoverflow.com/questions/3142495/deserialize-json-into-c-sharp-dynamic-object
-    /// Use ActionName attribute to allow multiple POST URLs, one for each supported command
-    /// E.g. http://stackoverflow.com/a/12703423/939250
-    /// Strictly speaking, this goes against the purpose of an ApiController, which is to provide one GET/POST/PUT/DELETE, etc.
-    /// However, it reduces the amount of code by removing the need for a switch according to the incoming command type.
-    /// http://weblogs.asp.net/fredriknormen/archive/2012/06/11/asp-net-web-api-exception-handling.aspx
-    /// </para>
-    /// <para>
-    /// Exceptions handled on command by command basis rather than globally to allow details of the command
-    /// to be reflected in the response.  Default error handling is in the catch for Exception, but
-    /// other exception types may be caught where the feedback would be different.
-    /// NB: global alternatives discussed at 
-    /// http://weblogs.asp.net/fredriknormen/archive/2012/06/11/asp-net-web-api-exception-handling.aspx
-    /// </para>
-    /// </remarks>
-    public class HypervResourceController : ApiController
-    {
-        public static void Configure(HypervResourceControllerConfig config)
-        {
-            HypervResourceController.config = config;
-            wmiCallsV2 = new WmiCallsV2();
-        }
-
-        public static HypervResourceControllerConfig config = new HypervResourceControllerConfig();
-
-        private static ILog logger = LogManager.GetLogger(typeof(HypervResourceController));
-        private string systemVmIso  = "";
-        Dictionary<String, String> contextMap = new Dictionary<String, String>();
-
-        public static void Initialize()
-        {
-        }
-
-        public static IWmiCallsV2 wmiCallsV2 { get; set;}
-
-        // GET api/HypervResource
-        public string Get()
-        {
-            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
-            {
-                return "HypervResource controller running, use POST to send JSON encoded RPCs"; ;
-            }
-        }
-
-        /// <summary>
-        /// NOP - placeholder for future setup, e.g. delete existing VMs or Network ports 
-        /// POST api/HypervResource/SetupCommand
-        /// </summary>
-        /// <param name="cmd"></param>
-        /// <returns></returns>
-        /// TODO: produce test
-        [HttpPost]
-        [ActionName(CloudStackTypes.SetupCommand)]
-        public JContainer SetupCommand([FromBody]dynamic cmd)
-        {
-            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
-            {
+    }
+
+    /// <summary>
+    /// Supports one HTTP GET and multiple HTTP POST URIs
+    /// </summary>
+    /// <remarks>
+    /// <para>
+    /// POST takes dynamic to allow it to receive JSON without concern for what is the underlying object.
+    /// E.g. http://stackoverflow.com/questions/14071715/passing-dynamic-json-object-to-web-api-newtonsoft-example 
+    /// and http://stackoverflow.com/questions/3142495/deserialize-json-into-c-sharp-dynamic-object
+    /// Use ActionName attribute to allow multiple POST URLs, one for each supported command
+    /// E.g. http://stackoverflow.com/a/12703423/939250
+    /// Strictly speaking, this goes against the purpose of an ApiController, which is to provide one GET/POST/PUT/DELETE, etc.
+    /// However, it reduces the amount of code by removing the need for a switch according to the incoming command type.
+    /// http://weblogs.asp.net/fredriknormen/archive/2012/06/11/asp-net-web-api-exception-handling.aspx
+    /// </para>
+    /// <para>
+    /// Exceptions handled on command by command basis rather than globally to allow details of the command
+    /// to be reflected in the response.  Default error handling is in the catch for Exception, but
+    /// other exception types may be caught where the feedback would be different.
+    /// NB: global alternatives discussed at 
+    /// http://weblogs.asp.net/fredriknormen/archive/2012/06/11/asp-net-web-api-exception-handling.aspx
+    /// </para>
+    /// </remarks>
+    public class HypervResourceController : ApiController
+    {
+        public static void Configure(HypervResourceControllerConfig config)
+        {
+            HypervResourceController.config = config;
+            wmiCallsV2 = new WmiCallsV2();
+        }
+
+        public static HypervResourceControllerConfig config = new HypervResourceControllerConfig();
+
+        private static ILog logger = LogManager.GetLogger(typeof(HypervResourceController));
+        private string systemVmIso  = "";
+        Dictionary<String, String> contextMap = new Dictionary<String, String>();
+
+        public static void Initialize()
+        {
+        }
+
+        public static IWmiCallsV2 wmiCallsV2 { get; set;}
+
+        // GET api/HypervResource
+        public string Get()
+        {
+            using (log4net.NDC.Push(Guid.NewGuid().ToString()))
+            {
+                return "HypervResource controller running, use POST to send JSON encoded RPCs"; ;
+            }
+        }
+
+        /// <summary>
+        /// NOP - placeholder for future setup, e.g. delete existing VMs or Network ports 
+        /// POST api/HypervResource/SetupCommand
+        /// </summary>
+        /// <param name="cmd"></param>
+        /// <returns></returns>
+        /// TODO: produce test
+        [HttpPost]
+        [ActionName(CloudStackTypes.SetupCommand)]
+        public JContainer SetupCommand([FromBody]dynamic cmd)
+        {
+            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;
-
-                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()))
-            {
+
+                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 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()))
-            {
+                    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 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";
+                    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 = "s

<TRUNCATED>