You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by de...@apache.org on 2013/10/28 06:18:44 UTC

[2/2] git commit: updated refs/heads/hyperv to e0a5169

Hyperv unit tests for  the agent. Unit tests are written using NSubstitute and XUnit and
they test the create, stop and start commands in the agent.


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

Branch: refs/heads/hyperv
Commit: e0a51695cd58c73cd4ba77dd12d668a2e357d6c4
Parents: d0f764b
Author: Devdeep Singh <de...@gmail.com>
Authored: Mon Oct 28 10:47:04 2013 +0530
Committer: Devdeep Singh <de...@gmail.com>
Committed: Mon Oct 28 10:47:04 2013 +0530

----------------------------------------------------------------------
 .../hyperv/DotNet/ServerResource/.gitignore     |   1 +
 .../DotNet/ServerResource/.nuget/NuGet.Config   |   6 +
 .../DotNet/ServerResource/.nuget/NuGet.targets  | 136 +++++++++
 .../AgentShell/AgentSettings.Designer.cs        |   2 +-
 .../AgentShell/AgentSettings.settings           |   2 +-
 .../ServerResource/AgentShell/AgentShell.csproj |   9 +
 .../ServerResource/AgentShell/packages.config   |   3 +
 .../HypervResource/HypervResource.csproj        |   4 +-
 .../HypervResource/HypervResourceController.cs  |  33 +-
 .../ServerResource/HypervResource/IWmiCalls.cs  |  44 +++
 .../HypervResource/IWmiCallsV2.cs               |  22 ++
 .../ServerResource/HypervResource/WmiCalls.cs   | 103 ++++---
 .../ServerResource/HypervResource/WmiCallsV2.cs |  21 +-
 .../HypervResource/packages.config              |   2 +
 .../ServerResource.Tests/App.config             |  29 +-
 .../HypervResourceController1Test.cs            | 298 +++++++++++++++++++
 .../HypervResourceControllerTest.cs             | 209 ++++++-------
 .../ServerResource.Tests.csproj                 |  15 +
 .../ServerResource.Tests/packages.config        |   3 +
 .../WmiWrappers/WmiWrappers.csproj              |  20 +-
 plugins/hypervisors/hyperv/buildagent.sh        |   2 +-
 .../storagepool/TestCopiedLocalTemplate.vhdx    |   1 +
 22 files changed, 774 insertions(+), 191 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e0a51695/plugins/hypervisors/hyperv/DotNet/ServerResource/.gitignore
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/.gitignore b/plugins/hypervisors/hyperv/DotNet/ServerResource/.gitignore
index cf9cb85..99afc0b 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/.gitignore
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/.gitignore
@@ -5,4 +5,5 @@ WmiWrappers/bin/*
 AgentShell/bin/*
 ServerResource*/bin/*
 *.user
+!.nuget/
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e0a51695/plugins/hypervisors/hyperv/DotNet/ServerResource/.nuget/NuGet.Config
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/.nuget/NuGet.Config b/plugins/hypervisors/hyperv/DotNet/ServerResource/.nuget/NuGet.Config
new file mode 100644
index 0000000..6a318ad
--- /dev/null
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/.nuget/NuGet.Config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+  <solution>
+    <add key="disableSourceControlIntegration" value="true" />
+  </solution>
+</configuration>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e0a51695/plugins/hypervisors/hyperv/DotNet/ServerResource/.nuget/NuGet.targets
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/.nuget/NuGet.targets b/plugins/hypervisors/hyperv/DotNet/ServerResource/.nuget/NuGet.targets
new file mode 100644
index 0000000..d0ebc75
--- /dev/null
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/.nuget/NuGet.targets
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+    <PropertyGroup>
+        <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)\..\</SolutionDir>
+        
+        <!-- Enable the restore command to run before builds -->
+        <RestorePackages Condition="  '$(RestorePackages)' == '' ">false</RestorePackages>
+
+        <!-- Property that enables building a package from a project -->
+        <BuildPackage Condition=" '$(BuildPackage)' == '' ">false</BuildPackage>
+
+        <!-- Determines if package restore consent is required to restore packages -->
+        <RequireRestoreConsent Condition=" '$(RequireRestoreConsent)' != 'false' ">true</RequireRestoreConsent>
+        
+        <!-- Download NuGet.exe if it does not already exist -->
+        <DownloadNuGetExe Condition=" '$(DownloadNuGetExe)' == '' ">false</DownloadNuGetExe>
+    </PropertyGroup>
+    
+    <ItemGroup Condition=" '$(PackageSources)' == '' ">
+        <!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\NuGet\NuGet.Config will be used -->
+        <!-- The official NuGet package source (https://www.nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
+        <!--
+            <PackageSource Include="https://www.nuget.org/api/v2/" />
+            <PackageSource Include="https://my-nuget-source/nuget/" />
+        -->
+    </ItemGroup>
+
+    <PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
+        <!-- Windows specific commands -->
+        <NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
+        <PackagesConfig>$([System.IO.Path]::Combine($(ProjectDir), "packages.config"))</PackagesConfig>
+    </PropertyGroup>
+    
+    <PropertyGroup Condition=" '$(OS)' != 'Windows_NT'">
+        <!-- We need to launch nuget.exe with the mono command if we're not on windows -->
+        <NuGetToolsPath>$(SolutionDir).nuget</NuGetToolsPath>
+        <PackagesConfig>packages.config</PackagesConfig>
+    </PropertyGroup>
+    
+    <PropertyGroup>
+        <!-- NuGet command -->
+        <NuGetExePath Condition=" '$(NuGetExePath)' == '' ">$(NuGetToolsPath)\NuGet.exe</NuGetExePath>
+        <PackageSources Condition=" $(PackageSources) == '' ">@(PackageSource)</PackageSources>
+        
+        <NuGetCommand Condition=" '$(OS)' == 'Windows_NT'">"$(NuGetExePath)"</NuGetCommand>
+        <NuGetCommand Condition=" '$(OS)' != 'Windows_NT' ">mono --runtime=v4.0.30319 $(NuGetExePath)</NuGetCommand>
+
+        <PackageOutputDir Condition="$(PackageOutputDir) == ''">$(TargetDir.Trim('\\'))</PackageOutputDir>
+        
+        <RequireConsentSwitch Condition=" $(RequireRestoreConsent) == 'true' ">-RequireConsent</RequireConsentSwitch>
+        <NonInteractiveSwitch Condition=" '$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT' ">-NonInteractive</NonInteractiveSwitch>
+        
+        <PaddedSolutionDir Condition=" '$(OS)' == 'Windows_NT'">"$(SolutionDir) "</PaddedSolutionDir>
+        <PaddedSolutionDir Condition=" '$(OS)' != 'Windows_NT' ">"$(SolutionDir)"</PaddedSolutionDir>
+
+        <!-- Commands -->
+        <RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)"  $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)</RestoreCommand>
+        <BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols</BuildCommand>
+
+        <!-- We need to ensure packages are restored prior to assembly resolve -->
+        <BuildDependsOn Condition="$(RestorePackages) == 'true'">
+            RestorePackages;
+            $(BuildDependsOn);
+        </BuildDependsOn>
+
+        <!-- Make the build depend on restore packages -->
+        <BuildDependsOn Condition="$(BuildPackage) == 'true'">
+            $(BuildDependsOn);
+            BuildPackage;
+        </BuildDependsOn>
+    </PropertyGroup>
+
+    <Target Name="CheckPrerequisites">
+        <!-- Raise an error if we're unable to locate nuget.exe  -->
+        <Error Condition="'$(DownloadNuGetExe)' != 'true' AND !Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" />
+        <!--
+        Take advantage of MsBuild's build dependency tracking to make sure that we only ever download nuget.exe once.
+        This effectively acts as a lock that makes sure that the download operation will only happen once and all
+        parallel builds will have to wait for it to complete.
+        -->
+        <MsBuild Targets="_DownloadNuGet" Projects="$(MSBuildThisFileFullPath)" Properties="Configuration=NOT_IMPORTANT;DownloadNuGetExe=$(DownloadNuGetExe)" />
+    </Target>
+
+    <Target Name="_DownloadNuGet">
+        <DownloadNuGet OutputFilename="$(NuGetExePath)" Condition=" '$(DownloadNuGetExe)' == 'true' AND !Exists('$(NuGetExePath)')" />
+    </Target>
+
+    <Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites">
+        <Exec Command="$(RestoreCommand)"
+              Condition="'$(OS)' != 'Windows_NT' And Exists('$(PackagesConfig)')" />
+              
+        <Exec Command="$(RestoreCommand)"
+              LogStandardErrorAsError="true"
+              Condition="'$(OS)' == 'Windows_NT' And Exists('$(PackagesConfig)')" />
+    </Target>
+
+    <Target Name="BuildPackage" DependsOnTargets="CheckPrerequisites">
+        <Exec Command="$(BuildCommand)" 
+              Condition=" '$(OS)' != 'Windows_NT' " />
+              
+        <Exec Command="$(BuildCommand)"
+              LogStandardErrorAsError="true"
+              Condition=" '$(OS)' == 'Windows_NT' " />
+    </Target>
+    
+    <UsingTask TaskName="DownloadNuGet" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
+        <ParameterGroup>
+            <OutputFilename ParameterType="System.String" Required="true" />
+        </ParameterGroup>
+        <Task>
+            <Reference Include="System.Core" />
+            <Using Namespace="System" />
+            <Using Namespace="System.IO" />
+            <Using Namespace="System.Net" />
+            <Using Namespace="Microsoft.Build.Framework" />
+            <Using Namespace="Microsoft.Build.Utilities" />
+            <Code Type="Fragment" Language="cs">
+                <![CDATA[
+                try {
+                    OutputFilename = Path.GetFullPath(OutputFilename);
+
+                    Log.LogMessage("Downloading latest version of NuGet.exe...");
+                    WebClient webClient = new WebClient();
+                    webClient.DownloadFile("https://www.nuget.org/nuget.exe", OutputFilename);
+
+                    return true;
+                }
+                catch (Exception ex) {
+                    Log.LogErrorFromException(ex);
+                    return false;
+                }
+            ]]>
+            </Code>
+        </Task>
+    </UsingTask>
+</Project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e0a51695/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentSettings.Designer.cs
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentSettings.Designer.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentSettings.Designer.cs
index 281f169..ae2bbbc 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentSettings.Designer.cs
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentSettings.Designer.cs
@@ -192,7 +192,7 @@ namespace CloudStack.Plugin.AgentShell {
         
         [global::System.Configuration.ApplicationScopedSettingAttribute()]
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-        [global::System.Configuration.DefaultSettingValueAttribute("..\\..\\..\\..\\..\\")]
+        [global::System.Configuration.DefaultSettingValueAttribute("../../../../../")]
         public string hyperv_plugin_root {
             get {
                 return ((string)(this["hyperv_plugin_root"]));

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e0a51695/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentSettings.settings
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentSettings.settings b/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentSettings.settings
index 435b8e0..695ebe2 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentSettings.settings
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentSettings.settings
@@ -60,7 +60,7 @@
       <Value Profile="(Default)">4294967296</Value>
     </Setting>
     <Setting Name="hyperv_plugin_root" Type="System.String" Scope="Application">
-      <Value Profile="(Default)">..\..\..\..\..\</Value>
+      <Value Profile="(Default)">../../../../../</Value>
     </Setting>
     <Setting Name="RootDeviceName" Type="System.String" Scope="Application">
       <Value Profile="(Default)">e:\</Value>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e0a51695/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentShell.csproj
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentShell.csproj b/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentShell.csproj
index 2a3c0db..a813124 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentShell.csproj
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentShell.csproj
@@ -54,6 +54,9 @@
     <Prefer32Bit>true</Prefer32Bit>
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="AWSSDK">
+      <HintPath>..\packages\AWSSDK.1.5.23.0\lib\AWSSDK.dll</HintPath>
+    </Reference>
     <Reference Include="Ionic.Zip">
       <HintPath>..\packages\DotNetZip.1.9.1.8\lib\net20\Ionic.Zip.dll</HintPath>
     </Reference>
@@ -63,6 +66,9 @@
     <Reference Include="Newtonsoft.Json">
       <HintPath>..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath>
     </Reference>
+    <Reference Include="NSubstitute">
+      <HintPath>..\packages\NSubstitute.1.6.1.0\lib\NET40\NSubstitute.dll</HintPath>
+    </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
     <Reference Include="System.Management" />
@@ -83,6 +89,9 @@
     <Reference Include="System.Data" />
     <Reference Include="System.ServiceProcess" />
     <Reference Include="System.Xml" />
+    <Reference Include="xunit">
+      <HintPath>..\packages\xunit.1.9.2\lib\net20\xunit.dll</HintPath>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
     <Compile Include="AgentService.cs">

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e0a51695/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/packages.config
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/packages.config b/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/packages.config
index f5f47e6..fb1c846 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/packages.config
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/packages.config
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
+  <package id="AWSSDK" version="1.5.23.0" targetFramework="net45" />
   <package id="DotNetZip" version="1.9.1.8" targetFramework="net45" />
   <package id="log4net" version="2.0.0" targetFramework="net45" />
   <package id="Microsoft.AspNet.WebApi.Client" version="4.0.20710.0" targetFramework="net45" />
@@ -7,4 +8,6 @@
   <package id="Microsoft.AspNet.WebApi.SelfHost" version="4.0.20918.0" targetFramework="net45" />
   <package id="Microsoft.Net.Http" version="2.0.20710.0" targetFramework="net45" />
   <package id="Newtonsoft.Json" version="4.5.11" targetFramework="net45" />
+  <package id="NSubstitute" version="1.6.1.0" targetFramework="net45" />
+  <package id="xunit" version="1.9.2" targetFramework="net45" />
 </packages>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e0a51695/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResource.csproj
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResource.csproj b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResource.csproj
index dbd7b15..ed22a7a 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResource.csproj
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResource.csproj
@@ -76,6 +76,8 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="CloudStackTypes.cs" />
+    <Compile Include="IWmiCalls.cs" />
+    <Compile Include="IWmiCallsV2.cs" />
     <Compile Include="WmiCallsV2.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="HypervResourceController.cs" />
@@ -100,4 +102,4 @@
   <Target Name="AfterBuild">
   </Target>
   -->
-</Project>
+</Project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e0a51695/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 2d61a6c..bdb0eae 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/HypervResourceController.cs
@@ -118,6 +118,9 @@ namespace HypervResource
         {
         }
 
+        public IWmiCalls wmiCalls { get; set; }
+        public IWmiCallsV2 wmiCallsV2 { get; set;}
+
         // GET api/HypervResource
         public string Get()
         {
@@ -152,7 +155,7 @@ namespace HypervResource
                     share.uri = new Uri(uriStr);
 
                     string systemVmIso = (string)cmd.systemVmIso;
-                    string defaultDataPath = WmiCallsV2.GetDefaultDataRoot();
+                    string defaultDataPath = wmiCallsV2.GetDefaultDataRoot();
                     string isoPath = Path.Combine(defaultDataPath, Path.GetFileName(systemVmIso));
                     if (!File.Exists(isoPath))
                     {
@@ -195,7 +198,7 @@ namespace HypervResource
                 {
                     string vmName = (string)cmd.vmName;
                     string isoPath = "\\\\10.102.192.150\\SMB-Share\\202-2-305ed1f7-1be8-345e-86c3-a976f7f57f10.iso";
-                    WmiCalls.AttachIso(vmName, isoPath);
+                    wmiCalls.AttachIso(vmName, isoPath);
 
                     result = true;
                 }
@@ -288,7 +291,7 @@ namespace HypervResource
                     string vmName = (string)cmd.vmName;
                     if (!string.IsNullOrEmpty(vmName) && File.Exists(path))
                     {
-                        var imgmgr = WmiCalls.GetImageManagementService();
+                        var imgmgr = wmiCalls.GetImageManagementService();
                         var returncode = imgmgr.Unmount(path);
                         if (returncode != ReturnCode.Completed)
                         {
@@ -367,7 +370,7 @@ namespace HypervResource
                                 newVolName = cmd.diskCharacteristics.name;
                                 newVolPath = Path.Combine(poolLocalPath, newVolName, diskType.ToLower());
                                 // TODO: how do you specify format as VHD or VHDX?
-                                WmiCalls.CreateDynamicVirtualHardDisk(disksize, newVolPath);
+                                wmiCalls.CreateDynamicVirtualHardDisk(disksize, newVolPath);
                                 if (File.Exists(newVolPath))
                                 {
                                     result = true;
@@ -632,7 +635,7 @@ namespace HypervResource
                 string state = null;
 
                 // TODO: Look up the VM, convert Hyper-V state to CloudStack version.
-                var sys = WmiCalls.GetComputerSystem(vmName);
+                var sys = wmiCalls.GetComputerSystem(vmName);
                 if (sys == null)
                 {
                     details = CloudStackTypes.CheckVirtualMachineCommand + " requested unknown VM " + vmName;
@@ -831,7 +834,7 @@ namespace HypervResource
 
                 try
                 {
-                    WmiCalls.DeployVirtualMachine(cmd, systemVmIso);
+                    wmiCalls.DeployVirtualMachine(cmd, systemVmIso);
                     result = true;
                 }
                 catch (Exception wmiEx)
@@ -863,7 +866,7 @@ namespace HypervResource
 
                 try
                 {
-                    WmiCalls.DestroyVm(cmd);
+                    wmiCalls.DestroyVm(cmd);
                     result = true;
                 }
                 catch (Exception wmiEx)
@@ -962,13 +965,13 @@ namespace HypervResource
                 var vmsToInspect = new List<System.Management.ManagementPath>();
                 foreach (var vmName in vmNames)
                 {
-                    var sys = WmiCalls.GetComputerSystem(vmName);
+                    var sys = wmiCalls.GetComputerSystem(vmName);
                     if (sys == null)
                     {
                         logger.InfoFormat("GetVmStatsCommand requested unknown VM {0}", vmNames);
                         continue;
                     }
-                    var sysInfo = WmiCalls.GetVmSettings(sys);
+                    var sysInfo = wmiCalls.GetVmSettings(sys);
                     vmsToInspect.Add(sysInfo.Path);
                 }
 
@@ -982,7 +985,7 @@ namespace HypervResource
                 };
 
                 System.Management.ManagementBaseObject[] sysSummary;
-                var vmsvc = WmiCalls.GetVirtualisationSystemManagementService();
+                var vmsvc = wmiCalls.GetVirtualisationSystemManagementService();
                 System.Management.ManagementPath[] vmPaths = vmsToInspect.ToArray();
                 vmsvc.GetSummaryInformation(requestedInfo, vmPaths, out sysSummary);
 
@@ -1315,8 +1318,8 @@ namespace HypervResource
                 try
                 {
                     long hostId = (long)cmd.hostId;
-                    WmiCalls.GetMemoryResources(out totalMemoryKBs, out freeMemoryKBs);
-                    WmiCalls.GetProcessorUsageInfo(out cpuUtilization);
+                    wmiCalls.GetMemoryResources(out totalMemoryKBs, out freeMemoryKBs);
+                    wmiCalls.GetProcessorUsageInfo(out cpuUtilization);
 
                     // TODO: can we assume that the host has only one adaptor?
                     string tmp;
@@ -1379,12 +1382,12 @@ namespace HypervResource
                 // Detect CPUs, speed, memory
                 uint cores;
                 uint mhz;
-                WmiCalls.GetProcessorResources(out cores, out mhz);
+                wmiCalls.GetProcessorResources(out cores, out mhz);
                 strtRouteCmd.cpus = cores;
                 strtRouteCmd.speed = mhz;
                 ulong memoryKBs;
                 ulong freeMemoryKBs;
-                WmiCalls.GetMemoryResources(out memoryKBs, out freeMemoryKBs);
+                wmiCalls.GetMemoryResources(out memoryKBs, out freeMemoryKBs);
                 strtRouteCmd.memory = memoryKBs * 1024;   // Convert to bytes
 
                 // Need 2 Gig for DOM0, see http://technet.microsoft.com/en-us/magazine/hh750394.aspx
@@ -1395,7 +1398,7 @@ namespace HypervResource
                 // Read the localStoragePath for virtual disks from the Hyper-V configuration
                 // See http://blogs.msdn.com/b/virtual_pc_guy/archive/2010/05/06/managing-the-default-virtual-machine-location-with-hyper-v.aspx
                 // for discussion of Hyper-V file locations paths.
-                string localStoragePath = WmiCalls.GetDefaultVirtualDiskFolder();
+                string localStoragePath = wmiCalls.GetDefaultVirtualDiskFolder();
                 if (localStoragePath != null)
                 {
                     // GUID arbitrary.  Host agents deals with storage pool in terms of localStoragePath.

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e0a51695/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/IWmiCalls.cs
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/IWmiCalls.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/IWmiCalls.cs
new file mode 100644
index 0000000..2f48f6a
--- /dev/null
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/IWmiCalls.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CloudStack.Plugin.WmiWrappers.ROOT.VIRTUALIZATION;
+using System.Management;
+
+namespace HypervResource
+{
+    public interface IWmiCalls
+    {
+        ComputerSystem CreateVM(string name, long memory_mb, int vcpus);
+        void DestroyVm(string displayName);
+        void DestroyVm(dynamic jsonObj);
+        void patchSystemVmIso(String vmName, String systemVmIso);
+        void AttachIso(string displayName, string iso);        
+        void GetProcessorResources(out uint cores, out uint mhz);
+        void GetMemoryResources(out ulong physicalRamKBs, out ulong freeMemoryKBs);
+        string GetDefaultVirtualDiskFolder();
+        ComputerSystem DeployVirtualMachine(dynamic jsonObj, string systemVmIso);
+        ComputerSystem GetComputerSystem(string displayName);
+        void GetProcessorUsageInfo(out double cpuUtilization);
+        SyntheticEthernetPortSettingData CreateNICforVm(ComputerSystem vm, string mac, string vlan);
+        ManagementPath AddDiskDriveToVm(ComputerSystem vm, string vhdfile, string cntrllerAddr, string driveResourceType);
+        void SetState(ComputerSystem vm, ushort requiredState);
+        bool DeleteSwitchPort(string elementName);
+        VLANEndpointSettingData GetVlanEndpointSettings(VirtualSwitchManagementService vmNetMgmtSvc, ManagementPath newSwitchPath);
+        VirtualSwitch GetExternalVirtSwitch();
+        VirtualSwitchManagementService GetVirtualSwitchManagementService();
+        void CreateDynamicVirtualHardDisk(ulong MaxInternalSize, string Path);
+        ImageManagementService GetImageManagementService();
+        VirtualSystemManagementService GetVirtualisationSystemManagementService();
+        List<string> GetVmElementNames();
+        ProcessorSettingData GetProcSettings(VirtualSystemSettingData vmSettings);
+        MemorySettingData GetMemSettings(VirtualSystemSettingData vmSettings);
+        ResourceAllocationSettingData GetIDEControllerSettings(VirtualSystemSettingData vmSettings, string cntrllerAddr);
+        ResourceAllocationSettingData.ResourceAllocationSettingDataCollection GetResourceAllocationSettings(VirtualSystemSettingData vmSettings);
+        SwitchPort[] GetSwitchPorts(ComputerSystem vm);
+        SwitchPort GetSwitchPort(SyntheticEthernetPort nic);
+        SyntheticEthernetPortSettingData[] GetEthernetPorts(ComputerSystem vm);
+        VirtualSystemSettingData GetVmSettings(ComputerSystem vm);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e0a51695/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
new file mode 100644
index 0000000..b3695c7
--- /dev/null
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/IWmiCallsV2.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CloudStack.Plugin.WmiWrappers.ROOT.VIRTUALIZATION.V2;
+using System.Management;
+
+namespace HypervResource
+{
+    public interface IWmiCallsV2
+    {
+        ComputerSystem AddUserData(ComputerSystem vm, string userData);
+        void DeleteHostKvpItem(ComputerSystem vm, string key);
+        VirtualSystemManagementService GetVirtualisationSystemManagementService();
+        ComputerSystem GetComputerSystem(string displayName);        
+        List<string> GetVmElementNames();
+        VirtualSystemSettingData GetVmSettings(ComputerSystem vm);
+        KvpExchangeComponentSettingData GetKvpSettings(VirtualSystemSettingData vmSettings);
+        string GetDefaultDataRoot();
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e0a51695/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCalls.cs
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCalls.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCalls.cs
index 65b726e..1d8d58a 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCalls.cs
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCalls.cs
@@ -30,8 +30,13 @@ using System.IO;
 
 namespace HypervResource
 {
-    public class WmiCalls
+    public class WmiCalls : IWmiCalls
     {
+        private IWmiCallsV2 wmiCallsV2;
+        public WmiCalls()
+        {
+            wmiCallsV2 = new WmiCallsV2();
+        }
         public static void Initialize()
         {
             // Trigger assembly load into curren appdomain
@@ -42,7 +47,7 @@ namespace HypervResource
         /// <summary>
         /// Returns ComputerSystem lacking any NICs and VOLUMEs
         /// </summary>
-        public static ComputerSystem CreateVM(string name, long memory_mb, int vcpus)
+        public ComputerSystem CreateVM(string name, long memory_mb, int vcpus)
         {
             // Obtain controller for Hyper-V virtualisation subsystem
             VirtualSystemManagementService vmMgmtSvc = GetVirtualisationSystemManagementService();
@@ -84,7 +89,7 @@ namespace HypervResource
         /// <param name="mac"></param>
         /// <param name="vlan"></param>
         /// <returns></returns>
-        public static SyntheticEthernetPortSettingData CreateNICforVm(ComputerSystem vm, string mac, string vlan)
+        public SyntheticEthernetPortSettingData CreateNICforVm(ComputerSystem vm, string mac, string vlan)
         {
             logger.DebugFormat("Creating nic for VM {0} (GUID {1})", vm.ElementName, vm.Name);
 
@@ -158,7 +163,8 @@ namespace HypervResource
         /// <summary>
         /// Create new VM.  By default we start it. 
         /// </summary>
-        public static ComputerSystem DeployVirtualMachine(dynamic jsonObj, string systemVmIso)
+
+        public ComputerSystem DeployVirtualMachine(dynamic jsonObj, string systemVmIso)
         {
             var vmInfo = jsonObj.vm;
             string vmName = vmInfo.name;
@@ -209,7 +215,7 @@ namespace HypervResource
 
             // Create vm carcase
             logger.DebugFormat("Going ahead with create VM {0}, {1} vcpus, {2}MB RAM", vmName, vcpus, memSize);
-            var newVm = WmiCalls.CreateVM(vmName, memSize, vcpus);
+            var newVm = CreateVM(vmName, memSize, vcpus);
 
             foreach (var diskDrive in diskDrives)
             {
@@ -319,12 +325,11 @@ namespace HypervResource
             // 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 = WmiCallsV2.GetComputerSystem(vmName);
+            var vm = wmiCallsV2.GetComputerSystem(vmName);
             if (bootArgs != null)
             {
-               
                 String bootargs = bootArgs;
-                WmiCallsV2.AddUserData(vm, bootargs);
+                wmiCallsV2.AddUserData(vm, bootargs);
             }
 
             // call patch systemvm iso only for systemvms
@@ -352,11 +357,13 @@ namespace HypervResource
         /// this method is to add a dvd drive and attach the systemvm iso.
         /// 
 
-        public static void patchSystemVmIso(String vmName, String systemVmIso)
+
+        public void patchSystemVmIso(String vmName, String systemVmIso)
         {
-            ComputerSystem vmObject = WmiCalls.GetComputerSystem(vmName);
+            ComputerSystem vmObject = GetComputerSystem(vmName);
             AddDiskDriveToVm(vmObject, "", "1", IDE_ISO_DRIVE);
-            WmiCalls.AttachIso(vmName, systemVmIso);
+
+            AttachIso(vmName, systemVmIso);
         }
 
         /// <summary>
@@ -365,7 +372,7 @@ namespace HypervResource
         /// <param name="vm"></param>
         /// <param name="cntrllerAddr"></param>
         /// <param name="driveResourceType">IDE_HARDDISK_DRIVE or IDE_ISO_DRIVE</param>
-        public static ManagementPath AddDiskDriveToVm(ComputerSystem vm, string vhdfile, string cntrllerAddr, string driveResourceType)
+        public ManagementPath AddDiskDriveToVm(ComputerSystem vm, string vhdfile, string cntrllerAddr, string driveResourceType)
         {
             logger.DebugFormat("Creating DISK for VM {0} (GUID {1}) by attaching {2}", 
                         vm.ElementName,
@@ -406,7 +413,7 @@ namespace HypervResource
             return newDrivePath;
     }
 
-        private static ManagementPath AttachNewDriveToVm(ComputerSystem vm, string cntrllerAddr, string driveType)
+        private ManagementPath AttachNewDriveToVm(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);
@@ -453,7 +460,7 @@ namespace HypervResource
         /// </summary>
         /// <param name="vm"></param>
         /// <param name="isoPath"></param>
-        private static void AttachIsoToVm(ComputerSystem vm, string isoPath)
+        private void AttachIsoToVm(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);
@@ -490,7 +497,7 @@ namespace HypervResource
                     isoPath);
         }
 
-        private static void InsertDiskImage(ComputerSystem vm, string vhdfile, string diskResourceSubType, ManagementPath drivePath)
+        private void InsertDiskImage(ComputerSystem vm, string vhdfile, 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);
@@ -524,7 +531,7 @@ namespace HypervResource
                     vhdfile);
         }
 
-        private static ResourceAllocationSettingData CloneResourceAllocationSetting(string wmiQuery)
+        private ResourceAllocationSettingData CloneResourceAllocationSetting(string wmiQuery)
         {
             var defaultDiskDriveSettingsObjs = ResourceAllocationSettingData.GetInstances(wmiQuery);
 
@@ -541,7 +548,7 @@ namespace HypervResource
             return new ResourceAllocationSettingData((ManagementBaseObject)defaultDiskDriveSettings.LateBoundObject.Clone());
         }
 
-        public static void AttachIso(string displayName, string iso)
+        public void AttachIso(string displayName, string iso)
         {
             logger.DebugFormat("Got request to attach iso {0} to vm {1}", iso, displayName);
 
@@ -557,7 +564,7 @@ namespace HypervResource
             }
         }
 
-        public static void DestroyVm(dynamic jsonObj)
+        public void DestroyVm(dynamic jsonObj)
         {
             string vmToDestroy = jsonObj.vmName;
             DestroyVm(vmToDestroy);
@@ -567,7 +574,7 @@ namespace HypervResource
         /// Remove all VMs and all SwitchPorts with the displayName.  VHD gets deleted elsewhere.
         /// </summary>
         /// <param name="displayName"></param>
-        public static void DestroyVm(string displayName)
+        public void DestroyVm(string displayName)
         {
             logger.DebugFormat("Got request to destroy vm {0}", displayName);
 
@@ -614,7 +621,7 @@ namespace HypervResource
             while (vm != null);
         }
 
-        public static void SetState(ComputerSystem vm, ushort requiredState)
+        public void SetState(ComputerSystem vm, ushort requiredState)
         {
             logger.InfoFormat(
                 "Changing state of {0} (GUID {1}) to {2}", 
@@ -657,7 +664,7 @@ namespace HypervResource
 
 
         //TODO:  Write method to delete SwitchPort based on Name
-        public static bool DeleteSwitchPort(string elementName)
+        public bool DeleteSwitchPort(string elementName)
         {
             var virtSwitchMgmtSvc = GetVirtualSwitchManagementService();
             // Get NIC path
@@ -683,7 +690,7 @@ namespace HypervResource
         }
 
         // Add new 
-        private static ManagementPath[] AddVirtualResource(string[] resourceSettings, ComputerSystem vm )
+        private ManagementPath[] AddVirtualResource(string[] resourceSettings, ComputerSystem vm )
         {
             var virtSysMgmtSvc = GetVirtualisationSystemManagementService();
 
@@ -715,7 +722,7 @@ namespace HypervResource
             return resourcePaths;
         }
 
-        private static ManagementPath CreateSwitchPortForVm(ComputerSystem vm, VirtualSwitchManagementService vmNetMgmtSvc, VirtualSwitch vSwitch)
+        private ManagementPath CreateSwitchPortForVm(ComputerSystem vm, VirtualSwitchManagementService vmNetMgmtSvc, VirtualSwitch vSwitch)
         {
             ManagementPath newSwitchPath = null;
             var ret_val = vmNetMgmtSvc.CreateSwitchPort(
@@ -740,7 +747,7 @@ namespace HypervResource
         }
 
         // add vlan support by setting AccessVLAN on VLANEndpointSettingData for port
-        private static void SetPortVlan(string vlan, VirtualSwitchManagementService vmNetMgmtSvc, ManagementPath newSwitchPath)
+        private void SetPortVlan(string vlan, VirtualSwitchManagementService vmNetMgmtSvc, ManagementPath newSwitchPath)
         {
             logger.DebugFormat("Setting VLAN to {0}", vlan);
 
@@ -749,7 +756,7 @@ namespace HypervResource
             vlanEndpointSettings.CommitObject();
         }
 
-        public static VLANEndpointSettingData GetVlanEndpointSettings(VirtualSwitchManagementService vmNetMgmtSvc, ManagementPath newSwitchPath)
+        public VLANEndpointSettingData GetVlanEndpointSettings(VirtualSwitchManagementService vmNetMgmtSvc, ManagementPath newSwitchPath)
         {
             // Get Msvm_VLANEndpoint through associated with new Port
             var vlanEndpointQuery = new RelatedObjectQuery(newSwitchPath.Path, VLANEndpoint.CreatedClassName);
@@ -791,7 +798,7 @@ namespace HypervResource
         /// <param name="vmSettings"></param>
         /// <returns></returns>
         /// <throw>Throws if there is no vswitch</throw>
-        public static VirtualSwitch GetExternalVirtSwitch()
+        public VirtualSwitch GetExternalVirtSwitch()
         {
             // Work back from the first *bound* external NIC we find.
             var externNICs = ExternalEthernetPort.GetInstances("IsBound = TRUE");
@@ -857,7 +864,7 @@ namespace HypervResource
         }
 
 
-        private static void ModifyVmResources(VirtualSystemManagementService vmMgmtSvc, ComputerSystem vm, string[] resourceSettings)
+        private void ModifyVmResources(VirtualSystemManagementService vmMgmtSvc, ComputerSystem vm, string[] resourceSettings)
         {
             // Resource settings are changed through the management service
             System.Management.ManagementPath jobPath;
@@ -883,7 +890,7 @@ namespace HypervResource
             }
         }
 
-        private static ComputerSystem CreateDefaultVm(VirtualSystemManagementService vmMgmtSvc, string name)
+        private ComputerSystem CreateDefaultVm(VirtualSystemManagementService vmMgmtSvc, string name)
         {
             // Tweak default settings by basing new VM on default global setting object 
             // with designed display name.
@@ -936,7 +943,7 @@ namespace HypervResource
             return vm;
         }
 
-        public static VirtualSwitchManagementService GetVirtualSwitchManagementService()
+        public  VirtualSwitchManagementService GetVirtualSwitchManagementService()
         {
             // VirtualSwitchManagementService is a singleton, most anonymous way of lookup is by asking for the set
             // of local instances, which should be size 1.
@@ -952,7 +959,7 @@ namespace HypervResource
             throw ex;
         }
 
-        public static void CreateDynamicVirtualHardDisk(ulong MaxInternalSize, string Path)
+        public  void CreateDynamicVirtualHardDisk(ulong MaxInternalSize, string Path)
         {
             // Resource settings are changed through the management service
             System.Management.ManagementPath jobPath;
@@ -976,7 +983,7 @@ namespace HypervResource
             }
         }
 
-        public static ImageManagementService GetImageManagementService()
+        public  ImageManagementService GetImageManagementService()
         {
             // VirtualSystemManagementService is a singleton, most anonymous way of lookup is by asking for the set
             // of local instances, which should be size 1.
@@ -994,7 +1001,7 @@ namespace HypervResource
         }
 
 
-        public static VirtualSystemManagementService GetVirtualisationSystemManagementService()
+        public  VirtualSystemManagementService GetVirtualisationSystemManagementService()
         {
             // VirtualSystemManagementService is a singleton, most anonymous way of lookup is by asking for the set
             // of local instances, which should be size 1.
@@ -1016,7 +1023,7 @@ namespace HypervResource
         /// </summary>
         /// <param name="jobPath"></param>
         /// <returns></returns>
-        private static void JobCompleted(ManagementPath jobPath)
+        private  void JobCompleted(ManagementPath jobPath)
         {
             ConcreteJob jobObj = null;
             for(;;)
@@ -1044,7 +1051,7 @@ namespace HypervResource
             logger.DebugFormat("WMI job succeeded: {0}, Elapsed={1}", jobObj.Description, jobObj.ElapsedTime);
         }
 
-        public static void GetProcessorResources(out uint cores, out uint mhz)
+        public  void GetProcessorResources(out uint cores, out uint mhz)
         {
             //  Processor processors
             cores = 0;
@@ -1057,7 +1064,7 @@ namespace HypervResource
            }
         }
         
-        public static void GetProcessorUsageInfo(out double cpuUtilization)
+        public  void GetProcessorUsageInfo(out double cpuUtilization)
         {
             PerfFormattedData_Counters_ProcessorInformation.PerfFormattedData_Counters_ProcessorInformationCollection coll = 
                             PerfFormattedData_Counters_ProcessorInformation.GetInstances("Name=\"_Total\"");
@@ -1072,14 +1079,14 @@ namespace HypervResource
         }
 
 
-        public static void GetMemoryResources(out ulong physicalRamKBs, out ulong freeMemoryKBs)
+        public  void GetMemoryResources(out ulong physicalRamKBs, out ulong freeMemoryKBs)
         {
             OperatingSystem0 os = new OperatingSystem0();
             physicalRamKBs = os.TotalVisibleMemorySize;
             freeMemoryKBs = os.FreePhysicalMemory;
         }
 
-        public static string GetDefaultVirtualDiskFolder()
+        public  string GetDefaultVirtualDiskFolder()
         {
             VirtualSystemManagementServiceSettingData.VirtualSystemManagementServiceSettingDataCollection coll = VirtualSystemManagementServiceSettingData.GetInstances();
             string defaultVirtualHardDiskPath = null;
@@ -1099,7 +1106,7 @@ namespace HypervResource
             return defaultVirtualHardDiskPath;
         }
 
-        public static ComputerSystem GetComputerSystem(string displayName)
+        public  ComputerSystem GetComputerSystem(string displayName)
         {
             var wmiQuery = String.Format("ElementName=\"{0}\"", displayName);
             ComputerSystem.ComputerSystemCollection vmCollection = ComputerSystem.GetInstances(wmiQuery);
@@ -1112,7 +1119,7 @@ namespace HypervResource
             return null;
         }
 
-        public static List<string> GetVmElementNames()
+        public  List<string> GetVmElementNames()
         {
             List<string> result = new List<string>();
             ComputerSystem.ComputerSystemCollection vmCollection = ComputerSystem.GetInstances();
@@ -1129,7 +1136,7 @@ namespace HypervResource
             return result;
         }
 
-        public static ProcessorSettingData GetProcSettings(VirtualSystemSettingData vmSettings)
+        public  ProcessorSettingData GetProcSettings(VirtualSystemSettingData vmSettings)
         {
             // An ASSOCIATOR object provides the cross reference from the VirtualSystemSettingData and the 
             // ProcessorSettingData, but generated wrappers do not expose a ASSOCIATOR OF query as a method.
@@ -1154,7 +1161,7 @@ namespace HypervResource
             throw ex;
         }
 
-        public static MemorySettingData GetMemSettings(VirtualSystemSettingData vmSettings)
+        public  MemorySettingData GetMemSettings(VirtualSystemSettingData vmSettings)
         {
             // An ASSOCIATOR object provides the cross reference from the VirtualSystemSettingData and the 
             // MemorySettingData, but generated wrappers do not expose a ASSOCIATOR OF query as a method.
@@ -1179,7 +1186,7 @@ namespace HypervResource
             throw ex;
         }
 
-        public static ResourceAllocationSettingData GetDvdDriveSettings(VirtualSystemSettingData vmSettings)
+        public  ResourceAllocationSettingData GetDvdDriveSettings(VirtualSystemSettingData vmSettings)
         {
             var wmiObjCollection = GetResourceAllocationSettings(vmSettings);
 
@@ -1199,7 +1206,7 @@ namespace HypervResource
             throw ex;
         }
 
-        public static ResourceAllocationSettingData GetIDEControllerSettings(VirtualSystemSettingData vmSettings, string cntrllerAddr)
+        public  ResourceAllocationSettingData GetIDEControllerSettings(VirtualSystemSettingData vmSettings, string cntrllerAddr)
         {
             var wmiObjCollection = GetResourceAllocationSettings(vmSettings);
 
@@ -1228,7 +1235,7 @@ namespace HypervResource
         /// </summary>
         /// <param name="vmSettings"></param>
         /// <returns></returns>
-        public static ResourceAllocationSettingData.ResourceAllocationSettingDataCollection GetResourceAllocationSettings(VirtualSystemSettingData vmSettings)
+        public  ResourceAllocationSettingData.ResourceAllocationSettingDataCollection GetResourceAllocationSettings(VirtualSystemSettingData vmSettings)
         {
             // An ASSOCIATOR object provides the cross reference from the VirtualSystemSettingData and the 
             // ResourceAllocationSettingData, but generated wrappers do not expose a ASSOCIATOR OF query as a method.
@@ -1253,7 +1260,7 @@ namespace HypervResource
             throw ex;
         }
 
-        public static SwitchPort[] GetSwitchPorts(ComputerSystem vm)
+        public  SwitchPort[] GetSwitchPorts(ComputerSystem vm)
         {
             var virtSwitchMgmtSvc = GetVirtualSwitchManagementService();
             // Get NIC path
@@ -1274,7 +1281,7 @@ namespace HypervResource
         /// </summary>
         /// <param name="nic"></param>
         /// <returns></returns>
-        public static SwitchPort GetSwitchPort(SyntheticEthernetPort nic)
+        public  SwitchPort GetSwitchPort(SyntheticEthernetPort nic)
         {
             // An ASSOCIATOR object provides the cross reference between WMI objects, 
             // but generated wrappers do not expose a ASSOCIATOR OF query as a method.
@@ -1316,7 +1323,7 @@ namespace HypervResource
             return switchPort;
         }
 
-        public static SyntheticEthernetPortSettingData[] GetEthernetPorts(ComputerSystem vm)
+        public  SyntheticEthernetPortSettingData[] GetEthernetPorts(ComputerSystem vm)
         {
             // An ASSOCIATOR object provides the cross reference from the ComputerSettings and the 
             // SyntheticEthernetPortSettingData, via the VirtualSystemSettingData.
@@ -1343,7 +1350,7 @@ namespace HypervResource
             return results.ToArray();
         }
 
-        public static VirtualSystemSettingData GetVmSettings(ComputerSystem vm)
+        public  VirtualSystemSettingData GetVmSettings(ComputerSystem vm)
         {
             // An ASSOCIATOR object provides the cross reference from the ComputerSettings and the 
             // VirtualSystemSettingData, but generated wrappers do not expose a ASSOCIATOR OF query as a method.

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e0a51695/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 f95c337..6afa788 100755
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/WmiCallsV2.cs
@@ -30,7 +30,7 @@ using System.IO;
 
 namespace HypervResource
 {
-    public class WmiCallsV2
+    public class WmiCallsV2 : IWmiCallsV2
     {
         public static String CloudStackUserDataKey = "cloudstack-vm-userdata";
 
@@ -54,7 +54,7 @@ namespace HypervResource
         /// <summary>
         /// Returns ComputerSystem lacking any NICs and VOLUMEs
         /// </summary>
-        public static ComputerSystem AddUserData(ComputerSystem vm, string userData)
+        public ComputerSystem AddUserData(ComputerSystem vm, string userData)
         {
             // Obtain controller for Hyper-V virtualisation subsystem
             VirtualSystemManagementService vmMgmtSvc = GetVirtualisationSystemManagementService();
@@ -95,7 +95,7 @@ namespace HypervResource
         /// <summary>
         /// Returns ComputerSystem lacking any NICs and VOLUMEs
         /// </summary>
-        public static void DeleteHostKvpItem(ComputerSystem vm, string key)
+        public void DeleteHostKvpItem(ComputerSystem vm, string key)
         {
             // Obtain controller for Hyper-V virtualisation subsystem
             VirtualSystemManagementService vmMgmtSvc = GetVirtualisationSystemManagementService();
@@ -132,7 +132,7 @@ namespace HypervResource
             }
         }
 
-        public static VirtualSystemManagementService GetVirtualisationSystemManagementService()
+        public VirtualSystemManagementService GetVirtualisationSystemManagementService()
         {
             // VirtualSystemManagementService is a singleton, most anonymous way of lookup is by asking for the set
             // of local instances, which should be size 1.
@@ -182,7 +182,7 @@ namespace HypervResource
             logger.DebugFormat("WMI job succeeded: {0}, Elapsed={1}", jobObj.Description, jobObj.ElapsedTime);
         }
 
-        public static ComputerSystem GetComputerSystem(string displayName)
+        public ComputerSystem GetComputerSystem(string displayName)
         {
             var wmiQuery = String.Format("ElementName=\"{0}\"", displayName);
             ComputerSystem.ComputerSystemCollection vmCollection = ComputerSystem.GetInstances(wmiQuery);
@@ -195,7 +195,7 @@ namespace HypervResource
             return null;
         }
 
-        public static List<string> GetVmElementNames()
+        public List<string> GetVmElementNames()
         {
             List<string> result = new List<string>();
             ComputerSystem.ComputerSystemCollection vmCollection = ComputerSystem.GetInstances();
@@ -212,7 +212,7 @@ namespace HypervResource
             return result;
         }
 
-        public static string GetDefaultDataRoot()
+        public string GetDefaultDataRoot()
         {
             string defaultRootPath = null;
             VirtualSystemManagementServiceSettingData vs_mgmt_data = VirtualSystemManagementServiceSettingData.CreateInstance();
@@ -224,8 +224,9 @@ namespace HypervResource
 
             return defaultRootPath;
         }
-
-        public static VirtualSystemSettingData GetVmSettings(ComputerSystem vm)
+
+        public VirtualSystemSettingData GetVmSettings(ComputerSystem vm)
+
         {
             // An ASSOCIATOR object provides the cross reference from the ComputerSettings and the 
             // VirtualSystemSettingData, but generated wrappers do not expose a ASSOCIATOR OF query as a method.
@@ -256,7 +257,7 @@ namespace HypervResource
             throw ex;
         }
 
-        public static KvpExchangeComponentSettingData GetKvpSettings(VirtualSystemSettingData vmSettings)
+        public KvpExchangeComponentSettingData GetKvpSettings(VirtualSystemSettingData vmSettings)
         {
             // An ASSOCIATOR object provides the cross reference from the VirtualSystemSettingData and the 
             // KvpExchangeComponentSettingData, but generated wrappers do not expose a ASSOCIATOR OF query as a method.

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e0a51695/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/packages.config
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/packages.config b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/packages.config
index b0f2ace..4c538e4 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/packages.config
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/HypervResource/packages.config
@@ -4,4 +4,6 @@
   <package id="DotNetZip" version="1.9.1.8" targetFramework="net45" />
   <package id="log4net" version="2.0.0" targetFramework="net45" />
   <package id="Newtonsoft.Json" version="4.5.11" targetFramework="net45" />
+  <package id="NSubstitute" version="1.6.1.0" targetFramework="net45" />
+  <package id="xunit" version="1.9.2" targetFramework="net45" />
 </packages>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e0a51695/plugins/hypervisors/hyperv/DotNet/ServerResource/ServerResource.Tests/App.config
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/ServerResource.Tests/App.config b/plugins/hypervisors/hyperv/DotNet/ServerResource/ServerResource.Tests/App.config
index 1bf17d4..c959ccf 100644
--- a/plugins/hypervisors/hyperv/DotNet/ServerResource/ServerResource.Tests/App.config
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/ServerResource.Tests/App.config
@@ -1,23 +1,22 @@
-<?xml version="1.0" encoding="utf-8" ?>
+<?xml version="1.0" encoding="utf-8"?>
 <!-- 
     Note: Add entries to the App.config file for configuration settings
     that apply only to the Test project.
 -->
 <configuration>
   <configSections>
-    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
+    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
       <section name="CloudStack.Plugin.AgentShell.AgentSettings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
     </sectionGroup>
-    <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
+    <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
       <section name="CloudStack.Plugin.AgentShell.AgentSettings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
     </sectionGroup>
   </configSections>
-
   <appSettings>
-    </appSettings>
-    <connectionStrings>
-    </connectionStrings>
-
+    <add key="ClientSettingsProvider.ServiceUri" value="" />
+  </appSettings>
+  <connectionStrings>
+  </connectionStrings>
   <applicationSettings>
     <CloudStack.Plugin.AgentShell.AgentSettings>
       <setting name="cpus" serializeAs="String">
@@ -125,4 +124,16 @@
       </setting>
     </CloudStack.Plugin.AgentShell.AgentSettings>
   </userSettings>
-</configuration>
+  <system.web>
+    <membership defaultProvider="ClientAuthenticationMembershipProvider">
+      <providers>
+        <add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
+      </providers>
+    </membership>
+    <roleManager defaultProvider="ClientRoleProvider" enabled="true">
+      <providers>
+        <add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
+      </providers>
+    </roleManager>
+  </system.web>
+</configuration>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/e0a51695/plugins/hypervisors/hyperv/DotNet/ServerResource/ServerResource.Tests/HypervResourceController1Test.cs
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/ServerResource.Tests/HypervResourceController1Test.cs b/plugins/hypervisors/hyperv/DotNet/ServerResource/ServerResource.Tests/HypervResourceController1Test.cs
new file mode 100644
index 0000000..6f8aa4b
--- /dev/null
+++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/ServerResource.Tests/HypervResourceController1Test.cs
@@ -0,0 +1,298 @@
+// 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 CloudStack.Plugin.WmiWrappers.ROOT.VIRTUALIZATION;
+using System.Management;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json;
+using System.IO;
+using log4net;
+using HypervResource;
+using CloudStack.Plugin.AgentShell;
+using System.Collections.Generic;
+using NSubstitute;
+using System.Web.Http;
+using Xunit;
+
+namespace ServerResource.Tests
+{
+    public class HypervResourceController1Test
+    {
+
+        protected static string testCifsUrl = AgentSettings.Default.testCifsUrl;
+        protected static string testCifsPath = AgentSettings.Default.testCifsPath;
+        protected static String testPrimaryDataStoreHost = HypervResourceController.config.StorageIpAddress;
+        protected static String testS3TemplateName = AgentSettings.Default.testS3TemplateName;
+        protected static String testCifsTemplateName = AgentSettings.Default.testS3TemplateName;
+        protected static String testSystemVMTemplateName = AgentSettings.Default.testSystemVMTemplateName;
+        protected static String testSystemVMTemplateNameNoExt = AgentSettings.Default.testSystemVMTemplateNameNoExt;
+        protected static String testLocalStoreUUID = "5fe2bad3-d785-394e-9949-89786b8a63d2";
+        protected static String testLocalStorePath = Path.Combine(AgentSettings.Default.hyperv_plugin_root, "var", "test", "storagepool");
+        protected static String testSecondaryStoreLocalPath = Path.Combine(AgentSettings.Default.hyperv_plugin_root, "var", "test", "secondary");
+
+        // TODO: differentiate between NFS and HTTP template URLs.
+        protected static String testSampleTemplateUUID = "TestCopiedLocalTemplate.vhdx";
+        protected static String testSampleTemplateURL = testSampleTemplateUUID;
+
+        // test volumes are both a minimal size vhdx.  Changing the extension to .vhd makes on corrupt.
+        protected static String testSampleVolumeWorkingUUID = "TestVolumeLegit.vhdx";
+        protected static String testSampleVolumeCorruptUUID = "TestVolumeCorrupt.vhd";
+        protected static String testSampleVolumeTempUUID = "TestVolumeTemp.vhdx";
+        protected static String testSampleVolumeTempUUIDNoExt = "TestVolumeTemp";
+        protected static String testSampleVolumeWorkingURIJSON;
+        protected static String testSampleVolumeCorruptURIJSON;
+        protected static String testSampleVolumeTempURIJSON;
+
+        protected static String testSampleTemplateURLJSON;
+        protected static String testLocalStorePathJSON;
+
+        protected static IWmiCalls wmiCalls;
+
+
+        private static ILog s_logger = LogManager.GetLogger(typeof(HypervResourceController1Test));
+
+        /// <summary>
+        /// Test WmiCalls to which incoming HTTP POST requests are dispatched.
+        /// 
+        /// TODO: revise beyond first approximation
+        /// First approximation is a quick port of the existing Java tests for Hyper-V server resource.
+        /// A second approximation would use the AgentShell settings files directly.
+        /// A third approximation would look to invoke ServerResource methods via an HTTP request
+        /// </summary>
+
+        public HypervResourceController1Test()
+        {
+            wmiCalls = Substitute.For<IWmiCalls>();
+            //AgentService.ConfigServerResource();
+            HypervResourceController.config.PrivateMacAddress = AgentSettings.Default.private_mac_address;
+            HypervResourceController.config.PrivateNetmask = AgentSettings.Default.private_ip_netmask;
+            HypervResourceController.config.StorageIpAddress = HypervResourceController.config.PrivateIpAddress;
+            HypervResourceController.config.StorageMacAddress = HypervResourceController.config.PrivateMacAddress;
+            HypervResourceController.config.StorageNetmask = HypervResourceController.config.PrivateNetmask;
+
+
+            // Used to create existing StoragePool in preparation for the ModifyStoragePool
+            testLocalStoreUUID = AgentSettings.Default.local_storage_uuid.ToString();
+
+            // Make sure secondary store is available.
+            string fullPath = Path.GetFullPath(testSecondaryStoreLocalPath);
+            s_logger.Info("Test secondary storage in " + fullPath);
+            DirectoryInfo testSecondarStoreDir = new DirectoryInfo(fullPath);
+            if (!testSecondarStoreDir.Exists)
+            {
+                try
+                {
+                    testSecondarStoreDir.Create();
+                }
+                catch (System.IO.IOException ex)
+                {
+                    throw new NotImplementedException("Need to be able to create the folder " + testSecondarStoreDir.FullName + " failed due to " + ex.Message);
+                }
+            }
+
+            // Convert to secondary storage string to canonical path
+            testSecondaryStoreLocalPath = testSecondarStoreDir.FullName;
+            AgentSettings.Default.local_secondary_storage_path = testSecondaryStoreLocalPath;
+
+            // Make sure local primary storage is available
+            DirectoryInfo testPoolDir = new DirectoryInfo(testLocalStorePath);
+            //Assert.True(testPoolDir.Exists, "To simulate local file system Storage Pool, you need folder at " + testPoolDir.FullName);
+
+            // Convert to local primary storage string to canonical path
+            testLocalStorePath = testPoolDir.FullName;
+            AgentSettings.Default.local_storage_path = testLocalStorePath;
+
+            // Clean up old test files in local storage folder
+            FileInfo testVolWorks = new FileInfo(Path.Combine(testLocalStorePath, testSampleVolumeWorkingUUID));
+            // Assert.True(testVolWorks.Exists, "Create a working virtual disk at " + testVolWorks.FullName);           
+            
+            testSampleTemplateURLJSON = JsonConvert.SerializeObject(testSampleTemplateUUID);
+            s_logger.Info("Created " + testSampleTemplateURLJSON + " in local storage.");           
+
+
+            // Capture other JSON encoded paths
+            testSampleVolumeWorkingURIJSON = Newtonsoft.Json.JsonConvert.SerializeObject(testVolWorks.FullName);
+            testLocalStorePathJSON = JsonConvert.SerializeObject(testLocalStorePath);
+
+            // TODO: may need to initialise the server resource in future.
+            //    s_hypervresource.initialize();
+
+            // Verify sample template is in place storage pool
+            s_logger.Info("setUp complete, sample StoragePool at " + testLocalStorePathJSON
+                      + " sample template at " + testSampleTemplateURLJSON);
+        }
+
+        private String CreateTestDiskImageFromExistingImage(FileInfo srcFile,
+        String dstPath,
+        String dstFileName)
+        {
+            var newFullname = Path.Combine(dstPath, dstFileName);
+            var newFileInfo = new FileInfo(newFullname);
+            if (!newFileInfo.Exists)
+            {
+                newFileInfo = srcFile.CopyTo(newFullname);
+            }
+            newFileInfo.Refresh();
+            Assert.True(newFileInfo.Exists, "Attempted to create " + newFullname + " from " + newFileInfo.FullName);
+
+            return JsonConvert.SerializeObject(newFileInfo.FullName);
+        }
+        
+        [Fact]
+        public void TestCreateCommand()
+        {
+            var counter = 0;
+            wmiCalls.When(x => x.CreateDynamicVirtualHardDisk(Arg.Any<ulong>(), Arg.Any<String>())).Do(x => counter++);
+            // TODO: Need sample to update the test.
+            // Arrange
+            String createCmd = "{\"volId\":10,\"pool\":{\"id\":201,\"uuid\":\"" + testLocalStoreUUID + "\",\"host\":\"" + HypervResourceController.config.StorageIpAddress + "\"" +
+                            ",\"path\":" + testLocalStorePathJSON + ",\"port\":0,\"type\":\"Filesystem\"},\"diskCharacteristics\":{\"size\":0," +
+                            "\"tags\":[],\"type\":\"ROOT\",\"name\":\"ROOT-9\",\"useLocalStorage\":true,\"recreatable\":true,\"diskOfferingId\":11," +
+                            "\"volumeId\":10,\"hyperType\":\"Hyperv\"},\"templateUrl\":" + testSampleTemplateURLJSON + ",\"contextMap\":{},\"wait\":0}";
+            dynamic jsonCreateCmd = JsonConvert.DeserializeObject(createCmd);
+            HypervResourceController rsrcServer = new HypervResourceController();
+            rsrcServer.wmiCalls = wmiCalls;
+
+            Assert.True(Directory.Exists(testLocalStorePath), testLocalStorePath + " does not exist ");
+            string filePath = Path.Combine(testLocalStorePath, (string)JsonConvert.DeserializeObject(testSampleTemplateURLJSON));
+            Assert.True(File.Exists(filePath), "The template we make volumes from is missing from path " + filePath);
+            int fileCount = Directory.GetFiles(testLocalStorePath).Length;
+            s_logger.Debug(" test local store has " + fileCount + "files");
+
+            // Act
+            // Test requires there to be a template at the tempalteUrl, which is its location in the local file system.
+            dynamic jsonResult = rsrcServer.CreateCommand(jsonCreateCmd);
+            s_logger.Debug("CreateDynamicVirtualHardDisk method is called " + counter + " times");
+
+            //Assert.Equal(counter, 1);
+
+            JObject ansAsProperty2 = jsonResult[0];
+            dynamic ans = ansAsProperty2.GetValue(CloudStackTypes.CreateAnswer);
+            Assert.NotNull(ans);
+            Assert.True((bool)ans.result, "Failed to CreateCommand due to " + (string)ans.result);
+            Assert.Equal(Directory.GetFiles(testLocalStorePath).Length, fileCount + 1);
+            FileInfo newFile = new FileInfo((string)ans.volume.path);
+            Assert.True(newFile.Length > 0, "The new file should have a size greater than zero");
+            newFile.Delete();
+        }
+
+        /// <summary>
+        /// Possible additional tests:  place an ISO in the drive
+        /// </summary>        
+
+        [Fact]
+        public void TestStartCommand()
+        {
+            ComputerSystem system = new ComputerSystem();
+            wmiCalls.DeployVirtualMachine(Arg.Any<Object>(), Arg.Any<string>()).Returns(system);
+
+            // Arrange
+            HypervResourceController rsrcServer = new HypervResourceController();
+            rsrcServer.wmiCalls = wmiCalls;
+            String sample = getSampleStartCommand();
+
+
+            dynamic jsonStartCmd = JsonConvert.DeserializeObject(sample);
+
+            // Act
+            dynamic startAns = rsrcServer.StartCommand(jsonStartCmd);
+
+            // Assert
+            Assert.NotNull(startAns[0][CloudStackTypes.StartAnswer]);
+            Assert.True((bool)startAns[0][CloudStackTypes.StartAnswer].result, "StartCommand did not succeed " + startAns[0][CloudStackTypes.StartAnswer].details);
+
+            Assert.Null((string)startAns[0][CloudStackTypes.StartAnswer].details);            
+        }
+
+        [Fact]
+        public void TestStopCommand()
+        {
+            //string vmName = "Test VM";
+            var counter = 0;
+            wmiCalls.When(x => x.DestroyVm(Arg.Any<Object>())).Do(x => counter++);
+
+            // Arrange
+            HypervResourceController rsrcServer = new HypervResourceController();
+            rsrcServer.wmiCalls = wmiCalls;
+
+            String sampleStop = "{\"isProxy\":false,\"vmName\":\"i-2-17-VM\",\"contextMap\":{},\"wait\":0}";
+            dynamic jsonStopCmd = JsonConvert.DeserializeObject(sampleStop);
+
+            // Act
+            dynamic stopAns = rsrcServer.StopCommand(jsonStopCmd);
+
+            // Assert VM is gone!
+            Assert.NotNull(stopAns[0][CloudStackTypes.StopAnswer]);
+            Assert.True((bool)stopAns[0][CloudStackTypes.StopAnswer].result, "StopCommand did not succeed " + stopAns[0][CloudStackTypes.StopAnswer].details);
+
+            Assert.Null((string)stopAns[0][CloudStackTypes.StopAnswer].details);
+            Assert.Equal<int>(counter, 1);
+        }
+
+        public static String getSamplePrimaryDataStoreInfo()
+        {
+            String samplePrimaryDataStoreInfo =
+            "{\"org.apache.cloudstack.storage.to.PrimaryDataStoreTO\":" +
+                "{\"uuid\":\"" + testLocalStoreUUID + "\"," +
+                "\"id\":201," +
+                "\"host\":\"" + testPrimaryDataStoreHost + "\"," +
+                "\"type\":\"Filesystem\"," +  // Not used in PrimaryDataStoreTO
+                "\"poolType\":\"Filesystem\"," +  // Not used in PrimaryDataStoreTO
+                "\"path\":" + testLocalStorePathJSON + "," +
+                "\"port\":0}" +
+            "}";
+            return samplePrimaryDataStoreInfo;
+        }
+
+        public static String getSampleVolumeObjectTO()
+        {
+            String sampleVolumeObjectTO =
+                    "{\"org.apache.cloudstack.storage.to.VolumeObjectTO\":" +
+                        "{\"uuid\":\"19ae8e67-cb2c-4ab4-901e-e0b864272b59\"," +
+                        "\"volumeType\":\"ROOT\"," +
+                        "\"format\":\"VHDX\"," +
+                        "\"dataStore\":" + getSamplePrimaryDataStoreInfo() + "," +
+                        "\"name\":\"" + testSampleVolumeTempUUIDNoExt + "\"," +
+                        "\"size\":52428800," +
+                        "\"volumeId\":10," +
+                //                            "\"vmName\":\"i-3-5-VM\"," +  // TODO: do we have to fill in the vmName?
+                        "\"accountId\":3,\"id\":10}" +
+                    "}";  // end of destTO 
+            return sampleVolumeObjectTO;
+        }
+
+        public static String getSampleStartCommand()
+        {
+            String sample = "{\"vm\":{\"id\":17,\"name\":\"i-2-17-VM\",\"type\":\"User\",\"cpus\":1,\"speed\":500," +
+                                "\"minRam\":536870912,\"maxRam\":536870912,\"arch\":\"x86_64\"," +
+                                "\"os\":\"CentOS 6.0 (64-bit)\",\"bootArgs\":\"\",\"rebootOnCrash\":false," +
+                                "\"enableHA\":false,\"limitCpuUse\":false,\"vncPassword\":\"31f82f29aff646eb\"," +
+                                "\"params\":{},\"uuid\":\"8b030b6a-0243-440a-8cc5-45d08815ca11\"" +
+                            ",\"disks\":[" +
+                               "{\"data\":" + getSampleVolumeObjectTO() + ",\"diskSeq\":0,\"type\":\"ROOT\"}," +
+                               "{\"diskSeq\":1,\"type\":\"ISO\"}" +
+                            "]," +
+                            "\"nics\":[" +
+                                    "{\"deviceId\":0,\"networkRateMbps\":100,\"defaultNic\":true,\"uuid\":\"99cb4813-23af-428c-a87a-2d1899be4f4b\"," +
+                                    "\"ip\":\"10.1.1.67\",\"netmask\":\"255.255.255.0\",\"gateway\":\"10.1.1.1\"," +
+                                    "\"mac\":\"02:00:51:2c:00:0e\",\"dns1\":\"4.4.4.4\",\"broadcastType\":\"Vlan\",\"type\":\"Guest\"," +
+                                    "\"broadcastUri\":\"vlan://261\",\"isolationUri\":\"vlan://261\",\"isSecurityGroupEnabled\":false}" +
+                            "]},\"contextMap\":{},\"wait\":0}";
+            return sample;
+        }        
+    }
+}