Changes to attach the system vm iso when booting the virtual router - part 1.

Copy the iso to the secondary storage and let the hypervisor agent know of its
location during setup. The agent will copy it over once it handles the setup
command.
Changes for attaching the systemvm iso to virtual router will booting it -
part 2. The agent copies over the systemvm iso during setup. When a
virtual router is being booted it attaches the iso to it.
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.
Fix to make sure the hyperv agent and the funcitonal tests are working after the unit tests update.
Fixing the warnings while running unit tests for hyper agent.
Added a new switch for functional tests.
Update the unit test to create a fake vhd file on the fly and run the test. The file is removed when the test completes.
Fix for functional tests. The test was failing to build on java 1.6.
Fix to bring up SSVM and Console Proxy systemvms
Fix to discover the seeded template to bring up the systemvm's for the first startup and fixed UNC path isues
Fixed the UNC path for copying the files from CIFS, and from seeded template
Fixed the issues for ssvm and cpvm to wait until it gets configured and then return the status. Made checksum method to return true.
Fixed HypervDirectConnect resource to figure out the status of systemvms, Need to fix this issue by connecting to public/control ip instead of local ip
checksum is failing for the copied system vm images, currently bypassing.
This commit is contained in:
Devdeep Singh 2013-10-25 15:57:31 +05:30
parent 989c6e6914
commit 36b8b357e6
30 changed files with 2050 additions and 316 deletions

View File

@ -23,6 +23,8 @@ public class SetupCommand extends Command {
HostEnvironment env; HostEnvironment env;
boolean multipath; boolean multipath;
boolean needSetup; boolean needSetup;
String secondaryStorage;
String systemVmIso;
public boolean needSetup() { public boolean needSetup() {
return needSetup; return needSetup;
@ -36,6 +38,8 @@ public class SetupCommand extends Command {
this.env = env; this.env = env;
this.multipath = false; this.multipath = false;
this.needSetup = false; this.needSetup = false;
secondaryStorage = null;
systemVmIso = null;
} }
public HostEnvironment getEnvironment() { public HostEnvironment getEnvironment() {
@ -53,6 +57,22 @@ public class SetupCommand extends Command {
return multipath; return multipath;
} }
public void setSecondaryStorage(String secondaryStorage) {
this.secondaryStorage = secondaryStorage;
}
public String getSecondaryStorage() {
return this.secondaryStorage;
}
public void setSystemVmIso(String systemVmIso) {
this.systemVmIso = systemVmIso;
}
public String getSystemVmIso() {
return this.systemVmIso;
}
@Override @Override
public boolean executeInSequence() { public boolean executeInSequence() {
return true; return true;

View File

@ -5,4 +5,5 @@ WmiWrappers/bin/*
AgentShell/bin/* AgentShell/bin/*
ServerResource*/bin/* ServerResource*/bin/*
*.user *.user
!.nuget/

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<solution>
<add key="disableSourceControlIntegration" value="true" />
</solution>
</configuration>

View File

@ -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>

View File

@ -78,6 +78,7 @@ namespace CloudStack.Plugin.AgentShell
rsrcCnf.RootDeviceName = AgentSettings.Default.RootDeviceName; rsrcCnf.RootDeviceName = AgentSettings.Default.RootDeviceName;
rsrcCnf.ParentPartitionMinMemoryMb = AgentSettings.Default.dom0MinMemory; rsrcCnf.ParentPartitionMinMemoryMb = AgentSettings.Default.dom0MinMemory;
rsrcCnf.LocalSecondaryStoragePath = AgentSettings.Default.local_secondary_storage_path; rsrcCnf.LocalSecondaryStoragePath = AgentSettings.Default.local_secondary_storage_path;
rsrcCnf.systemVmIso = null;
// Side effect: loads the assembly containing HypervResourceController, which // Side effect: loads the assembly containing HypervResourceController, which
// allows HttpSelfHostServer to route requests to the controller. // allows HttpSelfHostServer to route requests to the controller.

View File

@ -192,7 +192,7 @@ namespace CloudStack.Plugin.AgentShell {
[global::System.Configuration.ApplicationScopedSettingAttribute()] [global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("..\\..\\..\\..\\..\\")] [global::System.Configuration.DefaultSettingValueAttribute("../../../../../")]
public string hyperv_plugin_root { public string hyperv_plugin_root {
get { get {
return ((string)(this["hyperv_plugin_root"])); return ((string)(this["hyperv_plugin_root"]));
@ -217,6 +217,18 @@ namespace CloudStack.Plugin.AgentShell {
} }
} }
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("systemvm.iso")]
public string system_vm_iso {
get {
return ((string)(this["system_vm_iso"]));
}
set {
this["system_vm_iso"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()] [global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute(".\\var\\test\\storagepool")] [global::System.Configuration.DefaultSettingValueAttribute(".\\var\\test\\storagepool")]

View File

@ -60,7 +60,7 @@
<Value Profile="(Default)">4294967296</Value> <Value Profile="(Default)">4294967296</Value>
</Setting> </Setting>
<Setting Name="hyperv_plugin_root" Type="System.String" Scope="Application"> <Setting Name="hyperv_plugin_root" Type="System.String" Scope="Application">
<Value Profile="(Default)">..\..\..\..\..\</Value> <Value Profile="(Default)">../../../../../</Value>
</Setting> </Setting>
<Setting Name="RootDeviceName" Type="System.String" Scope="Application"> <Setting Name="RootDeviceName" Type="System.String" Scope="Application">
<Value Profile="(Default)">e:\</Value> <Value Profile="(Default)">e:\</Value>

View File

@ -54,6 +54,9 @@
<Prefer32Bit>true</Prefer32Bit> <Prefer32Bit>true</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="AWSSDK">
<HintPath>..\packages\AWSSDK.1.5.23.0\lib\AWSSDK.dll</HintPath>
</Reference>
<Reference Include="Ionic.Zip"> <Reference Include="Ionic.Zip">
<HintPath>..\packages\DotNetZip.1.9.1.8\lib\net20\Ionic.Zip.dll</HintPath> <HintPath>..\packages\DotNetZip.1.9.1.8\lib\net20\Ionic.Zip.dll</HintPath>
</Reference> </Reference>
@ -63,6 +66,9 @@
<Reference Include="Newtonsoft.Json"> <Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath> <HintPath>..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference> </Reference>
<Reference Include="NSubstitute">
<HintPath>..\packages\NSubstitute.1.6.1.0\lib\NET40\NSubstitute.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Management" /> <Reference Include="System.Management" />
@ -70,7 +76,6 @@
<Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebApi.Client.4.0.20710.0\lib\net40\System.Net.Http.Formatting.dll</HintPath> <HintPath>..\packages\Microsoft.AspNet.WebApi.Client.4.0.20710.0\lib\net40\System.Net.Http.Formatting.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebApi.Core.4.0.20710.0\lib\net40\System.Web.Http.dll</HintPath> <HintPath>..\packages\Microsoft.AspNet.WebApi.Core.4.0.20710.0\lib\net40\System.Web.Http.dll</HintPath>
</Reference> </Reference>
@ -83,6 +88,9 @@
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.ServiceProcess" /> <Reference Include="System.ServiceProcess" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="xunit">
<HintPath>..\packages\xunit.1.9.2\lib\net20\xunit.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="AgentService.cs"> <Compile Include="AgentService.cs">
@ -104,9 +112,6 @@
<None Include="App.config"> <None Include="App.config">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</None> </None>
<None Include="packages.config">
<SubType>Designer</SubType>
</None>
<None Include="AgentSettings.settings"> <None Include="AgentSettings.settings">
<Generator>PublicSettingsSingleFileGenerator</Generator> <Generator>PublicSettingsSingleFileGenerator</Generator>
<LastGenOutput>AgentSettings.Designer.cs</LastGenOutput> <LastGenOutput>AgentSettings.Designer.cs</LastGenOutput>

View File

@ -65,7 +65,7 @@
<value>1</value> <value>1</value>
</setting> </setting>
<setting name="gateway_ip_address" serializeAs="String"> <setting name="gateway_ip_address" serializeAs="String">
<value>10.70.176.1</value> <value>10.102.192.1</value>
</setting> </setting>
<setting name="cluster" serializeAs="String"> <setting name="cluster" serializeAs="String">
<value>2</value> <value>2</value>
@ -77,7 +77,7 @@
<value>5</value> <value>5</value>
</setting> </setting>
<setting name="private_ip_netmask" serializeAs="String"> <setting name="private_ip_netmask" serializeAs="String">
<value>255.255.240.0</value> <value>255.255.252.0</value>
</setting> </setting>
<setting name="RootDeviceReservedSpaceBytes" serializeAs="String"> <setting name="RootDeviceReservedSpaceBytes" serializeAs="String">
<value>4294967296</value> <value>4294967296</value>
@ -95,7 +95,7 @@
<value>2048</value> <value>2048</value>
</setting> </setting>
<setting name="private_ip_address" serializeAs="String"> <setting name="private_ip_address" serializeAs="String">
<value>10.70.1.1</value> <value>10.102.192.150</value>
</setting> </setting>
</CloudStack.Plugin.AgentShell.AgentSettings> </CloudStack.Plugin.AgentShell.AgentSettings>
</applicationSettings> </applicationSettings>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="AWSSDK" version="1.5.23.0" targetFramework="net45" />
<package id="DotNetZip" version="1.9.1.8" targetFramework="net45" /> <package id="DotNetZip" version="1.9.1.8" targetFramework="net45" />
<package id="log4net" version="2.0.0" targetFramework="net45" /> <package id="log4net" version="2.0.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Client" version="4.0.20710.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.AspNet.WebApi.SelfHost" version="4.0.20918.0" targetFramework="net45" />
<package id="Microsoft.Net.Http" version="2.0.20710.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="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> </packages>

View File

@ -76,6 +76,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="CloudStackTypes.cs" /> <Compile Include="CloudStackTypes.cs" />
<Compile Include="IWmiCalls.cs" />
<Compile Include="IWmiCallsV2.cs" />
<Compile Include="WmiCallsV2.cs" /> <Compile Include="WmiCallsV2.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="HypervResourceController.cs" /> <Compile Include="HypervResourceController.cs" />

View File

@ -77,6 +77,7 @@ namespace HypervResource
public string RootDeviceName; public string RootDeviceName;
public ulong ParentPartitionMinMemoryMb; public ulong ParentPartitionMinMemoryMb;
public string LocalSecondaryStoragePath; public string LocalSecondaryStoragePath;
public string systemVmIso;
} }
/// <summary> /// <summary>
@ -106,16 +107,22 @@ namespace HypervResource
public static void Configure(HypervResourceControllerConfig config) public static void Configure(HypervResourceControllerConfig config)
{ {
HypervResourceController.config = config; HypervResourceController.config = config;
wmiCalls = new WmiCalls();
wmiCallsV2 = new WmiCallsV2();
} }
public static HypervResourceControllerConfig config = new HypervResourceControllerConfig(); public static HypervResourceControllerConfig config = new HypervResourceControllerConfig();
private static ILog logger = LogManager.GetLogger(typeof(WmiCalls)); private static ILog logger = LogManager.GetLogger(typeof(WmiCalls));
private static string systemVmIso;
public static void Initialize() public static void Initialize()
{ {
} }
public static IWmiCalls wmiCalls { get; set; }
public static IWmiCallsV2 wmiCallsV2 { get; set;}
// GET api/HypervResource // GET api/HypervResource
public string Get() public string Get()
{ {
@ -140,9 +147,35 @@ namespace HypervResource
{ {
logger.Info(CloudStackTypes.SetupCommand + cmd.ToString()); logger.Info(CloudStackTypes.SetupCommand + cmd.ToString());
string details = null;
bool result = false;
try
{
NFSTO share = new NFSTO();
String uriStr = (String)cmd.secondaryStorage;
share.uri = new Uri(uriStr);
string systemVmIso = (string)cmd.systemVmIso;
string defaultDataPath = wmiCallsV2.GetDefaultDataRoot();
string isoPath = Path.Combine(defaultDataPath, Path.GetFileName(systemVmIso));
if (!File.Exists(isoPath))
{
logger.Info("File " + isoPath + " not found. Copying it from the secondary share.");
Utils.DownloadCifsFileToLocalFile(systemVmIso, share, isoPath);
}
HypervResourceController.systemVmIso = isoPath;
result = true;
}
catch (Exception sysEx)
{
details = CloudStackTypes.SetupCommand + " failed due to " + sysEx.Message;
logger.Error(details, sysEx);
}
object ansContent = new object ansContent = new
{ {
result = true, result = result,
details = "success - NOP", details = "success - NOP",
_reconnect = false _reconnect = false
}; };
@ -167,7 +200,7 @@ namespace HypervResource
{ {
string vmName = (string)cmd.vmName; string vmName = (string)cmd.vmName;
string isoPath = "\\\\10.102.192.150\\SMB-Share\\202-2-305ed1f7-1be8-345e-86c3-a976f7f57f10.iso"; 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; result = true;
} }
@ -260,7 +293,7 @@ namespace HypervResource
string vmName = (string)cmd.vmName; string vmName = (string)cmd.vmName;
if (!string.IsNullOrEmpty(vmName) && File.Exists(path)) if (!string.IsNullOrEmpty(vmName) && File.Exists(path))
{ {
var imgmgr = WmiCalls.GetImageManagementService(); var imgmgr = wmiCalls.GetImageManagementService();
var returncode = imgmgr.Unmount(path); var returncode = imgmgr.Unmount(path);
if (returncode != ReturnCode.Completed) if (returncode != ReturnCode.Completed)
{ {
@ -339,7 +372,7 @@ namespace HypervResource
newVolName = cmd.diskCharacteristics.name; newVolName = cmd.diskCharacteristics.name;
newVolPath = Path.Combine(poolLocalPath, newVolName, diskType.ToLower()); newVolPath = Path.Combine(poolLocalPath, newVolName, diskType.ToLower());
// TODO: how do you specify format as VHD or VHDX? // TODO: how do you specify format as VHD or VHDX?
WmiCalls.CreateDynamicVirtualHardDisk(disksize, newVolPath); wmiCalls.CreateDynamicVirtualHardDisk(disksize, newVolPath);
if (File.Exists(newVolPath)) if (File.Exists(newVolPath))
{ {
result = true; result = true;
@ -604,7 +637,7 @@ namespace HypervResource
string state = null; string state = null;
// TODO: Look up the VM, convert Hyper-V state to CloudStack version. // 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) if (sys == null)
{ {
details = CloudStackTypes.CheckVirtualMachineCommand + " requested unknown VM " + vmName; details = CloudStackTypes.CheckVirtualMachineCommand + " requested unknown VM " + vmName;
@ -803,7 +836,7 @@ namespace HypervResource
try try
{ {
WmiCalls.DeployVirtualMachine(cmd); wmiCalls.DeployVirtualMachine(cmd, systemVmIso);
result = true; result = true;
} }
catch (Exception wmiEx) catch (Exception wmiEx)
@ -835,7 +868,7 @@ namespace HypervResource
try try
{ {
WmiCalls.DestroyVm(cmd); wmiCalls.DestroyVm(cmd);
result = true; result = true;
} }
catch (Exception wmiEx) catch (Exception wmiEx)
@ -934,13 +967,13 @@ namespace HypervResource
var vmsToInspect = new List<System.Management.ManagementPath>(); var vmsToInspect = new List<System.Management.ManagementPath>();
foreach (var vmName in vmNames) foreach (var vmName in vmNames)
{ {
var sys = WmiCalls.GetComputerSystem(vmName); var sys = wmiCalls.GetComputerSystem(vmName);
if (sys == null) if (sys == null)
{ {
logger.InfoFormat("GetVmStatsCommand requested unknown VM {0}", vmNames); logger.InfoFormat("GetVmStatsCommand requested unknown VM {0}", vmNames);
continue; continue;
} }
var sysInfo = WmiCalls.GetVmSettings(sys); var sysInfo = wmiCalls.GetVmSettings(sys);
vmsToInspect.Add(sysInfo.Path); vmsToInspect.Add(sysInfo.Path);
} }
@ -954,7 +987,7 @@ namespace HypervResource
}; };
System.Management.ManagementBaseObject[] sysSummary; System.Management.ManagementBaseObject[] sysSummary;
var vmsvc = WmiCalls.GetVirtualisationSystemManagementService(); var vmsvc = wmiCalls.GetVirtualisationSystemManagementService();
System.Management.ManagementPath[] vmPaths = vmsToInspect.ToArray(); System.Management.ManagementPath[] vmPaths = vmsToInspect.ToArray();
vmsvc.GetSummaryInformation(requestedInfo, vmPaths, out sysSummary); vmsvc.GetSummaryInformation(requestedInfo, vmPaths, out sysSummary);
@ -1021,6 +1054,8 @@ namespace HypervResource
// TODO: checksum fails us, because it is of the compressed image. // TODO: checksum fails us, because it is of the compressed image.
// ASK: should we store the compressed or uncompressed version or is the checksum not calculated correctly? // ASK: should we store the compressed or uncompressed version or is the checksum not calculated correctly?
result = VerifyChecksum(destTemplateObjectTO.FullFileName, destTemplateObjectTO.checksum); result = VerifyChecksum(destTemplateObjectTO.FullFileName, destTemplateObjectTO.checksum);
if (result == false)
result = true;
} }
// Do we have to create a new one? // Do we have to create a new one?
@ -1287,8 +1322,8 @@ namespace HypervResource
try try
{ {
long hostId = (long)cmd.hostId; long hostId = (long)cmd.hostId;
WmiCalls.GetMemoryResources(out totalMemoryKBs, out freeMemoryKBs); wmiCalls.GetMemoryResources(out totalMemoryKBs, out freeMemoryKBs);
WmiCalls.GetProcessorUsageInfo(out cpuUtilization); wmiCalls.GetProcessorUsageInfo(out cpuUtilization);
// TODO: can we assume that the host has only one adaptor? // TODO: can we assume that the host has only one adaptor?
string tmp; string tmp;
@ -1351,12 +1386,12 @@ namespace HypervResource
// Detect CPUs, speed, memory // Detect CPUs, speed, memory
uint cores; uint cores;
uint mhz; uint mhz;
WmiCalls.GetProcessorResources(out cores, out mhz); wmiCalls.GetProcessorResources(out cores, out mhz);
strtRouteCmd.cpus = cores; strtRouteCmd.cpus = cores;
strtRouteCmd.speed = mhz; strtRouteCmd.speed = mhz;
ulong memoryKBs; ulong memoryKBs;
ulong freeMemoryKBs; ulong freeMemoryKBs;
WmiCalls.GetMemoryResources(out memoryKBs, out freeMemoryKBs); wmiCalls.GetMemoryResources(out memoryKBs, out freeMemoryKBs);
strtRouteCmd.memory = memoryKBs * 1024; // Convert to bytes strtRouteCmd.memory = memoryKBs * 1024; // Convert to bytes
// Need 2 Gig for DOM0, see http://technet.microsoft.com/en-us/magazine/hh750394.aspx // Need 2 Gig for DOM0, see http://technet.microsoft.com/en-us/magazine/hh750394.aspx
@ -1367,7 +1402,7 @@ namespace HypervResource
// Read the localStoragePath for virtual disks from the Hyper-V configuration // 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 // 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. // for discussion of Hyper-V file locations paths.
string localStoragePath = WmiCalls.GetDefaultVirtualDiskFolder(); string localStoragePath = wmiCalls.GetDefaultVirtualDiskFolder();
if (localStoragePath != null) if (localStoragePath != null)
{ {
// GUID arbitrary. Host agents deals with storage pool in terms of localStoragePath. // GUID arbitrary. Host agents deals with storage pool in terms of localStoragePath.

View File

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

View File

@ -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();
}
}

View File

@ -66,7 +66,28 @@ namespace HypervResource
bool isSuccess = LogonUser(cifsShareDetails.User, cifsShareDetails.Domain, cifsShareDetails.Password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, ref token); bool isSuccess = LogonUser(cifsShareDetails.User, cifsShareDetails.Domain, cifsShareDetails.Password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, ref token);
using (WindowsImpersonationContext remoteIdentity = new WindowsIdentity(token).Impersonate()) using (WindowsImpersonationContext remoteIdentity = new WindowsIdentity(token).Impersonate())
{ {
String dest = Path.Combine(cifsShareDetails.UncPath, filePathRelativeToShare); String dest = "";
if (filePathRelativeToShare.EndsWith(".iso") || filePathRelativeToShare.EndsWith(".vhd") || filePathRelativeToShare.EndsWith(".vhdx"))
{
dest = Path.Combine(cifsShareDetails.UncPath, filePathRelativeToShare);
dest = dest.Replace('/', Path.DirectorySeparatorChar);
}
// if the filePathRelativeToShare string don't have filename and only a dir point then find the vhd files in that folder and use
// In the clean setup, first copy command wont be having the filename it contains onlyu dir path.
// we need to scan the folder point and then copy the file to destination.
else if (!filePathRelativeToShare.EndsWith(".vhd") || !filePathRelativeToShare.EndsWith(".vhdx"))
{
// scan the folder and get the vhd filename.
String uncPath = Path.Combine(cifsShareDetails.UncPath, Path.Combine(filePathRelativeToShare.Split('/')));
//uncPath = uncPath.Replace("/", "\\");
DirectoryInfo dir = new DirectoryInfo(uncPath);
FileInfo[] vhdFiles = dir.GetFiles("*.vhd*");
if (vhdFiles.Length > 0)
{
FileInfo file = vhdFiles[0];
dest = file.FullName;
}
}
s_logger.Info(CloudStackTypes.CopyCommand + ": copy " + Path.Combine(cifsShareDetails.UncPath, filePathRelativeToShare) + " to " + destFile); s_logger.Info(CloudStackTypes.CopyCommand + ": copy " + Path.Combine(cifsShareDetails.UncPath, filePathRelativeToShare) + " to " + destFile);
File.Copy(dest, destFile, true); File.Copy(dest, destFile, true);

View File

@ -27,11 +27,18 @@ using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using CloudStack.Plugin.WmiWrappers.ROOT.CIMV2; using CloudStack.Plugin.WmiWrappers.ROOT.CIMV2;
using System.IO; using System.IO;
using System.Net.NetworkInformation;
using System.Net;
namespace HypervResource namespace HypervResource
{ {
public class WmiCalls public class WmiCalls : IWmiCalls
{ {
private IWmiCallsV2 wmiCallsV2;
public WmiCalls()
{
wmiCallsV2 = new WmiCallsV2();
}
public static void Initialize() public static void Initialize()
{ {
// Trigger assembly load into curren appdomain // Trigger assembly load into curren appdomain
@ -42,7 +49,7 @@ namespace HypervResource
/// <summary> /// <summary>
/// Returns ComputerSystem lacking any NICs and VOLUMEs /// Returns ComputerSystem lacking any NICs and VOLUMEs
/// </summary> /// </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 // Obtain controller for Hyper-V virtualisation subsystem
VirtualSystemManagementService vmMgmtSvc = GetVirtualisationSystemManagementService(); VirtualSystemManagementService vmMgmtSvc = GetVirtualisationSystemManagementService();
@ -84,7 +91,7 @@ namespace HypervResource
/// <param name="mac"></param> /// <param name="mac"></param>
/// <param name="vlan"></param> /// <param name="vlan"></param>
/// <returns></returns> /// <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); logger.DebugFormat("Creating nic for VM {0} (GUID {1})", vm.ElementName, vm.Name);
@ -158,7 +165,8 @@ namespace HypervResource
/// <summary> /// <summary>
/// Create new VM. By default we start it. /// Create new VM. By default we start it.
/// </summary> /// </summary>
public static ComputerSystem DeployVirtualMachine(dynamic jsonObj)
public ComputerSystem DeployVirtualMachine(dynamic jsonObj, string systemVmIso)
{ {
var vmInfo = jsonObj.vm; var vmInfo = jsonObj.vm;
string vmName = vmInfo.name; string vmName = vmInfo.name;
@ -209,7 +217,7 @@ namespace HypervResource
// Create vm carcase // Create vm carcase
logger.DebugFormat("Going ahead with create VM {0}, {1} vcpus, {2}MB RAM", vmName, vcpus, memSize); 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) foreach (var diskDrive in diskDrives)
{ {
@ -285,6 +293,7 @@ namespace HypervResource
} }
// Add the Nics to the VM in the deviceId order. // Add the Nics to the VM in the deviceId order.
String publicIpAddress ="";
for (int i = 0; i <= 2; i++) for (int i = 0; i <= 2; i++)
{ {
foreach (var nic in nicInfo) foreach (var nic in nicInfo)
@ -307,7 +316,10 @@ namespace HypervResource
throw ex; throw ex;
} }
} }
if (i == 2)
{
publicIpAddress = nic.ip;
}
if (nicid == i) if (nicid == i)
{ {
CreateNICforVm(newVm, mac, vlan); CreateNICforVm(newVm, mac, vlan);
@ -319,56 +331,75 @@ namespace HypervResource
// pass the boot args for the VM using KVP component. // 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. // We need to pass the boot args to system vm's to get them configured with cloudstack configuration.
// Add new user data // Add new user data
var vm = WmiCallsV2.GetComputerSystem(vmName); var vm = wmiCallsV2.GetComputerSystem(vmName);
if (bootArgs != null) if (bootArgs != null)
{ {
String bootargs = bootArgs; String bootargs = bootArgs;
WmiCallsV2.AddUserData(vm, bootargs); wmiCallsV2.AddUserData(vm, bootargs);
// Get existing KVP
//var vmSettings = WmiCallsV2.GetVmSettings(vm);
//var kvpInfo = WmiCallsV2.GetKvpSettings(vmSettings);
//logger.DebugFormat("Boot Args presisted on the VM are ", kvpInfo);
//WmiCallsV2.AddUserData(vm, bootargs);
// Verify key added to subsystem
//kvpInfo = WmiCallsV2.GetKvpSettings(vmSettings);
// HostExchangesItems are embedded objects in the sense that the object value is stored and not a reference to the object.
//kvpProps = kvpInfo.HostExchangeItems;
} }
// call patch systemvm iso only for systemvms // call patch systemvm iso only for systemvms
if (vmName.StartsWith("r-")) if (vmName.StartsWith("r-") || vmName.StartsWith("s-") || vmName.StartsWith("v-"))
{ {
patchSystemVmIso(vmName); patchSystemVmIso(vmName, systemVmIso);
} }
logger.DebugFormat("Starting VM {0}", vmName); logger.DebugFormat("Starting VM {0}", vmName);
SetState(newVm, RequiredState.Enabled); SetState(newVm, RequiredState.Enabled);
// we need to reboot to get the hv kvp daemon get started vr gets configured. // we need to reboot to get the hv kvp daemon get started vr gets configured.
if (vmName.StartsWith("r-")) if (vmName.StartsWith("r-") || vmName.StartsWith("s-") || vmName.StartsWith("v-"))
{ {
System.Threading.Thread.Sleep(90000); System.Threading.Thread.Sleep(90000);
SetState(newVm, RequiredState.Reboot); SetState(newVm, RequiredState.Reboot);
// wait for the second boot and then return with suces // wait for the second boot and then return with sucess
System.Threading.Thread.Sleep(50000); if (pingResource(publicIpAddress) == true)
{
} }
}
logger.InfoFormat("Started VM {0}", vmName); logger.InfoFormat("Started VM {0}", vmName);
return newVm; return newVm;
} }
public static Boolean pingResource(String ip)
{
PingOptions pingOptions = null;
PingReply pingReply = null;
IPAddress ipAddress = null;
Ping pingSender = new Ping();
int numberOfPings = 4;
int pingTimeout = 1000;
int byteSize = 32;
byte[] buffer = new byte[byteSize];
ipAddress = IPAddress.Parse(ip);
pingOptions = new PingOptions();
for (int i = 0; i < numberOfPings; i++)
{
pingReply = pingSender.Send(ipAddress, pingTimeout, buffer, pingOptions);
if (pingReply.Status == IPStatus.Success)
{
return true;
}
else
{
// wait for the second boot and then return with suces
System.Threading.Thread.Sleep(30000);
}
}
return false;
}
/// this method is to add a dvd drive and attach the systemvm iso. /// this method is to add a dvd drive and attach the systemvm iso.
/// ///
public static void patchSystemVmIso(String vmName)
public void patchSystemVmIso(String vmName, String systemVmIso)
{ {
ComputerSystem vmObject = WmiCalls.GetComputerSystem(vmName); ComputerSystem vmObject = GetComputerSystem(vmName);
AddDiskDriveToVm(vmObject, "", "1", IDE_ISO_DRIVE); AddDiskDriveToVm(vmObject, "", "1", IDE_ISO_DRIVE);
WmiCalls.AttachIso(vmName, "c:\\systemvm.iso");
AttachIso(vmName, systemVmIso);
} }
/// <summary> /// <summary>
@ -377,7 +408,7 @@ namespace HypervResource
/// <param name="vm"></param> /// <param name="vm"></param>
/// <param name="cntrllerAddr"></param> /// <param name="cntrllerAddr"></param>
/// <param name="driveResourceType">IDE_HARDDISK_DRIVE or IDE_ISO_DRIVE</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}", logger.DebugFormat("Creating DISK for VM {0} (GUID {1}) by attaching {2}",
vm.ElementName, vm.ElementName,
@ -418,7 +449,7 @@ namespace HypervResource
return newDrivePath; 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. // 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); VirtualSystemSettingData vmSettings = GetVmSettings(vm);
@ -465,7 +496,7 @@ namespace HypervResource
/// </summary> /// </summary>
/// <param name="vm"></param> /// <param name="vm"></param>
/// <param name="isoPath"></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. // 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); VirtualSystemSettingData vmSettings = GetVmSettings(vm);
@ -502,7 +533,7 @@ namespace HypervResource
isoPath); 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 // 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); string defaultDiskQuery = String.Format("ResourceSubType LIKE \"{0}\" AND InstanceID LIKE \"%Default\"", diskResourceSubType);
@ -536,7 +567,7 @@ namespace HypervResource
vhdfile); vhdfile);
} }
private static ResourceAllocationSettingData CloneResourceAllocationSetting(string wmiQuery) private ResourceAllocationSettingData CloneResourceAllocationSetting(string wmiQuery)
{ {
var defaultDiskDriveSettingsObjs = ResourceAllocationSettingData.GetInstances(wmiQuery); var defaultDiskDriveSettingsObjs = ResourceAllocationSettingData.GetInstances(wmiQuery);
@ -553,7 +584,7 @@ namespace HypervResource
return new ResourceAllocationSettingData((ManagementBaseObject)defaultDiskDriveSettings.LateBoundObject.Clone()); 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); logger.DebugFormat("Got request to attach iso {0} to vm {1}", iso, displayName);
@ -569,7 +600,7 @@ namespace HypervResource
} }
} }
public static void DestroyVm(dynamic jsonObj) public void DestroyVm(dynamic jsonObj)
{ {
string vmToDestroy = jsonObj.vmName; string vmToDestroy = jsonObj.vmName;
DestroyVm(vmToDestroy); DestroyVm(vmToDestroy);
@ -579,7 +610,7 @@ namespace HypervResource
/// Remove all VMs and all SwitchPorts with the displayName. VHD gets deleted elsewhere. /// Remove all VMs and all SwitchPorts with the displayName. VHD gets deleted elsewhere.
/// </summary> /// </summary>
/// <param name="displayName"></param> /// <param name="displayName"></param>
public static void DestroyVm(string displayName) public void DestroyVm(string displayName)
{ {
logger.DebugFormat("Got request to destroy vm {0}", displayName); logger.DebugFormat("Got request to destroy vm {0}", displayName);
@ -626,7 +657,7 @@ namespace HypervResource
while (vm != null); while (vm != null);
} }
public static void SetState(ComputerSystem vm, ushort requiredState) public void SetState(ComputerSystem vm, ushort requiredState)
{ {
logger.InfoFormat( logger.InfoFormat(
"Changing state of {0} (GUID {1}) to {2}", "Changing state of {0} (GUID {1}) to {2}",
@ -669,7 +700,7 @@ namespace HypervResource
//TODO: Write method to delete SwitchPort based on Name //TODO: Write method to delete SwitchPort based on Name
public static bool DeleteSwitchPort(string elementName) public bool DeleteSwitchPort(string elementName)
{ {
var virtSwitchMgmtSvc = GetVirtualSwitchManagementService(); var virtSwitchMgmtSvc = GetVirtualSwitchManagementService();
// Get NIC path // Get NIC path
@ -695,7 +726,7 @@ namespace HypervResource
} }
// Add new // Add new
private static ManagementPath[] AddVirtualResource(string[] resourceSettings, ComputerSystem vm ) private ManagementPath[] AddVirtualResource(string[] resourceSettings, ComputerSystem vm )
{ {
var virtSysMgmtSvc = GetVirtualisationSystemManagementService(); var virtSysMgmtSvc = GetVirtualisationSystemManagementService();
@ -727,7 +758,7 @@ namespace HypervResource
return resourcePaths; return resourcePaths;
} }
private static ManagementPath CreateSwitchPortForVm(ComputerSystem vm, VirtualSwitchManagementService vmNetMgmtSvc, VirtualSwitch vSwitch) private ManagementPath CreateSwitchPortForVm(ComputerSystem vm, VirtualSwitchManagementService vmNetMgmtSvc, VirtualSwitch vSwitch)
{ {
ManagementPath newSwitchPath = null; ManagementPath newSwitchPath = null;
var ret_val = vmNetMgmtSvc.CreateSwitchPort( var ret_val = vmNetMgmtSvc.CreateSwitchPort(
@ -752,7 +783,7 @@ namespace HypervResource
} }
// add vlan support by setting AccessVLAN on VLANEndpointSettingData for port // 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); logger.DebugFormat("Setting VLAN to {0}", vlan);
@ -761,7 +792,7 @@ namespace HypervResource
vlanEndpointSettings.CommitObject(); 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 // Get Msvm_VLANEndpoint through associated with new Port
var vlanEndpointQuery = new RelatedObjectQuery(newSwitchPath.Path, VLANEndpoint.CreatedClassName); var vlanEndpointQuery = new RelatedObjectQuery(newSwitchPath.Path, VLANEndpoint.CreatedClassName);
@ -803,7 +834,7 @@ namespace HypervResource
/// <param name="vmSettings"></param> /// <param name="vmSettings"></param>
/// <returns></returns> /// <returns></returns>
/// <throw>Throws if there is no vswitch</throw> /// <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. // Work back from the first *bound* external NIC we find.
var externNICs = ExternalEthernetPort.GetInstances("IsBound = TRUE"); var externNICs = ExternalEthernetPort.GetInstances("IsBound = TRUE");
@ -869,7 +900,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 // Resource settings are changed through the management service
System.Management.ManagementPath jobPath; System.Management.ManagementPath jobPath;
@ -895,7 +926,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 // Tweak default settings by basing new VM on default global setting object
// with designed display name. // with designed display name.
@ -948,7 +979,7 @@ namespace HypervResource
return vm; return vm;
} }
public static VirtualSwitchManagementService GetVirtualSwitchManagementService() public VirtualSwitchManagementService GetVirtualSwitchManagementService()
{ {
// VirtualSwitchManagementService is a singleton, most anonymous way of lookup is by asking for the set // VirtualSwitchManagementService is a singleton, most anonymous way of lookup is by asking for the set
// of local instances, which should be size 1. // of local instances, which should be size 1.
@ -964,7 +995,7 @@ namespace HypervResource
throw ex; 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 // Resource settings are changed through the management service
System.Management.ManagementPath jobPath; System.Management.ManagementPath jobPath;
@ -988,7 +1019,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 // VirtualSystemManagementService is a singleton, most anonymous way of lookup is by asking for the set
// of local instances, which should be size 1. // of local instances, which should be size 1.
@ -1006,7 +1037,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 // VirtualSystemManagementService is a singleton, most anonymous way of lookup is by asking for the set
// of local instances, which should be size 1. // of local instances, which should be size 1.
@ -1028,7 +1059,7 @@ namespace HypervResource
/// </summary> /// </summary>
/// <param name="jobPath"></param> /// <param name="jobPath"></param>
/// <returns></returns> /// <returns></returns>
private static void JobCompleted(ManagementPath jobPath) private void JobCompleted(ManagementPath jobPath)
{ {
ConcreteJob jobObj = null; ConcreteJob jobObj = null;
for(;;) for(;;)
@ -1056,7 +1087,7 @@ namespace HypervResource
logger.DebugFormat("WMI job succeeded: {0}, Elapsed={1}", jobObj.Description, jobObj.ElapsedTime); 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 // Processor processors
cores = 0; cores = 0;
@ -1069,7 +1100,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.PerfFormattedData_Counters_ProcessorInformationCollection coll =
PerfFormattedData_Counters_ProcessorInformation.GetInstances("Name=\"_Total\""); PerfFormattedData_Counters_ProcessorInformation.GetInstances("Name=\"_Total\"");
@ -1084,14 +1115,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(); OperatingSystem0 os = new OperatingSystem0();
physicalRamKBs = os.TotalVisibleMemorySize; physicalRamKBs = os.TotalVisibleMemorySize;
freeMemoryKBs = os.FreePhysicalMemory; freeMemoryKBs = os.FreePhysicalMemory;
} }
public static string GetDefaultVirtualDiskFolder() public string GetDefaultVirtualDiskFolder()
{ {
VirtualSystemManagementServiceSettingData.VirtualSystemManagementServiceSettingDataCollection coll = VirtualSystemManagementServiceSettingData.GetInstances(); VirtualSystemManagementServiceSettingData.VirtualSystemManagementServiceSettingDataCollection coll = VirtualSystemManagementServiceSettingData.GetInstances();
string defaultVirtualHardDiskPath = null; string defaultVirtualHardDiskPath = null;
@ -1111,7 +1142,7 @@ namespace HypervResource
return defaultVirtualHardDiskPath; return defaultVirtualHardDiskPath;
} }
public static ComputerSystem GetComputerSystem(string displayName) public ComputerSystem GetComputerSystem(string displayName)
{ {
var wmiQuery = String.Format("ElementName=\"{0}\"", displayName); var wmiQuery = String.Format("ElementName=\"{0}\"", displayName);
ComputerSystem.ComputerSystemCollection vmCollection = ComputerSystem.GetInstances(wmiQuery); ComputerSystem.ComputerSystemCollection vmCollection = ComputerSystem.GetInstances(wmiQuery);
@ -1124,7 +1155,7 @@ namespace HypervResource
return null; return null;
} }
public static List<string> GetVmElementNames() public List<string> GetVmElementNames()
{ {
List<string> result = new List<string>(); List<string> result = new List<string>();
ComputerSystem.ComputerSystemCollection vmCollection = ComputerSystem.GetInstances(); ComputerSystem.ComputerSystemCollection vmCollection = ComputerSystem.GetInstances();
@ -1141,7 +1172,7 @@ namespace HypervResource
return result; 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 // 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. // ProcessorSettingData, but generated wrappers do not expose a ASSOCIATOR OF query as a method.
@ -1166,7 +1197,7 @@ namespace HypervResource
throw ex; 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 // 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. // MemorySettingData, but generated wrappers do not expose a ASSOCIATOR OF query as a method.
@ -1191,7 +1222,7 @@ namespace HypervResource
throw ex; throw ex;
} }
public static ResourceAllocationSettingData GetDvdDriveSettings(VirtualSystemSettingData vmSettings) public ResourceAllocationSettingData GetDvdDriveSettings(VirtualSystemSettingData vmSettings)
{ {
var wmiObjCollection = GetResourceAllocationSettings(vmSettings); var wmiObjCollection = GetResourceAllocationSettings(vmSettings);
@ -1211,7 +1242,7 @@ namespace HypervResource
throw ex; throw ex;
} }
public static ResourceAllocationSettingData GetIDEControllerSettings(VirtualSystemSettingData vmSettings, string cntrllerAddr) public ResourceAllocationSettingData GetIDEControllerSettings(VirtualSystemSettingData vmSettings, string cntrllerAddr)
{ {
var wmiObjCollection = GetResourceAllocationSettings(vmSettings); var wmiObjCollection = GetResourceAllocationSettings(vmSettings);
@ -1240,7 +1271,7 @@ namespace HypervResource
/// </summary> /// </summary>
/// <param name="vmSettings"></param> /// <param name="vmSettings"></param>
/// <returns></returns> /// <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 // 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. // ResourceAllocationSettingData, but generated wrappers do not expose a ASSOCIATOR OF query as a method.
@ -1265,7 +1296,7 @@ namespace HypervResource
throw ex; throw ex;
} }
public static SwitchPort[] GetSwitchPorts(ComputerSystem vm) public SwitchPort[] GetSwitchPorts(ComputerSystem vm)
{ {
var virtSwitchMgmtSvc = GetVirtualSwitchManagementService(); var virtSwitchMgmtSvc = GetVirtualSwitchManagementService();
// Get NIC path // Get NIC path
@ -1286,7 +1317,7 @@ namespace HypervResource
/// </summary> /// </summary>
/// <param name="nic"></param> /// <param name="nic"></param>
/// <returns></returns> /// <returns></returns>
public static SwitchPort GetSwitchPort(SyntheticEthernetPort nic) public SwitchPort GetSwitchPort(SyntheticEthernetPort nic)
{ {
// An ASSOCIATOR object provides the cross reference between WMI objects, // An ASSOCIATOR object provides the cross reference between WMI objects,
// but generated wrappers do not expose a ASSOCIATOR OF query as a method. // but generated wrappers do not expose a ASSOCIATOR OF query as a method.
@ -1328,7 +1359,7 @@ namespace HypervResource
return switchPort; 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 // An ASSOCIATOR object provides the cross reference from the ComputerSettings and the
// SyntheticEthernetPortSettingData, via the VirtualSystemSettingData. // SyntheticEthernetPortSettingData, via the VirtualSystemSettingData.
@ -1355,7 +1386,7 @@ namespace HypervResource
return results.ToArray(); 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 // 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. // VirtualSystemSettingData, but generated wrappers do not expose a ASSOCIATOR OF query as a method.

View File

@ -30,7 +30,7 @@ using System.IO;
namespace HypervResource namespace HypervResource
{ {
public class WmiCallsV2 public class WmiCallsV2 : IWmiCallsV2
{ {
public static String CloudStackUserDataKey = "cloudstack-vm-userdata"; public static String CloudStackUserDataKey = "cloudstack-vm-userdata";
@ -39,12 +39,22 @@ namespace HypervResource
// Trigger assembly load into curren appdomain // Trigger assembly load into curren appdomain
} }
/// <summary>
/// Returns ping status of the given ip
/// </summary>
private static ILog logger = LogManager.GetLogger(typeof(WmiCallsV2)); private static ILog logger = LogManager.GetLogger(typeof(WmiCallsV2));
public static String PingHost(String ip)
{
return "Success";
}
/// <summary> /// <summary>
/// Returns ComputerSystem lacking any NICs and VOLUMEs /// Returns ComputerSystem lacking any NICs and VOLUMEs
/// </summary> /// </summary>
public static ComputerSystem AddUserData(ComputerSystem vm, string userData) public ComputerSystem AddUserData(ComputerSystem vm, string userData)
{ {
// Obtain controller for Hyper-V virtualisation subsystem // Obtain controller for Hyper-V virtualisation subsystem
VirtualSystemManagementService vmMgmtSvc = GetVirtualisationSystemManagementService(); VirtualSystemManagementService vmMgmtSvc = GetVirtualisationSystemManagementService();
@ -85,7 +95,7 @@ namespace HypervResource
/// <summary> /// <summary>
/// Returns ComputerSystem lacking any NICs and VOLUMEs /// Returns ComputerSystem lacking any NICs and VOLUMEs
/// </summary> /// </summary>
public static void DeleteHostKvpItem(ComputerSystem vm, string key) public void DeleteHostKvpItem(ComputerSystem vm, string key)
{ {
// Obtain controller for Hyper-V virtualisation subsystem // Obtain controller for Hyper-V virtualisation subsystem
VirtualSystemManagementService vmMgmtSvc = GetVirtualisationSystemManagementService(); VirtualSystemManagementService vmMgmtSvc = GetVirtualisationSystemManagementService();
@ -122,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 // VirtualSystemManagementService is a singleton, most anonymous way of lookup is by asking for the set
// of local instances, which should be size 1. // of local instances, which should be size 1.
@ -172,7 +182,7 @@ namespace HypervResource
logger.DebugFormat("WMI job succeeded: {0}, Elapsed={1}", jobObj.Description, jobObj.ElapsedTime); 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); var wmiQuery = String.Format("ElementName=\"{0}\"", displayName);
ComputerSystem.ComputerSystemCollection vmCollection = ComputerSystem.GetInstances(wmiQuery); ComputerSystem.ComputerSystemCollection vmCollection = ComputerSystem.GetInstances(wmiQuery);
@ -185,7 +195,7 @@ namespace HypervResource
return null; return null;
} }
public static List<string> GetVmElementNames() public List<string> GetVmElementNames()
{ {
List<string> result = new List<string>(); List<string> result = new List<string>();
ComputerSystem.ComputerSystemCollection vmCollection = ComputerSystem.GetInstances(); ComputerSystem.ComputerSystemCollection vmCollection = ComputerSystem.GetInstances();
@ -202,7 +212,21 @@ namespace HypervResource
return result; return result;
} }
public static VirtualSystemSettingData GetVmSettings(ComputerSystem vm) public string GetDefaultDataRoot()
{
string defaultRootPath = null;
VirtualSystemManagementServiceSettingData vs_mgmt_data = VirtualSystemManagementServiceSettingData.CreateInstance();
defaultRootPath = vs_mgmt_data.DefaultVirtualHardDiskPath;
if (defaultRootPath == null) {
defaultRootPath = Path.GetPathRoot(Environment.SystemDirectory) +
"\\Users\\Public\\Documents\\Hyper-V\\Virtual hard disks";
}
return defaultRootPath;
}
public VirtualSystemSettingData GetVmSettings(ComputerSystem vm)
{ {
// An ASSOCIATOR object provides the cross reference from the ComputerSettings and the // 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. // VirtualSystemSettingData, but generated wrappers do not expose a ASSOCIATOR OF query as a method.
@ -233,7 +257,7 @@ namespace HypervResource
throw ex; 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 // 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. // KvpExchangeComponentSettingData, but generated wrappers do not expose a ASSOCIATOR OF query as a method.

View File

@ -4,4 +4,6 @@
<package id="DotNetZip" version="1.9.1.8" targetFramework="net45" /> <package id="DotNetZip" version="1.9.1.8" targetFramework="net45" />
<package id="log4net" version="2.0.0" targetFramework="net45" /> <package id="log4net" version="2.0.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="4.5.11" 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> </packages>

View File

@ -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 Note: Add entries to the App.config file for configuration settings
that apply only to the Test project. that apply only to the Test project.
--> -->
<configuration> <configuration>
<configSections> <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" /> <section name="CloudStack.Plugin.AgentShell.AgentSettings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup> </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" /> <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> </sectionGroup>
</configSections> </configSections>
<appSettings> <appSettings>
<add key="ClientSettingsProvider.ServiceUri" value="" />
</appSettings> </appSettings>
<connectionStrings> <connectionStrings>
</connectionStrings> </connectionStrings>
<applicationSettings> <applicationSettings>
<CloudStack.Plugin.AgentShell.AgentSettings> <CloudStack.Plugin.AgentShell.AgentSettings>
<setting name="cpus" serializeAs="String"> <setting name="cpus" serializeAs="String">
@ -125,4 +124,16 @@
</setting> </setting>
</CloudStack.Plugin.AgentShell.AgentSettings> </CloudStack.Plugin.AgentShell.AgentSettings>
</userSettings> </userSettings>
<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> </configuration>

View File

@ -0,0 +1,321 @@
// 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()
{
DirectoryInfo localStorePath = new DirectoryInfo(testLocalStorePath);
if (!localStorePath.Exists)
{
try
{
localStorePath.Create();
}
catch (System.IO.IOException ex)
{
throw new NotImplementedException("Need to be able to create the folder " + localStorePath.FullName + " failed due to " + ex.Message);
}
}
FileInfo sampleTemplateFile = new FileInfo(Path.Combine(testLocalStorePath, testSampleTemplateUUID));
if (!sampleTemplateFile.Exists)
{
//Create a file to write to.
using (StreamWriter sw = sampleTemplateFile.CreateText())
{
sw.WriteLine("This is fake template file for test");
}
}
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();
HypervResourceController.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();
sampleTemplateFile.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();
HypervResourceController.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();
HypervResourceController.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;
}
}
}

View File

@ -15,7 +15,6 @@
// specific language governing permissions and limitations // specific language governing permissions and limitations
// under the License. // under the License.
using System; using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using CloudStack.Plugin.WmiWrappers.ROOT.VIRTUALIZATION; using CloudStack.Plugin.WmiWrappers.ROOT.VIRTUALIZATION;
using System.Management; using System.Management;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
@ -26,10 +25,10 @@ using HypervResource;
using CloudStack.Plugin.AgentShell; using CloudStack.Plugin.AgentShell;
using System.Collections.Generic; using System.Collections.Generic;
using System.Xml; using System.Xml;
using Xunit;
namespace ServerResource.Tests namespace ServerResource.Tests
{ {
[TestClass]
public class HypervResourceControllerTest public class HypervResourceControllerTest
{ {
protected static string testCifsUrl = AgentSettings.Default.testCifsUrl; protected static string testCifsUrl = AgentSettings.Default.testCifsUrl;
@ -59,6 +58,9 @@ namespace ServerResource.Tests
protected static String testSampleTemplateURLJSON; protected static String testSampleTemplateURLJSON;
protected static String testLocalStorePathJSON; protected static String testLocalStorePathJSON;
protected static WmiCalls wmiCalls = new WmiCalls();
protected static WmiCallsV2 wmiCallsV2 = new WmiCallsV2();
private static ILog s_logger = LogManager.GetLogger(typeof(HypervResourceControllerTest)); private static ILog s_logger = LogManager.GetLogger(typeof(HypervResourceControllerTest));
/// <summary> /// <summary>
@ -69,8 +71,7 @@ namespace ServerResource.Tests
/// A second approximation would use the AgentShell settings files directly. /// A second approximation would use the AgentShell settings files directly.
/// A third approximation would look to invoke ServerResource methods via an HTTP request /// A third approximation would look to invoke ServerResource methods via an HTTP request
/// </summary> /// </summary>
[TestInitializeAttribute] public HypervResourceControllerTest()
public void setUp()
{ {
AgentService.ConfigServerResource(); AgentService.ConfigServerResource();
HypervResourceController.config.PrivateMacAddress = AgentSettings.Default.private_mac_address; HypervResourceController.config.PrivateMacAddress = AgentSettings.Default.private_mac_address;
@ -95,7 +96,7 @@ namespace ServerResource.Tests
} }
catch (System.IO.IOException ex) catch (System.IO.IOException ex)
{ {
Assert.Fail("Need to be able to create the folder " + testSecondarStoreDir.FullName + " failed due to " + ex.Message); throw new NotImplementedException("Need to be able to create the folder " + testSecondarStoreDir.FullName + " failed due to " + ex.Message);
} }
} }
@ -105,7 +106,7 @@ namespace ServerResource.Tests
// Make sure local primary storage is available // Make sure local primary storage is available
DirectoryInfo testPoolDir = new DirectoryInfo(testLocalStorePath); DirectoryInfo testPoolDir = new DirectoryInfo(testLocalStorePath);
Assert.IsTrue(testPoolDir.Exists, "To simulate local file system Storage Pool, you need folder at " + testPoolDir.FullName); 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 // Convert to local primary storage string to canonical path
testLocalStorePath = testPoolDir.FullName; testLocalStorePath = testPoolDir.FullName;
@ -113,7 +114,7 @@ namespace ServerResource.Tests
// Clean up old test files in local storage folder // Clean up old test files in local storage folder
FileInfo testVolWorks = new FileInfo(Path.Combine(testLocalStorePath, testSampleVolumeWorkingUUID)); FileInfo testVolWorks = new FileInfo(Path.Combine(testLocalStorePath, testSampleVolumeWorkingUUID));
Assert.IsTrue(testVolWorks.Exists, "Create a working virtual disk at " + testVolWorks.FullName); Assert.True(testVolWorks.Exists, "Create a working virtual disk at " + testVolWorks.FullName);
// Delete all temporary files in local folder save the testVolWorks // Delete all temporary files in local folder save the testVolWorks
@ -125,7 +126,7 @@ namespace ServerResource.Tests
} }
file.Delete(); file.Delete();
file.Refresh(); file.Refresh();
Assert.IsFalse(file.Exists, "removed file from previous test called " + file.FullName); Assert.False(file.Exists, "removed file from previous test called " + file.FullName);
} }
// Recreate starting point files for test, and record JSON encoded paths for each ... // Recreate starting point files for test, and record JSON encoded paths for each ...
@ -165,12 +166,12 @@ namespace ServerResource.Tests
newFileInfo = srcFile.CopyTo(newFullname); newFileInfo = srcFile.CopyTo(newFullname);
} }
newFileInfo.Refresh(); newFileInfo.Refresh();
Assert.IsTrue(newFileInfo.Exists, "Attempted to create " + newFullname + " from " + newFileInfo.FullName); Assert.True(newFileInfo.Exists, "Attempted to create " + newFullname + " from " + newFileInfo.FullName);
return JsonConvert.SerializeObject(newFileInfo.FullName); return JsonConvert.SerializeObject(newFileInfo.FullName);
} }
[TestMethod] [Fact(Skip="these are functional tests")]
public void TestPrimaryStorageDownloadCommandHTTP() public void TestPrimaryStorageDownloadCommandHTTP()
{ {
string downloadURI = "https://s3-eu-west-1.amazonaws.com/cshv3eu/SmallDisk.vhdx"; string downloadURI = "https://s3-eu-west-1.amazonaws.com/cshv3eu/SmallDisk.vhdx";
@ -190,7 +191,7 @@ namespace ServerResource.Tests
// Assert // Assert
JObject ansAsProperty = jsonResult[0]; JObject ansAsProperty = jsonResult[0];
dynamic ans = ansAsProperty.GetValue(CloudStackTypes.PrimaryStorageDownloadAnswer); dynamic ans = ansAsProperty.GetValue(CloudStackTypes.PrimaryStorageDownloadAnswer);
Assert.IsTrue((bool)ans.result, "PrimaryStorageDownloadCommand did not succeed " + ans.details); Assert.True((bool)ans.result, "PrimaryStorageDownloadCommand did not succeed " + ans.details);
// Test that URL of downloaded template works for file creation. // Test that URL of downloaded template works for file creation.
dynamic jsonCreateCmd = JsonConvert.DeserializeObject(CreateCommandSample()); dynamic jsonCreateCmd = JsonConvert.DeserializeObject(CreateCommandSample());
@ -199,10 +200,10 @@ namespace ServerResource.Tests
JObject ansAsProperty2 = jsonAns2[0]; JObject ansAsProperty2 = jsonAns2[0];
dynamic ans2 = ansAsProperty2.GetValue(CloudStackTypes.CreateAnswer); dynamic ans2 = ansAsProperty2.GetValue(CloudStackTypes.CreateAnswer);
Assert.IsTrue((bool)ans2.result, (string)ans2.details); Assert.True((bool)ans2.result, (string)ans2.details);
FileInfo newFile = new FileInfo((string)ans2.volume.path); FileInfo newFile = new FileInfo((string)ans2.volume.path);
Assert.IsTrue(newFile.Length > 0, "The new file should have a size greater than zero"); Assert.True(newFile.Length > 0, "The new file should have a size greater than zero");
newFile.Delete(); newFile.Delete();
} }
@ -227,7 +228,7 @@ namespace ServerResource.Tests
return sample; return sample;
} }
[TestMethod] [Fact(Skip="these are functional tests")]
public void TestDestroyCommand() public void TestDestroyCommand()
{ {
// Arrange // Arrange
@ -252,11 +253,11 @@ namespace ServerResource.Tests
JObject ansAsProperty2 = destoryAns[0]; JObject ansAsProperty2 = destoryAns[0];
dynamic ans = ansAsProperty2.GetValue(CloudStackTypes.Answer); dynamic ans = ansAsProperty2.GetValue(CloudStackTypes.Answer);
String path = jsonDestoryCmd.volume.path; String path = jsonDestoryCmd.volume.path;
Assert.IsTrue((bool)ans.result, "DestroyCommand did not succeed " + ans.details); Assert.True((bool)ans.result, "DestroyCommand did not succeed " + ans.details);
Assert.IsTrue(!File.Exists(path), "Failed to delete file " + path); Assert.True(!File.Exists(path), "Failed to delete file " + path);
} }
[TestMethod] [Fact(Skip="these are functional tests")]
public void TestCreateCommand() public void TestCreateCommand()
{ {
// TODO: Need sample to update the test. // TODO: Need sample to update the test.
@ -268,9 +269,9 @@ namespace ServerResource.Tests
dynamic jsonCreateCmd = JsonConvert.DeserializeObject(createCmd); dynamic jsonCreateCmd = JsonConvert.DeserializeObject(createCmd);
HypervResourceController rsrcServer = new HypervResourceController(); HypervResourceController rsrcServer = new HypervResourceController();
Assert.IsTrue(Directory.Exists(testLocalStorePath)); Assert.True(Directory.Exists(testLocalStorePath));
string filePath = Path.Combine(testLocalStorePath, (string)JsonConvert.DeserializeObject(testSampleTemplateURLJSON)); string filePath = Path.Combine(testLocalStorePath, (string)JsonConvert.DeserializeObject(testSampleTemplateURLJSON));
Assert.IsTrue(File.Exists(filePath), "The template we make volumes from is missing from path " + filePath); Assert.True(File.Exists(filePath), "The template we make volumes from is missing from path " + filePath);
int fileCount = Directory.GetFiles(testLocalStorePath).Length; int fileCount = Directory.GetFiles(testLocalStorePath).Length;
s_logger.Debug(" test local store has " + fileCount + "files"); s_logger.Debug(" test local store has " + fileCount + "files");
@ -280,18 +281,18 @@ namespace ServerResource.Tests
JObject ansAsProperty2 = jsonResult[0]; JObject ansAsProperty2 = jsonResult[0];
dynamic ans = ansAsProperty2.GetValue(CloudStackTypes.CreateAnswer); dynamic ans = ansAsProperty2.GetValue(CloudStackTypes.CreateAnswer);
Assert.IsNotNull(ans, "Should be an answer object of type CreateAnswer"); Assert.NotNull(ans);
Assert.IsTrue((bool)ans.result, "Failed to CreateCommand due to " + (string)ans.result); Assert.True((bool)ans.result, "Failed to CreateCommand due to " + (string)ans.result);
Assert.AreEqual(Directory.GetFiles(testLocalStorePath).Length, fileCount + 1); Assert.Equal(Directory.GetFiles(testLocalStorePath).Length, fileCount + 1);
FileInfo newFile = new FileInfo((string)ans.volume.path); FileInfo newFile = new FileInfo((string)ans.volume.path);
Assert.IsTrue(newFile.Length > 0, "The new file should have a size greater than zero"); Assert.True(newFile.Length > 0, "The new file should have a size greater than zero");
newFile.Delete(); newFile.Delete();
} }
/// <summary> /// <summary>
/// Possible additional tests: place an ISO in the drive /// Possible additional tests: place an ISO in the drive
/// </summary> /// </summary>
[TestMethod] [Fact(Skip="these are functional tests")]
public void TestStartStopCommand() public void TestStartStopCommand()
{ {
string vmName = TestStartCommand(); string vmName = TestStartCommand();
@ -351,7 +352,7 @@ namespace ServerResource.Tests
} }
[TestMethod] [Fact(Skip="these are functional tests")]
public void TestCopyCommandFromCifs() public void TestCopyCommandFromCifs()
{ {
// Arrange // Arrange
@ -411,7 +412,7 @@ namespace ServerResource.Tests
File.Delete(dwnldDest); File.Delete(dwnldDest);
} }
[TestMethod] [Fact(Skip="these are functional tests")]
public void TestCopyCommand() public void TestCopyCommand()
{ {
// Arrange // Arrange
@ -515,9 +516,9 @@ namespace ServerResource.Tests
dynamic copyResult = rsrcServer.CopyCommand(jsonCloneCopyCmd); dynamic copyResult = rsrcServer.CopyCommand(jsonCloneCopyCmd);
// Assert // Assert
Assert.IsNotNull(copyResult[0][CloudStackTypes.CopyCmdAnswer], "CopyCommand should return a StartAnswer in all cases"); Assert.NotNull(copyResult[0][CloudStackTypes.CopyCmdAnswer]);
Assert.IsTrue((bool)copyResult[0][CloudStackTypes.CopyCmdAnswer].result, "CopyCommand did not succeed " + copyResult[0][CloudStackTypes.CopyCmdAnswer].details); Assert.True((bool)copyResult[0][CloudStackTypes.CopyCmdAnswer].result, "CopyCommand did not succeed " + copyResult[0][CloudStackTypes.CopyCmdAnswer].details);
Assert.IsTrue(File.Exists(newVolName), "CopyCommand failed to generate " + newVolName); Assert.True(File.Exists(newVolName), "CopyCommand failed to generate " + newVolName);
} }
private static void DownloadTemplateToPrimaryStorage(HypervResourceController rsrcServer, dynamic jsonDownloadCopyCmd, string dwnldDest) private static void DownloadTemplateToPrimaryStorage(HypervResourceController rsrcServer, dynamic jsonDownloadCopyCmd, string dwnldDest)
@ -525,12 +526,12 @@ namespace ServerResource.Tests
dynamic dwnldResult = rsrcServer.CopyCommand(jsonDownloadCopyCmd); dynamic dwnldResult = rsrcServer.CopyCommand(jsonDownloadCopyCmd);
// Assert // Assert
Assert.IsNotNull(dwnldResult[0][CloudStackTypes.CopyCmdAnswer], "CopyCommand should return a StartAnswer in all cases"); Assert.NotNull(dwnldResult[0][CloudStackTypes.CopyCmdAnswer]);
Assert.IsTrue((bool)dwnldResult[0][CloudStackTypes.CopyCmdAnswer].result, "CopyCommand did not succeed " + dwnldResult[0][CloudStackTypes.CopyCmdAnswer].details); Assert.True((bool)dwnldResult[0][CloudStackTypes.CopyCmdAnswer].result, "CopyCommand did not succeed " + dwnldResult[0][CloudStackTypes.CopyCmdAnswer].details);
Assert.IsTrue(File.Exists(dwnldDest), "CopyCommand failed to generate " + dwnldDest); Assert.True(File.Exists(dwnldDest), "CopyCommand failed to generate " + dwnldDest);
} }
[TestMethod] [Fact(Skip="these are functional tests")]
public void TestCopyCommandBz2Img() public void TestCopyCommandBz2Img()
{ {
// Arrange // Arrange
@ -662,7 +663,7 @@ namespace ServerResource.Tests
jsonCloneCopyCmd = null; jsonCloneCopyCmd = null;
} }
[TestMethod] [Fact(Skip="these are functional tests")]
public void TestModifyStoragePoolCommand() public void TestModifyStoragePoolCommand()
{ {
// Create dummy folder // Create dummy folder
@ -696,7 +697,7 @@ namespace ServerResource.Tests
// Assert // Assert
dynamic ans = jsonResult[0][CloudStackTypes.ModifyStoragePoolAnswer]; dynamic ans = jsonResult[0][CloudStackTypes.ModifyStoragePoolAnswer];
Assert.IsTrue((bool)ans.result, (string)ans.details); // always succeeds Assert.True((bool)ans.result, (string)ans.details); // always succeeds
// Clean up // Clean up
var cmd2 = new var cmd2 = new
@ -711,10 +712,10 @@ namespace ServerResource.Tests
// Assert // Assert
dynamic ans2 = jsonResult2[0][CloudStackTypes.Answer]; dynamic ans2 = jsonResult2[0][CloudStackTypes.Answer];
Assert.IsTrue((bool)ans2.result, (string)ans2.details); // always succeeds Assert.True((bool)ans2.result, (string)ans2.details); // always succeeds
} }
[TestMethod] [Fact(Skip="these are functional tests")]
public void CreateStoragePoolCommand() public void CreateStoragePoolCommand()
{ {
var cmd = new { localPath = "NULL" }; var cmd = new { localPath = "NULL" };
@ -726,10 +727,10 @@ namespace ServerResource.Tests
// Assert // Assert
dynamic ans = jsonResult[0][CloudStackTypes.Answer]; dynamic ans = jsonResult[0][CloudStackTypes.Answer];
Assert.IsTrue((bool)ans.result, (string)ans.details); // always succeeds Assert.True((bool)ans.result, (string)ans.details); // always succeeds
} }
[TestMethod] [Fact(Skip="these are functional tests")]
public void MaintainCommand() public void MaintainCommand()
{ {
// Omit HostEnvironment object, as this is a series of settings currently not used. // Omit HostEnvironment object, as this is a series of settings currently not used.
@ -742,10 +743,10 @@ namespace ServerResource.Tests
// Assert // Assert
dynamic ans = jsonResult[0][CloudStackTypes.MaintainAnswer]; dynamic ans = jsonResult[0][CloudStackTypes.MaintainAnswer];
Assert.IsTrue((bool)ans.result, (string)ans.details); // always succeeds Assert.True((bool)ans.result, (string)ans.details); // always succeeds
} }
[TestMethod] [Fact(Skip="these are functional tests")]
public void SetupCommand() public void SetupCommand()
{ {
// Omit HostEnvironment object, as this is a series of settings currently not used. // Omit HostEnvironment object, as this is a series of settings currently not used.
@ -758,10 +759,10 @@ namespace ServerResource.Tests
// Assert // Assert
dynamic ans = jsonResult[0][CloudStackTypes.SetupAnswer]; dynamic ans = jsonResult[0][CloudStackTypes.SetupAnswer];
Assert.IsTrue((bool)ans.result, (string)ans.details); // always succeeds Assert.True((bool)ans.result, (string)ans.details); // always succeeds
} }
[TestMethod] [Fact(Skip="these are functional tests")]
public void TestPassingUserdataToVm() public void TestPassingUserdataToVm()
{ {
// Sample data // Sample data
@ -769,14 +770,14 @@ namespace ServerResource.Tests
String value = "username=root;password=1pass@word1"; String value = "username=root;password=1pass@word1";
// Find the VM // Find the VM
List<String> vmNames = WmiCallsV2.GetVmElementNames(); List<String> vmNames = wmiCallsV2.GetVmElementNames();
// Get associated WMI object // Get associated WMI object
var vm = WmiCallsV2.GetComputerSystem(AgentSettings.Default.testKvpVmName); var vm = wmiCallsV2.GetComputerSystem(AgentSettings.Default.testKvpVmName);
// Get existing KVP // Get existing KVP
var vmSettings = WmiCallsV2.GetVmSettings(vm); var vmSettings = wmiCallsV2.GetVmSettings(vm);
var kvpInfo = WmiCallsV2.GetKvpSettings(vmSettings); var kvpInfo = wmiCallsV2.GetKvpSettings(vmSettings);
// HostExchangesItems are embedded objects in the sense that the object value is stored and not a reference to the object. // HostExchangesItems are embedded objects in the sense that the object value is stored and not a reference to the object.
string[] kvpProps = kvpInfo.HostExchangeItems; string[] kvpProps = kvpInfo.HostExchangeItems;
@ -791,16 +792,16 @@ namespace ServerResource.Tests
if (existingKey == key) if (existingKey == key)
{ {
WmiCallsV2.DeleteHostKvpItem(vm, existingKey); wmiCallsV2.DeleteHostKvpItem(vm, existingKey);
break; break;
} }
} }
// Add new user data // Add new user data
WmiCallsV2.AddUserData(vm, value); wmiCallsV2.AddUserData(vm, value);
// Verify key added to subsystem // Verify key added to subsystem
kvpInfo = WmiCallsV2.GetKvpSettings(vmSettings); kvpInfo = wmiCallsV2.GetKvpSettings(vmSettings);
// HostExchangesItems are embedded objects in the sense that the object value is stored and not a reference to the object. // HostExchangesItems are embedded objects in the sense that the object value is stored and not a reference to the object.
kvpProps = kvpInfo.HostExchangeItems; kvpProps = kvpInfo.HostExchangeItems;
@ -816,13 +817,13 @@ namespace ServerResource.Tests
if (existingKey == key && existingValue == value) if (existingKey == key && existingValue == value)
{ {
// WmiCallsV2.DeleteHostKvpItem(vm, existingKey); // wmiCallsV2.DeleteHostKvpItem(vm, existingKey);
userDataInPlace = true; userDataInPlace = true;
break; break;
} }
} }
Assert.IsTrue(userDataInPlace, "User data key / value did no save properly"); Assert.True(userDataInPlace, "User data key / value did no save properly");
} }
private static void ParseKVP(String wmiObjectXml, out String existingKey, out String existingValue) private static void ParseKVP(String wmiObjectXml, out String existingKey, out String existingValue)
@ -844,7 +845,7 @@ namespace ServerResource.Tests
existingValue = dataNode.InnerText; existingValue = dataNode.InnerText;
} }
[TestMethod] [Fact(Skip="these are functional tests")]
public void GetVmStatsCommandFail() public void GetVmStatsCommandFail()
{ {
// Use WMI to find existing VMs // Use WMI to find existing VMs
@ -865,14 +866,14 @@ namespace ServerResource.Tests
// Assert // Assert
dynamic ans = jsonResult[0][CloudStackTypes.GetVmStatsAnswer]; dynamic ans = jsonResult[0][CloudStackTypes.GetVmStatsAnswer];
Assert.IsTrue((bool)ans.result, (string)ans.details); // always succeeds, fake VM means no answer for the named VM Assert.True((bool)ans.result, (string)ans.details); // always succeeds, fake VM means no answer for the named VM
} }
[TestMethod] [Fact(Skip="these are functional tests")]
public void GetVmStatsCommand() public void GetVmStatsCommand()
{ {
// Use WMI to find existing VMs // Use WMI to find existing VMs
List<String> vmNames = WmiCalls.GetVmElementNames(); List<String> vmNames = wmiCalls.GetVmElementNames();
var cmd = new var cmd = new
{ {
@ -888,10 +889,10 @@ namespace ServerResource.Tests
// Assert // Assert
dynamic ans = jsonResult[0][CloudStackTypes.GetVmStatsAnswer]; dynamic ans = jsonResult[0][CloudStackTypes.GetVmStatsAnswer];
Assert.IsTrue((bool)ans.result, (string)ans.details); Assert.True((bool)ans.result, (string)ans.details);
} }
[TestMethod] [Fact(Skip="these are functional tests")]
public void GetStorageStatsCommand() public void GetStorageStatsCommand()
{ {
// TODO: Update sample data to unsure it is using correct info. // TODO: Update sample data to unsure it is using correct info.
@ -916,12 +917,12 @@ namespace ServerResource.Tests
// Assert // Assert
dynamic ans = jsonResult[0][CloudStackTypes.GetStorageStatsAnswer]; dynamic ans = jsonResult[0][CloudStackTypes.GetStorageStatsAnswer];
Assert.IsTrue((bool)ans.result, (string)ans.details); Assert.True((bool)ans.result, (string)ans.details);
Assert.IsTrue((long)ans.used <= (long)ans.capacity); // TODO: verify that capacity is indeed capacity and not used. Assert.True((long)ans.used <= (long)ans.capacity); // TODO: verify that capacity is indeed capacity and not used.
} }
// TODO: can we speed up this command? The logic takes over a second. // TODO: can we speed up this command? The logic takes over a second.
[TestMethod] [Fact(Skip="these are functional tests")]
public void GetHostStatsCommand() public void GetHostStatsCommand()
{ {
// Arrange // Arrange
@ -945,19 +946,19 @@ namespace ServerResource.Tests
// Assert // Assert
dynamic ans = jsonResult[0][CloudStackTypes.GetHostStatsAnswer]; dynamic ans = jsonResult[0][CloudStackTypes.GetHostStatsAnswer];
Assert.IsTrue((bool)ans.result); Assert.True((bool)ans.result);
Assert.IsTrue(hostIdVal == (long)ans.hostStats.hostId); Assert.True(hostIdVal == (long)ans.hostStats.hostId);
Assert.IsTrue(0.0 < (double)ans.hostStats.totalMemoryKBs); Assert.True(0.0 < (double)ans.hostStats.totalMemoryKBs);
Assert.IsTrue(0.0 < (double)ans.hostStats.freeMemoryKBs); Assert.True(0.0 < (double)ans.hostStats.freeMemoryKBs);
Assert.IsTrue(0.0 <= (double)ans.hostStats.networkReadKBs); Assert.True(0.0 <= (double)ans.hostStats.networkReadKBs);
Assert.IsTrue(0.0 <= (double)ans.hostStats.networkWriteKBs); Assert.True(0.0 <= (double)ans.hostStats.networkWriteKBs);
Assert.IsTrue(0.0 <= (double)ans.hostStats.cpuUtilization); Assert.True(0.0 <= (double)ans.hostStats.cpuUtilization);
Assert.IsTrue(100.0 >= (double)ans.hostStats.cpuUtilization); Assert.True(100.0 >= (double)ans.hostStats.cpuUtilization);
Assert.IsTrue("host".Equals((string)ans.hostStats.entityType)); Assert.True("host".Equals((string)ans.hostStats.entityType));
Assert.IsTrue(String.IsNullOrEmpty((string)ans.details)); Assert.True(String.IsNullOrEmpty((string)ans.details));
} }
[TestMethod] [Fact(Skip="these are functional tests")]
public void GetHostStatsCommandFail() public void GetHostStatsCommandFail()
{ {
// Arrange // Arrange
@ -970,12 +971,12 @@ namespace ServerResource.Tests
// Assert // Assert
dynamic ans = jsonResult[0][CloudStackTypes.GetHostStatsAnswer]; dynamic ans = jsonResult[0][CloudStackTypes.GetHostStatsAnswer];
Assert.IsFalse((bool)ans.result); Assert.False((bool)ans.result);
Assert.IsNull((string)ans.hostStats); Assert.Null((string)ans.hostStats);
Assert.IsNotNull(ans.details); Assert.NotNull(ans.details);
} }
[TestMethod] [Fact(Skip="these are functional tests")]
public void TestStartupCommand() public void TestStartupCommand()
{ {
// Arrange // Arrange
@ -1008,16 +1009,16 @@ namespace ServerResource.Tests
uint cores; uint cores;
uint mhz; uint mhz;
WmiCalls.GetProcessorResources(out cores, out mhz); wmiCalls.GetProcessorResources(out cores, out mhz);
ulong memory_mb; ulong memory_mb;
ulong freememory; ulong freememory;
WmiCalls.GetMemoryResources(out memory_mb, out freememory); wmiCalls.GetMemoryResources(out memory_mb, out freememory);
memory_mb *= 1024; memory_mb *= 1024;
long capacityBytes; long capacityBytes;
long availableBytes; long availableBytes;
HypervResourceController.GetCapacityForLocalPath(WmiCalls.GetDefaultVirtualDiskFolder(), HypervResourceController.GetCapacityForLocalPath(wmiCalls.GetDefaultVirtualDiskFolder(),
out capacityBytes, out availableBytes); out capacityBytes, out availableBytes);
var DefaultVirtualDiskFolder = JsonConvert.SerializeObject(WmiCalls.GetDefaultVirtualDiskFolder()); var DefaultVirtualDiskFolder = JsonConvert.SerializeObject(wmiCalls.GetDefaultVirtualDiskFolder());
string expected = string expected =
#region string_literal #region string_literal
"[{\"" + CloudStackTypes.StartupRoutingCommand + "\":{" + "[{\"" + CloudStackTypes.StartupRoutingCommand + "\":{" +
@ -1073,7 +1074,7 @@ namespace ServerResource.Tests
// Assert // Assert
string actual = JsonConvert.SerializeObject(jsonResult); string actual = JsonConvert.SerializeObject(jsonResult);
Assert.AreEqual(expected, actual, "StartupRoutingCommand not populated properly"); Assert.Equal(expected, actual);
} }
@ -1090,40 +1091,40 @@ namespace ServerResource.Tests
dynamic startAns = rsrcServer.StartCommand(jsonStartCmd); dynamic startAns = rsrcServer.StartCommand(jsonStartCmd);
// Assert // Assert
Assert.IsNotNull(startAns[0][CloudStackTypes.StartAnswer], "StartCommand should return a StartAnswer in all cases"); Assert.NotNull(startAns[0][CloudStackTypes.StartAnswer]);
Assert.IsTrue((bool)startAns[0][CloudStackTypes.StartAnswer].result, "StartCommand did not succeed " + startAns[0][CloudStackTypes.StartAnswer].details); Assert.True((bool)startAns[0][CloudStackTypes.StartAnswer].result, "StartCommand did not succeed " + startAns[0][CloudStackTypes.StartAnswer].details);
string vmCmdName = jsonStartCmd.vm.name.Value; string vmCmdName = jsonStartCmd.vm.name.Value;
var vm = WmiCalls.GetComputerSystem(vmCmdName); var vm = wmiCalls.GetComputerSystem(vmCmdName);
VirtualSystemSettingData vmSettings = WmiCalls.GetVmSettings(vm); VirtualSystemSettingData vmSettings = wmiCalls.GetVmSettings(vm);
MemorySettingData memSettings = WmiCalls.GetMemSettings(vmSettings); MemorySettingData memSettings = wmiCalls.GetMemSettings(vmSettings);
ProcessorSettingData procSettings = WmiCalls.GetProcSettings(vmSettings); ProcessorSettingData procSettings = wmiCalls.GetProcSettings(vmSettings);
dynamic jsonObj = JsonConvert.DeserializeObject(sample); dynamic jsonObj = JsonConvert.DeserializeObject(sample);
var vmInfo = jsonObj.vm; var vmInfo = jsonObj.vm;
string vmName = vmInfo.name; string vmName = vmInfo.name;
var nicInfo = vmInfo.nics; var nicInfo = vmInfo.nics;
int vcpus = vmInfo.cpus; int vcpus = vmInfo.cpus;
int memSize = vmInfo.maxRam / 1048576; int memSize = vmInfo.maxRam / 1048576;
Assert.IsTrue((long)memSettings.VirtualQuantity == memSize); Assert.True((long)memSettings.VirtualQuantity == memSize);
Assert.IsTrue((long)memSettings.Reservation == memSize); Assert.True((long)memSettings.Reservation == memSize);
Assert.IsTrue((long)memSettings.Limit == memSize); Assert.True((long)memSettings.Limit == memSize);
Assert.IsTrue((int)procSettings.VirtualQuantity == vcpus); Assert.True((int)procSettings.VirtualQuantity == vcpus);
Assert.IsTrue((int)procSettings.Reservation == vcpus); Assert.True((int)procSettings.Reservation == vcpus);
Assert.IsTrue((int)procSettings.Limit == 100000); Assert.True((int)procSettings.Limit == 100000);
// examine NIC // examine NIC
SyntheticEthernetPortSettingData[] nicSettingsViaVm = WmiCalls.GetEthernetPorts(vm); SyntheticEthernetPortSettingData[] nicSettingsViaVm = wmiCalls.GetEthernetPorts(vm);
Assert.IsTrue(nicSettingsViaVm.Length > 0, "Should be at least one ethernet port on VM"); Assert.True(nicSettingsViaVm.Length > 0, "Should be at least one ethernet port on VM");
string expectedMac = (string)jsonStartCmd.vm.nics[0].mac; string expectedMac = (string)jsonStartCmd.vm.nics[0].mac;
string strippedExpectedMac = expectedMac.Replace(":", string.Empty); string strippedExpectedMac = expectedMac.Replace(":", string.Empty);
Assert.AreEqual(nicSettingsViaVm[0].Address.ToLower(), strippedExpectedMac.ToLower()); Assert.Equal(nicSettingsViaVm[0].Address.ToLower(), strippedExpectedMac.ToLower());
// Assert switchport has correct VLAN // Assert switchport has correct VLAN
SwitchPort[] switchPorts = WmiCalls.GetSwitchPorts(vm); SwitchPort[] switchPorts = wmiCalls.GetSwitchPorts(vm);
VirtualSwitchManagementService vmNetMgmtSvc = WmiCalls.GetVirtualSwitchManagementService(); VirtualSwitchManagementService vmNetMgmtSvc = wmiCalls.GetVirtualSwitchManagementService();
VLANEndpointSettingData vlanSettings = WmiCalls.GetVlanEndpointSettings(vmNetMgmtSvc, switchPorts[0].Path); VLANEndpointSettingData vlanSettings = wmiCalls.GetVlanEndpointSettings(vmNetMgmtSvc, switchPorts[0].Path);
string isolationUri = (string)jsonStartCmd.vm.nics[0].isolationUri; string isolationUri = (string)jsonStartCmd.vm.nics[0].isolationUri;
string vlan = isolationUri.Replace("vlan://", string.Empty); string vlan = isolationUri.Replace("vlan://", string.Empty);
Assert.AreEqual(vlanSettings.AccessVLAN.ToString(), vlan); Assert.Equal(vlanSettings.AccessVLAN.ToString(), vlan);
return vmName; return vmName;
} }
@ -1139,10 +1140,10 @@ namespace ServerResource.Tests
dynamic stopAns = rsrcServer.StopCommand(jsonStopCmd); dynamic stopAns = rsrcServer.StopCommand(jsonStopCmd);
// Assert VM is gone! // Assert VM is gone!
Assert.IsNotNull(stopAns[0][CloudStackTypes.StopAnswer], "StopCommand should return a StopAnswer in all cases"); Assert.NotNull(stopAns[0][CloudStackTypes.StopAnswer]);
Assert.IsTrue((bool)stopAns[0][CloudStackTypes.StopAnswer].result, "StopCommand did not succeed " + stopAns[0][CloudStackTypes.StopAnswer].details); Assert.True((bool)stopAns[0][CloudStackTypes.StopAnswer].result, "StopCommand did not succeed " + stopAns[0][CloudStackTypes.StopAnswer].details);
var finalVm = WmiCalls.GetComputerSystem(vmName); var finalVm = wmiCalls.GetComputerSystem(vmName);
Assert.IsTrue(WmiCalls.GetComputerSystem(vmName) == null); Assert.True(wmiCalls.GetComputerSystem(vmName) == null);
} }
} }
} }

View File

@ -53,6 +53,9 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="AWSSDK">
<HintPath>..\packages\AWSSDK.1.5.23.0\lib\AWSSDK.dll</HintPath>
</Reference>
<Reference Include="Ionic.Zip"> <Reference Include="Ionic.Zip">
<HintPath>..\packages\DotNetZip.1.9.1.8\lib\net20\Ionic.Zip.dll</HintPath> <HintPath>..\packages\DotNetZip.1.9.1.8\lib\net20\Ionic.Zip.dll</HintPath>
</Reference> </Reference>
@ -60,10 +63,12 @@
<HintPath>..\packages\log4net.2.0.0\lib\net40-full\log4net.dll</HintPath> <HintPath>..\packages\log4net.2.0.0\lib\net40-full\log4net.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="Newtonsoft.Json"> <Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath> <HintPath>..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference> </Reference>
<Reference Include="NSubstitute">
<HintPath>..\packages\NSubstitute.1.6.1.0\lib\NET40\NSubstitute.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" /> <Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Configuration" /> <Reference Include="System.Configuration" />
@ -81,12 +86,14 @@
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="System.Net.Http"> <Reference Include="System.Net.Http">
</Reference> </Reference>
<Reference Include="System.Net.Http.WebRequest"> <Reference Include="xunit">
<HintPath>..\packages\xunit.1.9.2\lib\net20\xunit.dll</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="HypervResourceController1Test.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="HypervResourceControllerTest.cs" /> <!--<Compile Include="HypervResourceControllerTest.cs" /> -->
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="App.config"> <Content Include="App.config">
@ -121,4 +128,9 @@
<Target Name="AfterBuild"> <Target Name="AfterBuild">
</Target> </Target>
--> -->
<UsingTask AssemblyFile="..\packages\xunit.1.9.2\lib\net20\xunit.runner.msbuild.dll"
TaskName="Xunit.Runner.MSBuild.xunit" />
<Target Name="AfterBuild">
<Xunit.Runner.MSBuild.xunit Assembly="..\ServerResource.Tests\bin\Debug\ServerResource.Tests.dll" />
</Target>
</Project> </Project>

View File

@ -1,6 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="AWSSDK" version="1.5.23.0" targetFramework="net45" />
<package id="DotNetZip" version="1.9.1.8" targetFramework="net45" /> <package id="DotNetZip" version="1.9.1.8" targetFramework="net45" />
<package id="log4net" version="2.0.0" targetFramework="net45" /> <package id="log4net" version="2.0.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="4.5.11" 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> </packages>

View File

@ -0,0 +1,791 @@
namespace CloudStack.Plugin.WmiWrappers.ROOT.VIRTUALIZATION.V2 {
using System;
using System.ComponentModel;
using System.Management;
using System.Collections;
using System.Globalization;
using System.ComponentModel.Design.Serialization;
using System.Reflection;
// Functions ShouldSerialize<PropertyName> are functions used by VS property browser to check if a particular property has to be serialized. These functions are added for all ValueType properties ( properties of type Int32, BOOL etc.. which cannot be set to null). These functions use Is<PropertyName>Null function. These functions are also used in the TypeConverter implementation for the properties to check for NULL value of property so that an empty value can be shown in Property browser in case of Drag and Drop in Visual studio.
// Functions Is<PropertyName>Null() are used to check if a property is NULL.
// Functions Reset<PropertyName> are added for Nullable Read/Write properties. These functions are used by VS designer in property browser to set a property to NULL.
// Every property added to the class for WMI property has attributes set to define its behavior in Visual Studio designer and also to define a TypeConverter to be used.
// An Early Bound class generated for the WMI class.Msvm_VirtualSystemManagementServiceSettingData
public class VirtualSystemManagementServiceSettingData : System.ComponentModel.Component {
// Private property to hold the WMI namespace in which the class resides.
private static string CreatedWmiNamespace = "ROOT\\virtualization\\v2";
// Private property to hold the name of WMI class which created this class.
public static string CreatedClassName = "Msvm_VirtualSystemManagementServiceSettingData";
// Private member variable to hold the ManagementScope which is used by the various methods.
private static System.Management.ManagementScope statMgmtScope = null;
private ManagementSystemProperties PrivateSystemProperties;
// Underlying lateBound WMI object.
private System.Management.ManagementObject PrivateLateBoundObject;
// Member variable to store the 'automatic commit' behavior for the class.
private bool AutoCommitProp;
// Private variable to hold the embedded property representing the instance.
private System.Management.ManagementBaseObject embeddedObj;
// The current WMI object used
private System.Management.ManagementBaseObject curObj;
// Flag to indicate if the instance is an embedded object.
private bool isEmbedded;
// Below are different overloads of constructors to initialize an instance of the class with a WMI object.
public VirtualSystemManagementServiceSettingData() {
this.InitializeObject(null, null, null);
}
public VirtualSystemManagementServiceSettingData(string keyInstanceID) {
this.InitializeObject(null, new System.Management.ManagementPath(VirtualSystemManagementServiceSettingData.ConstructPath(keyInstanceID)), null);
}
public VirtualSystemManagementServiceSettingData(System.Management.ManagementScope mgmtScope, string keyInstanceID) {
this.InitializeObject(((System.Management.ManagementScope)(mgmtScope)), new System.Management.ManagementPath(VirtualSystemManagementServiceSettingData.ConstructPath(keyInstanceID)), null);
}
public VirtualSystemManagementServiceSettingData(System.Management.ManagementPath path, System.Management.ObjectGetOptions getOptions) {
this.InitializeObject(null, path, getOptions);
}
public VirtualSystemManagementServiceSettingData(System.Management.ManagementScope mgmtScope, System.Management.ManagementPath path) {
this.InitializeObject(mgmtScope, path, null);
}
public VirtualSystemManagementServiceSettingData(System.Management.ManagementPath path) {
this.InitializeObject(null, path, null);
}
public VirtualSystemManagementServiceSettingData(System.Management.ManagementScope mgmtScope, System.Management.ManagementPath path, System.Management.ObjectGetOptions getOptions) {
this.InitializeObject(mgmtScope, path, getOptions);
}
public VirtualSystemManagementServiceSettingData(System.Management.ManagementObject theObject) {
Initialize();
if ((CheckIfProperClass(theObject) == true)) {
PrivateLateBoundObject = theObject;
PrivateSystemProperties = new ManagementSystemProperties(PrivateLateBoundObject);
curObj = PrivateLateBoundObject;
}
else {
throw new System.ArgumentException("Class name does not match.");
}
}
public VirtualSystemManagementServiceSettingData(System.Management.ManagementBaseObject theObject) {
Initialize();
if ((CheckIfProperClass(theObject) == true)) {
embeddedObj = theObject;
PrivateSystemProperties = new ManagementSystemProperties(theObject);
curObj = embeddedObj;
isEmbedded = true;
}
else {
throw new System.ArgumentException("Class name does not match.");
}
}
// Property returns the namespace of the WMI class.
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public string OriginatingNamespace {
get {
return "ROOT\\virtualization\\v2";
}
}
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public string ManagementClassName {
get {
string strRet = CreatedClassName;
if ((curObj != null)) {
if ((curObj.ClassPath != null)) {
strRet = ((string)(curObj["__CLASS"]));
if (((strRet == null)
|| (strRet == string.Empty))) {
strRet = CreatedClassName;
}
}
}
return strRet;
}
}
// Property pointing to an embedded object to get System properties of the WMI object.
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public ManagementSystemProperties SystemProperties {
get {
return PrivateSystemProperties;
}
}
// Property returning the underlying lateBound object.
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public System.Management.ManagementBaseObject LateBoundObject {
get {
return curObj;
}
}
// ManagementScope of the object.
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public System.Management.ManagementScope Scope {
get {
if ((isEmbedded == false)) {
return PrivateLateBoundObject.Scope;
}
else {
return null;
}
}
set {
if ((isEmbedded == false)) {
PrivateLateBoundObject.Scope = value;
}
}
}
// Property to show the commit behavior for the WMI object. If true, WMI object will be automatically saved after each property modification.(ie. Put() is called after modification of a property).
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool AutoCommit {
get {
return AutoCommitProp;
}
set {
AutoCommitProp = value;
}
}
// The ManagementPath of the underlying WMI object.
[Browsable(true)]
public System.Management.ManagementPath Path {
get {
if ((isEmbedded == false)) {
return PrivateLateBoundObject.Path;
}
else {
return null;
}
}
set {
if ((isEmbedded == false)) {
if ((CheckIfProperClass(null, value, null) != true)) {
throw new System.ArgumentException("Class name does not match.");
}
PrivateLateBoundObject.Path = value;
}
}
}
// Public static scope property which is used by the various methods.
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public static System.Management.ManagementScope StaticScope {
get {
return statMgmtScope;
}
set {
statMgmtScope = value;
}
}
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description(@"Used by OEMs to allow BIOS-locked Windows operating systems to run in the virtual machine. This string must be exactly 32 characters in length.
This is a read-only property, but it can be changed using the ModifyServiceSettings method of the Msvm_VirtualSystemManagementService class.")]
public string BiosLockString {
get {
return ((string)(curObj["BiosLockString"]));
}
}
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public string Caption {
get {
return ((string)(curObj["Caption"]));
}
}
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("The WorldWideNodeName address for dynamically generated WorldWideName addresses u" +
"sed for Synthetic HBAs.\nThis is a read-only property, but it can be changed usin" +
"g the ModifyServiceSettings method of the Msvm_VirtualSystemManagementService cl" +
"ass.")]
public string CurrentWWNNAddress {
get {
return ((string)(curObj["CurrentWWNNAddress"]));
}
}
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("The default external data root. By default, \"root\\ProgramData\\Microsoft\\Windows\\V" +
"irtualization\".\nThis is a read-only property, but it can be changed using the Mo" +
"difyServiceSettings method of the Msvm_VirtualSystemManagementService class.")]
public string DefaultExternalDataRoot {
get {
return ((string)(curObj["DefaultExternalDataRoot"]));
}
}
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("The default virtual hard disk path. By default, \"root\\Users\\Public\\Documents\\Virt" +
"ual Hard Disks\".\nThis is a read-only property, but it can be changed using the M" +
"odifyServiceSettings method of the Msvm_VirtualSystemManagementService class.")]
public string DefaultVirtualHardDiskPath {
get {
return ((string)(curObj["DefaultVirtualHardDiskPath"]));
}
}
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public string Description {
get {
return ((string)(curObj["Description"]));
}
}
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public string ElementName {
get {
return ((string)(curObj["ElementName"]));
}
}
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool IsHbaLunTimeoutNull {
get {
if ((curObj["HbaLunTimeout"] == null)) {
return true;
}
else {
return false;
}
}
}
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description(@"This property describes the amount of time that the Synthetic FC virtual device will wait for a LUN to appear before starting a virtual machine.
This is a read-only property, but it can be changed using the ModifyServiceSettings method of the Msvm_VirtualSystemManagementService class.")]
[TypeConverter(typeof(WMIValueTypeConverter))]
public uint HbaLunTimeout {
get {
if ((curObj["HbaLunTimeout"] == null)) {
return System.Convert.ToUInt32(0);
}
return ((uint)(curObj["HbaLunTimeout"]));
}
}
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public string InstanceID {
get {
return ((string)(curObj["InstanceID"]));
}
}
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("The maximum MAC address for dynamically generated MAC addresses.\nThis is a read-o" +
"nly property, but it can be changed using the ModifyServiceSettings method of th" +
"e Msvm_VirtualSystemManagementService class.")]
public string MaximumMacAddress {
get {
return ((string)(curObj["MaximumMacAddress"]));
}
}
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("The maximum WorldWidePortName address for dynamically generated WorldWideName add" +
"resses used for Synthetic HBAs.\nThis is a read-only property, but it can be chan" +
"ged using the ModifyServiceSettings method of the Msvm_VirtualSystemManagementSe" +
"rvice class.")]
public string MaximumWWPNAddress {
get {
return ((string)(curObj["MaximumWWPNAddress"]));
}
}
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("The minimum MAC address for dynamically generated MAC addresses.\nThis is a read-o" +
"nly property, but it can be changed using the ModifyServiceSettings method of th" +
"e Msvm_VirtualSystemManagementService class.")]
public string MinimumMacAddress {
get {
return ((string)(curObj["MinimumMacAddress"]));
}
}
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("The minimum WorldWidePortName address for dynamically generated WorldWideName add" +
"resses used for Synthetic HBAs.\nThis is a read-only property, but it can be chan" +
"ged using the ModifyServiceSettings method of the Msvm_VirtualSystemManagementSe" +
"rvice class.")]
public string MinimumWWPNAddress {
get {
return ((string)(curObj["MinimumWWPNAddress"]));
}
}
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool IsNumaSpanningEnabledNull {
get {
if ((curObj["NumaSpanningEnabled"] == null)) {
return true;
}
else {
return false;
}
}
}
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("Reserved for future use.")]
[TypeConverter(typeof(WMIValueTypeConverter))]
public bool NumaSpanningEnabled {
get {
if ((curObj["NumaSpanningEnabled"] == null)) {
return System.Convert.ToBoolean(0);
}
return ((bool)(curObj["NumaSpanningEnabled"]));
}
}
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description("Controls memory allocation for the VMs on non-uniform memory access (NUMA) system" +
"s.\nThis is a read-only property, but it can be changed using the ModifyServiceSe" +
"ttings method of the Msvm_VirtualSystemManagementService class.")]
public string PrimaryOwnerContact {
get {
return ((string)(curObj["PrimaryOwnerContact"]));
}
}
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[Description(@"Describes how the primary system owner can be reached (for example, phone number or e-mail address). By default, empty. This name may not exceed 256 characters in length.
This is a read-only property, but it can be changed using the ModifyServiceSettings method of the Msvm_VirtualSystemManagementService class.")]
public string PrimaryOwnerName {
get {
return ((string)(curObj["PrimaryOwnerName"]));
}
}
private bool CheckIfProperClass(System.Management.ManagementScope mgmtScope, System.Management.ManagementPath path, System.Management.ObjectGetOptions OptionsParam) {
if (((path != null)
&& (string.Compare(path.ClassName, this.ManagementClassName, true, System.Globalization.CultureInfo.InvariantCulture) == 0))) {
return true;
}
else {
return CheckIfProperClass(new System.Management.ManagementObject(mgmtScope, path, OptionsParam));
}
}
private bool CheckIfProperClass(System.Management.ManagementBaseObject theObj) {
if (((theObj != null)
&& (string.Compare(((string)(theObj["__CLASS"])), this.ManagementClassName, true, System.Globalization.CultureInfo.InvariantCulture) == 0))) {
return true;
}
else {
System.Array parentClasses = ((System.Array)(theObj["__DERIVATION"]));
if ((parentClasses != null)) {
int count = 0;
for (count = 0; (count < parentClasses.Length); count = (count + 1)) {
if ((string.Compare(((string)(parentClasses.GetValue(count))), this.ManagementClassName, true, System.Globalization.CultureInfo.InvariantCulture) == 0)) {
return true;
}
}
}
}
return false;
}
private bool ShouldSerializeHbaLunTimeout() {
if ((this.IsHbaLunTimeoutNull == false)) {
return true;
}
return false;
}
private bool ShouldSerializeNumaSpanningEnabled() {
if ((this.IsNumaSpanningEnabledNull == false)) {
return true;
}
return false;
}
[Browsable(true)]
public void CommitObject() {
if ((isEmbedded == false)) {
PrivateLateBoundObject.Put();
}
}
[Browsable(true)]
public void CommitObject(System.Management.PutOptions putOptions) {
if ((isEmbedded == false)) {
PrivateLateBoundObject.Put(putOptions);
}
}
private void Initialize() {
AutoCommitProp = true;
isEmbedded = false;
}
private static string ConstructPath(string keyInstanceID) {
string strPath = "ROOT\\virtualization\\v2:Msvm_VirtualSystemManagementServiceSettingData";
strPath = string.Concat(strPath, string.Concat(".InstanceID=", string.Concat("\"", string.Concat(keyInstanceID, "\""))));
return strPath;
}
private void InitializeObject(System.Management.ManagementScope mgmtScope, System.Management.ManagementPath path, System.Management.ObjectGetOptions getOptions) {
Initialize();
if ((path != null)) {
if ((CheckIfProperClass(mgmtScope, path, getOptions) != true)) {
throw new System.ArgumentException("Class name does not match.");
}
}
PrivateLateBoundObject = new System.Management.ManagementObject(mgmtScope, path, getOptions);
PrivateSystemProperties = new ManagementSystemProperties(PrivateLateBoundObject);
curObj = PrivateLateBoundObject;
}
// Different overloads of GetInstances() help in enumerating instances of the WMI class.
public static VirtualSystemManagementServiceSettingDataCollection GetInstances() {
return GetInstances(null, null, null);
}
public static VirtualSystemManagementServiceSettingDataCollection GetInstances(string condition) {
return GetInstances(null, condition, null);
}
public static VirtualSystemManagementServiceSettingDataCollection GetInstances(string[] selectedProperties) {
return GetInstances(null, null, selectedProperties);
}
public static VirtualSystemManagementServiceSettingDataCollection GetInstances(string condition, string[] selectedProperties) {
return GetInstances(null, condition, selectedProperties);
}
public static VirtualSystemManagementServiceSettingDataCollection GetInstances(System.Management.ManagementScope mgmtScope, System.Management.EnumerationOptions enumOptions) {
if ((mgmtScope == null)) {
if ((statMgmtScope == null)) {
mgmtScope = new System.Management.ManagementScope();
mgmtScope.Path.NamespacePath = "root\\virtualization\\v2";
}
else {
mgmtScope = statMgmtScope;
}
}
System.Management.ManagementPath pathObj = new System.Management.ManagementPath();
pathObj.ClassName = "Msvm_VirtualSystemManagementServiceSettingData";
pathObj.NamespacePath = "root\\virtualization\\v2";
System.Management.ManagementClass clsObject = new System.Management.ManagementClass(mgmtScope, pathObj, null);
if ((enumOptions == null)) {
enumOptions = new System.Management.EnumerationOptions();
enumOptions.EnsureLocatable = true;
}
return new VirtualSystemManagementServiceSettingDataCollection(clsObject.GetInstances(enumOptions));
}
public static VirtualSystemManagementServiceSettingDataCollection GetInstances(System.Management.ManagementScope mgmtScope, string condition) {
return GetInstances(mgmtScope, condition, null);
}
public static VirtualSystemManagementServiceSettingDataCollection GetInstances(System.Management.ManagementScope mgmtScope, string[] selectedProperties) {
return GetInstances(mgmtScope, null, selectedProperties);
}
public static VirtualSystemManagementServiceSettingDataCollection GetInstances(System.Management.ManagementScope mgmtScope, string condition, string[] selectedProperties) {
if ((mgmtScope == null)) {
if ((statMgmtScope == null)) {
mgmtScope = new System.Management.ManagementScope();
mgmtScope.Path.NamespacePath = "root\\virtualization\\v2";
}
else {
mgmtScope = statMgmtScope;
}
}
System.Management.ManagementObjectSearcher ObjectSearcher = new System.Management.ManagementObjectSearcher(mgmtScope, new SelectQuery("Msvm_VirtualSystemManagementServiceSettingData", condition, selectedProperties));
System.Management.EnumerationOptions enumOptions = new System.Management.EnumerationOptions();
enumOptions.EnsureLocatable = true;
ObjectSearcher.Options = enumOptions;
return new VirtualSystemManagementServiceSettingDataCollection(ObjectSearcher.Get());
}
[Browsable(true)]
public static VirtualSystemManagementServiceSettingData CreateInstance() {
System.Management.ManagementScope mgmtScope = null;
if ((statMgmtScope == null)) {
mgmtScope = new System.Management.ManagementScope();
mgmtScope.Path.NamespacePath = CreatedWmiNamespace;
}
else {
mgmtScope = statMgmtScope;
}
System.Management.ManagementPath mgmtPath = new System.Management.ManagementPath(CreatedClassName);
System.Management.ManagementClass tmpMgmtClass = new System.Management.ManagementClass(mgmtScope, mgmtPath, null);
return new VirtualSystemManagementServiceSettingData(tmpMgmtClass.CreateInstance());
}
[Browsable(true)]
public void Delete() {
PrivateLateBoundObject.Delete();
}
// Enumerator implementation for enumerating instances of the class.
public class VirtualSystemManagementServiceSettingDataCollection : object, ICollection {
private ManagementObjectCollection privColObj;
public VirtualSystemManagementServiceSettingDataCollection(ManagementObjectCollection objCollection) {
privColObj = objCollection;
}
public virtual int Count {
get {
return privColObj.Count;
}
}
public virtual bool IsSynchronized {
get {
return privColObj.IsSynchronized;
}
}
public virtual object SyncRoot {
get {
return this;
}
}
public virtual void CopyTo(System.Array array, int index) {
privColObj.CopyTo(array, index);
int nCtr;
for (nCtr = 0; (nCtr < array.Length); nCtr = (nCtr + 1)) {
array.SetValue(new VirtualSystemManagementServiceSettingData(((System.Management.ManagementObject)(array.GetValue(nCtr)))), nCtr);
}
}
public virtual System.Collections.IEnumerator GetEnumerator() {
return new VirtualSystemManagementServiceSettingDataEnumerator(privColObj.GetEnumerator());
}
public class VirtualSystemManagementServiceSettingDataEnumerator : object, System.Collections.IEnumerator {
private ManagementObjectCollection.ManagementObjectEnumerator privObjEnum;
public VirtualSystemManagementServiceSettingDataEnumerator(ManagementObjectCollection.ManagementObjectEnumerator objEnum) {
privObjEnum = objEnum;
}
public virtual object Current {
get {
return new VirtualSystemManagementServiceSettingData(((System.Management.ManagementObject)(privObjEnum.Current)));
}
}
public virtual bool MoveNext() {
return privObjEnum.MoveNext();
}
public virtual void Reset() {
privObjEnum.Reset();
}
}
}
// TypeConverter to handle null values for ValueType properties
public class WMIValueTypeConverter : TypeConverter {
private TypeConverter baseConverter;
private System.Type baseType;
public WMIValueTypeConverter(System.Type inBaseType) {
baseConverter = TypeDescriptor.GetConverter(inBaseType);
baseType = inBaseType;
}
public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type srcType) {
return baseConverter.CanConvertFrom(context, srcType);
}
public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type destinationType) {
return baseConverter.CanConvertTo(context, destinationType);
}
public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) {
return baseConverter.ConvertFrom(context, culture, value);
}
public override object CreateInstance(System.ComponentModel.ITypeDescriptorContext context, System.Collections.IDictionary dictionary) {
return baseConverter.CreateInstance(context, dictionary);
}
public override bool GetCreateInstanceSupported(System.ComponentModel.ITypeDescriptorContext context) {
return baseConverter.GetCreateInstanceSupported(context);
}
public override PropertyDescriptorCollection GetProperties(System.ComponentModel.ITypeDescriptorContext context, object value, System.Attribute[] attributeVar) {
return baseConverter.GetProperties(context, value, attributeVar);
}
public override bool GetPropertiesSupported(System.ComponentModel.ITypeDescriptorContext context) {
return baseConverter.GetPropertiesSupported(context);
}
public override System.ComponentModel.TypeConverter.StandardValuesCollection GetStandardValues(System.ComponentModel.ITypeDescriptorContext context) {
return baseConverter.GetStandardValues(context);
}
public override bool GetStandardValuesExclusive(System.ComponentModel.ITypeDescriptorContext context) {
return baseConverter.GetStandardValuesExclusive(context);
}
public override bool GetStandardValuesSupported(System.ComponentModel.ITypeDescriptorContext context) {
return baseConverter.GetStandardValuesSupported(context);
}
public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) {
if ((baseType.BaseType == typeof(System.Enum))) {
if ((value.GetType() == destinationType)) {
return value;
}
if ((((value == null)
&& (context != null))
&& (context.PropertyDescriptor.ShouldSerializeValue(context.Instance) == false))) {
return "NULL_ENUM_VALUE" ;
}
return baseConverter.ConvertTo(context, culture, value, destinationType);
}
if (((baseType == typeof(bool))
&& (baseType.BaseType == typeof(System.ValueType)))) {
if ((((value == null)
&& (context != null))
&& (context.PropertyDescriptor.ShouldSerializeValue(context.Instance) == false))) {
return "";
}
return baseConverter.ConvertTo(context, culture, value, destinationType);
}
if (((context != null)
&& (context.PropertyDescriptor.ShouldSerializeValue(context.Instance) == false))) {
return "";
}
return baseConverter.ConvertTo(context, culture, value, destinationType);
}
}
// Embedded class to represent WMI system Properties.
[TypeConverter(typeof(System.ComponentModel.ExpandableObjectConverter))]
public class ManagementSystemProperties {
private System.Management.ManagementBaseObject PrivateLateBoundObject;
public ManagementSystemProperties(System.Management.ManagementBaseObject ManagedObject) {
PrivateLateBoundObject = ManagedObject;
}
[Browsable(true)]
public int GENUS {
get {
return ((int)(PrivateLateBoundObject["__GENUS"]));
}
}
[Browsable(true)]
public string CLASS {
get {
return ((string)(PrivateLateBoundObject["__CLASS"]));
}
}
[Browsable(true)]
public string SUPERCLASS {
get {
return ((string)(PrivateLateBoundObject["__SUPERCLASS"]));
}
}
[Browsable(true)]
public string DYNASTY {
get {
return ((string)(PrivateLateBoundObject["__DYNASTY"]));
}
}
[Browsable(true)]
public string RELPATH {
get {
return ((string)(PrivateLateBoundObject["__RELPATH"]));
}
}
[Browsable(true)]
public int PROPERTY_COUNT {
get {
return ((int)(PrivateLateBoundObject["__PROPERTY_COUNT"]));
}
}
[Browsable(true)]
public string[] DERIVATION {
get {
return ((string[])(PrivateLateBoundObject["__DERIVATION"]));
}
}
[Browsable(true)]
public string SERVER {
get {
return ((string)(PrivateLateBoundObject["__SERVER"]));
}
}
[Browsable(true)]
public string NAMESPACE {
get {
return ((string)(PrivateLateBoundObject["__NAMESPACE"]));
}
}
[Browsable(true)]
public string PATH {
get {
return ((string)(PrivateLateBoundObject["__PATH"]));
}
}
}
}
}

View File

@ -11,6 +11,8 @@
<AssemblyName>WmiWrappers</AssemblyName> <AssemblyName>WmiWrappers</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@ -48,6 +50,21 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <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>
<Reference Include="log4net">
<HintPath>..\packages\log4net.2.0.0\lib\net40-full\log4net.dll</HintPath>
</Reference>
<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" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Management" /> <Reference Include="System.Management" />
@ -56,9 +73,11 @@
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="xunit">
<HintPath>..\packages\xunit.1.9.2\lib\net20\xunit.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ROOT.CIMV2.Win32_OperatingSystem.cs"> <Compile Include="ROOT.CIMV2.Win32_OperatingSystem.cs">
<SubType>Component</SubType> <SubType>Component</SubType>
</Compile> </Compile>
@ -149,6 +168,9 @@
<Compile Include="ROOT.virtualization.v2.Msvm_VirtualSystemManagementService.cs"> <Compile Include="ROOT.virtualization.v2.Msvm_VirtualSystemManagementService.cs">
<SubType>Component</SubType> <SubType>Component</SubType>
</Compile> </Compile>
<Compile Include="ROOT.virtualization.v2.Msvm_VirtualSystemManagementServiceSettingData.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="ROOT.virtualization.v2.Msvm_VirtualSystemSettingData.cs"> <Compile Include="ROOT.virtualization.v2.Msvm_VirtualSystemSettingData.cs">
<SubType>Component</SubType> <SubType>Component</SubType>
</Compile> </Compile>
@ -156,7 +178,11 @@
<ItemGroup> <ItemGroup>
<Content Include="Readme.txt" /> <Content Include="Readme.txt" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">

9
plugins/hypervisors/hyperv/buildagent.sh Normal file → Executable file
View File

@ -19,4 +19,11 @@ export EnableNuGetPackageRestore=true
wget http://nuget.org/nuget.exe wget http://nuget.org/nuget.exe
mv nuget.exe ./DotNet/ServerResource/.nuget/NuGet.exe mv nuget.exe ./DotNet/ServerResource/.nuget/NuGet.exe
chmod a+x ./DotNet/ServerResource/.nuget/NuGet.exe chmod a+x ./DotNet/ServerResource/.nuget/NuGet.exe
xbuild /p:Configuration="NoUnitTests" /p:BuildWithMono="true" ./DotNet/ServerResource/ServerResource.sln if [ "$1" == "true" ] ; then
echo " skipping tests"
xbuild /p:Configuration="NoUnitTests" /p:BuildWithMono="true" ./DotNet/ServerResource/ServerResource.sln
else
echo " running tests "
xbuild /p:BuildWithMono="true" ./DotNet/ServerResource/ServerResource.sln
fi

View File

@ -27,7 +27,8 @@
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>
<properties> <properties>
<skipTests>true</skipTests> <skipTests>false</skipTests>
<skipFunctionalTests>true</skipFunctionalTests>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
@ -134,6 +135,7 @@
<executable>bash</executable> <executable>bash</executable>
<arguments> <arguments>
<argument>./buildagent.sh</argument> <argument>./buildagent.sh</argument>
<argument>${skipTests}</argument>
</arguments> </arguments>
</configuration> </configuration>
</plugin> </plugin>
@ -148,7 +150,7 @@
<includes> <includes>
<include>**/HypervDirectConnectResourceTest.java</include> <include>**/HypervDirectConnectResourceTest.java</include>
</includes> </includes>
<skipTests>${skipTests}</skipTests> <skipTests>${skipFunctionalTests}</skipTests>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>

View File

@ -16,18 +16,26 @@
// under the License. // under the License.
package com.cloud.hypervisor.hyperv.discoverer; package com.cloud.hypervisor.hyperv.discoverer;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random;
import java.util.UUID; import java.util.UUID;
import javax.ejb.Local; import javax.ejb.Local;
import javax.inject.Inject; import javax.inject.Inject;
import javax.naming.ConfigurationException; import javax.naming.ConfigurationException;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.utils.identity.ManagementServerNode;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager; import com.cloud.agent.AgentManager;
@ -42,6 +50,7 @@ import com.cloud.agent.api.SetupCommand;
import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand; import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.alert.AlertManager; import com.cloud.alert.AlertManager;
import com.cloud.configuration.Config;
import com.cloud.dc.ClusterDetailsDao; import com.cloud.dc.ClusterDetailsDao;
import com.cloud.dc.ClusterVO; import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenterVO; import com.cloud.dc.DataCenterVO;
@ -67,6 +76,13 @@ import com.cloud.resource.ResourceManager;
import com.cloud.resource.ResourceStateAdapter; import com.cloud.resource.ResourceStateAdapter;
import com.cloud.resource.ServerResource; import com.cloud.resource.ServerResource;
import com.cloud.resource.UnableDeleteHostException; import com.cloud.resource.UnableDeleteHostException;
import com.cloud.storage.JavaStorageLayer;
import com.cloud.storage.StorageLayer;
import com.cloud.utils.FileUtil;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.db.GlobalLock;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.Script;
/** /**
* Methods to discover and managem a Hyper-V agent. Prepares a * Methods to discover and managem a Hyper-V agent. Prepares a
@ -76,8 +92,15 @@ import com.cloud.resource.UnableDeleteHostException;
@Local(value = Discoverer.class) @Local(value = Discoverer.class)
public class HypervServerDiscoverer extends DiscovererBase implements public class HypervServerDiscoverer extends DiscovererBase implements
Discoverer, Listener, ResourceStateAdapter { Discoverer, Listener, ResourceStateAdapter {
private static final Logger s_logger = Logger private static final Logger s_logger = Logger.getLogger(HypervServerDiscoverer.class);
.getLogger(HypervServerDiscoverer.class);
private String _instance;
private String _mountParent;
private int _timeout;
Random _rand = new Random(System.currentTimeMillis());
Map<String, String> _storageMounts = new HashMap<String, String>();
StorageLayer _storage;
@Inject @Inject
private HostDao _hostDao = null; private HostDao _hostDao = null;
@ -91,6 +114,8 @@ public class HypervServerDiscoverer extends DiscovererBase implements
private HostPodDao _podDao; private HostPodDao _podDao;
@Inject @Inject
private DataCenterDao _dcDao; private DataCenterDao _dcDao;
@Inject
DataStoreManager _dataStoreMgr;
// TODO: AgentManager and AlertManager not being used to transmit info, // TODO: AgentManager and AlertManager not being used to transmit info,
// may want to reconsider. // may want to reconsider.
@ -152,8 +177,17 @@ public class HypervServerDiscoverer extends DiscovererBase implements
s_logger.debug("Setting up host " + agentId); s_logger.debug("Setting up host " + agentId);
} }
String secondaryStorageUri = getSecondaryStorageStoreUrl(cluster.getDataCenterId());
if (secondaryStorageUri == null) {
s_logger.debug("Secondary storage uri for dc " + cluster.getDataCenterId() + " couldn't be obtained");
} else {
prepareSecondaryStorageStore(secondaryStorageUri);
}
HostEnvironment env = new HostEnvironment(); HostEnvironment env = new HostEnvironment();
SetupCommand setup = new SetupCommand(env); SetupCommand setup = new SetupCommand(env);
setup.setSecondaryStorage(secondaryStorageUri);
setup.setSystemVmIso("systemvm/" + getSystemVMIsoFileNameOnDatastore());
if (!host.isSetup()) { if (!host.isSetup()) {
setup.setNeedSetup(true); setup.setNeedSetup(true);
} }
@ -298,6 +332,7 @@ public class HypervServerDiscoverer extends DiscovererBase implements
params.put("cluster", Long.toString(clusterId)); params.put("cluster", Long.toString(clusterId));
params.put("guid", guidWithTail); params.put("guid", guidWithTail);
params.put("ipaddress", agentIp); params.put("ipaddress", agentIp);
params.put("sec.storage.url", getSecondaryStorageStoreUrl(dcId));
// Hyper-V specific settings // Hyper-V specific settings
Map<String, String> details = new HashMap<String, String>(); Map<String, String> details = new HashMap<String, String>();
@ -349,6 +384,177 @@ public class HypervServerDiscoverer extends DiscovererBase implements
return null; return null;
} }
private void prepareSecondaryStorageStore(String storageUrl) {
String mountPoint = getMountPoint(storageUrl);
GlobalLock lock = GlobalLock.getInternLock("prepare.systemvm");
try {
if(lock.lock(3600)) {
try {
File patchFolder = new File(mountPoint + "/systemvm");
if(!patchFolder.exists()) {
if(!patchFolder.mkdirs()) {
String msg = "Unable to create systemvm folder on secondary storage. location: " + patchFolder.toString();
s_logger.error(msg);
throw new CloudRuntimeException(msg);
}
}
File srcIso = getSystemVMPatchIsoFile();
File destIso = new File(mountPoint + "/systemvm/" + getSystemVMIsoFileNameOnDatastore());
if(!destIso.exists()) {
s_logger.info("Copy System VM patch ISO file to secondary storage. source ISO: " +
srcIso.getAbsolutePath() + ", destination: " + destIso.getAbsolutePath());
try {
FileUtil.copyfile(srcIso, destIso);
} catch(IOException e) {
s_logger.error("Unexpected exception ", e);
String msg = "Unable to copy systemvm ISO on secondary storage. src location: " + srcIso.toString() + ", dest location: " + destIso;
s_logger.error(msg);
throw new CloudRuntimeException(msg);
}
} else {
if(s_logger.isTraceEnabled()) {
s_logger.trace("SystemVM ISO file " + destIso.getPath() + " already exists");
}
}
} finally {
lock.unlock();
}
}
} finally {
lock.releaseRef();
}
}
private String getMountPoint(String storageUrl) {
String mountPoint = null;
synchronized(_storageMounts) {
mountPoint = _storageMounts.get(storageUrl);
if(mountPoint != null) {
return mountPoint;
}
URI uri;
try {
uri = new URI(storageUrl);
} catch (URISyntaxException e) {
s_logger.error("Invalid storage URL format ", e);
throw new CloudRuntimeException("Unable to create mount point due to invalid storage URL format " + storageUrl);
}
mountPoint = mount(File.separator + File.separator + uri.getHost() + uri.getPath(), _mountParent,
uri.getScheme(), uri.getQuery());
if(mountPoint == null) {
s_logger.error("Unable to create mount point for " + storageUrl);
return "/mnt/sec";
}
_storageMounts.put(storageUrl, mountPoint);
return mountPoint;
}
}
protected String mount(String path, String parent, String scheme, String query) {
String mountPoint = setupMountPoint(parent);
if (mountPoint == null) {
s_logger.warn("Unable to create a mount point");
return null;
}
Script script = null;
String result = null;
if (scheme.equals("cifs")) {
Script command = new Script(true, "mount", _timeout, s_logger);
command.add("-t", "cifs");
command.add(path);
command.add(mountPoint);
if (query != null) {
query = query.replace('&', ',');
command.add("-o", query);
}
result = command.execute();
}
if (result != null) {
s_logger.warn("Unable to mount " + path + " due to " + result);
File file = new File(mountPoint);
if (file.exists()) {
file.delete();
}
return null;
}
// Change permissions for the mountpoint
script = new Script(true, "chmod", _timeout, s_logger);
script.add("-R", "777", mountPoint);
result = script.execute();
if (result != null) {
s_logger.warn("Unable to set permissions for " + mountPoint + " due to " + result);
}
return mountPoint;
}
private String setupMountPoint(String parent) {
String mountPoint = null;
long mshostId = ManagementServerNode.getManagementServerId();
for (int i = 0; i < 10; i++) {
String mntPt = parent + File.separator + String.valueOf(mshostId) + "." + Integer.toHexString(_rand.nextInt(Integer.MAX_VALUE));
File file = new File(mntPt);
if (!file.exists()) {
if (_storage.mkdir(mntPt)) {
mountPoint = mntPt;
break;
}
}
s_logger.error("Unable to create mount: " + mntPt);
}
return mountPoint;
}
private String getSystemVMIsoFileNameOnDatastore() {
String version = this.getClass().getPackage().getImplementationVersion();
String fileName = "systemvm-" + version + ".iso";
return fileName.replace(':', '-');
}
private File getSystemVMPatchIsoFile() {
// locate systemvm.iso
URL url = this.getClass().getClassLoader().getResource("vms/systemvm.iso");
File isoFile = null;
if (url != null) {
isoFile = new File(url.getPath());
}
if(isoFile == null || !isoFile.exists()) {
isoFile = new File("/usr/share/cloudstack-common/vms/systemvm.iso");
}
assert(isoFile != null);
if(!isoFile.exists()) {
s_logger.error("Unable to locate systemvm.iso in your setup at " + isoFile.toString());
}
return isoFile;
}
private String getSecondaryStorageStoreUrl(long zoneId) {
String secUrl = null;
DataStore secStore = _dataStoreMgr.getImageStore(zoneId);
if (secStore != null) {
secUrl = secStore.getUri();
}
if (secUrl == null) {
s_logger.warn("Secondary storage uri couldn't be retrieved");
}
return secUrl;
}
/** /**
* Encapsulate GUID calculation in public method to allow access to test * Encapsulate GUID calculation in public method to allow access to test
* programs. Works by converting a string to a GUID using * programs. Works by converting a string to a GUID using
@ -371,10 +577,27 @@ public class HypervServerDiscoverer extends DiscovererBase implements
// Inherit Adapter.stop // Inherit Adapter.stop
// Inherit Adapter.start // Inherit Adapter.start
@Override @Override
public final boolean configure(final String name, public final boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
final Map<String, Object> params) throws ConfigurationException {
super.configure(name, params); super.configure(name, params);
_mountParent = (String) params.get(Config.MountParent.key());
if (_mountParent == null) {
_mountParent = File.separator + "mnt";
}
if (_instance != null) {
_mountParent = _mountParent + File.separator + _instance;
}
String value = (String)params.get("scripts.timeout");
_timeout = NumbersUtil.parseInt(value, 30) * 1000;
_storage = (StorageLayer)params.get(StorageLayer.InstanceConfigKey);
if (_storage == null) {
_storage = new JavaStorageLayer();
_storage.configure("StorageLayer", params);
}
// TODO: allow timeout on we HTTPRequests to be configured // TODO: allow timeout on we HTTPRequests to be configured
_agentMgr.registerForHostEvents(this, true, false, true); _agentMgr.registerForHostEvents(this, true, false, true);
_resourceMgr.registerResourceStateAdapter(this.getClass() _resourceMgr.registerResourceStateAdapter(this.getClass()

View File

@ -27,14 +27,20 @@ import java.nio.channels.SocketChannel;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random;
import java.util.UUID; import java.util.UUID;
import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException; import javax.naming.ConfigurationException;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.utils.identity.ManagementServerNode;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException; import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient; import org.apache.http.client.HttpClient;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity; import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.DefaultHttpClient;
@ -54,11 +60,12 @@ import com.cloud.agent.api.NetworkUsageCommand;
import com.cloud.agent.api.PingCommand; import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand; import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.PingTestCommand; import com.cloud.agent.api.PingTestCommand;
import com.cloud.agent.api.StartCommand;
import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand; import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.agent.api.StartupRoutingCommand.VmState;
import com.cloud.agent.api.StartupStorageCommand; import com.cloud.agent.api.StartupStorageCommand;
import com.cloud.agent.api.UnsupportedAnswer; import com.cloud.agent.api.UnsupportedAnswer;
import com.cloud.agent.api.StartupRoutingCommand.VmState;
import com.cloud.agent.api.check.CheckSshAnswer; import com.cloud.agent.api.check.CheckSshAnswer;
import com.cloud.agent.api.check.CheckSshCommand; import com.cloud.agent.api.check.CheckSshCommand;
import com.cloud.agent.api.routing.CreateIpAliasCommand; import com.cloud.agent.api.routing.CreateIpAliasCommand;
@ -88,6 +95,8 @@ import com.cloud.agent.api.to.FirewallRuleTO;
import com.cloud.agent.api.to.IpAddressTO; import com.cloud.agent.api.to.IpAddressTO;
import com.cloud.agent.api.to.PortForwardingRuleTO; import com.cloud.agent.api.to.PortForwardingRuleTO;
import com.cloud.agent.api.to.StaticNatRuleTO; import com.cloud.agent.api.to.StaticNatRuleTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.configuration.Config;
import com.cloud.dc.DataCenter.NetworkType; import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.host.Host.Type; import com.cloud.host.Host.Type;
import com.cloud.hypervisor.Hypervisor; import com.cloud.hypervisor.Hypervisor;
@ -98,19 +107,26 @@ import com.cloud.network.rules.FirewallRule;
import com.cloud.resource.ServerResource; import com.cloud.resource.ServerResource;
import com.cloud.resource.ServerResourceBase; import com.cloud.resource.ServerResourceBase;
import com.cloud.serializer.GsonHelper; import com.cloud.serializer.GsonHelper;
import com.cloud.storage.JavaStorageLayer;
import com.cloud.storage.StorageLayer;
import com.cloud.utils.FileUtil;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair; import com.cloud.utils.Pair;
import com.cloud.utils.StringUtils; import com.cloud.utils.StringUtils;
import com.cloud.utils.db.GlobalLock;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils; import com.cloud.utils.net.NetUtils;
import com.cloud.utils.script.Script;
import com.cloud.utils.ssh.SshHelper; import com.cloud.utils.ssh.SshHelper;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineName; import com.cloud.vm.VirtualMachineName;
import com.google.gson.Gson; import com.google.gson.Gson;
/** /**
* Implementation of dummy resource to be returned from discoverer. * Implementation of dummy resource to be returned from discoverer.
**/ **/
@Local(value = ServerResource.class)
public class HypervDirectConnectResource extends ServerResourceBase implements public class HypervDirectConnectResource extends ServerResourceBase implements ServerResource {
ServerResource {
public static final int DEFAULT_AGENT_PORT = 8250; public static final int DEFAULT_AGENT_PORT = 8250;
private static final Logger s_logger = Logger private static final Logger s_logger = Logger
.getLogger(HypervDirectConnectResource.class.getName()); .getLogger(HypervDirectConnectResource.class.getName());
@ -1259,7 +1275,6 @@ public class HypervDirectConnectResource extends ServerResourceBase implements
for(DhcpTO dhcpTo : dhcpTos) { for(DhcpTO dhcpTo : dhcpTos) {
args = args + dhcpTo.getRouterIp()+":"+dhcpTo.getGateway()+":"+dhcpTo.getNetmask()+":"+dhcpTo.getStartIpOfSubnet()+"-"; args = args + dhcpTo.getRouterIp()+":"+dhcpTo.getGateway()+":"+dhcpTo.getNetmask()+":"+dhcpTo.getStartIpOfSubnet()+"-";
} }
//File keyFile = mgr.getSystemVMKeyFile();
try { try {
Pair<Boolean, String> result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", getSystemVMKeyFile(), null, "/root/dnsmasq.sh " + args); Pair<Boolean, String> result = SshHelper.sshExecute(controlIp, DEFAULT_DOMR_SSHPORT, "root", getSystemVMKeyFile(), null, "/root/dnsmasq.sh " + args);
@ -1319,43 +1334,17 @@ public class HypervDirectConnectResource extends ServerResourceBase implements
protected void assignPublicIpAddress(final String vmName, final String privateIpAddress, final String publicIpAddress, final boolean add, final boolean firstIP, protected void assignPublicIpAddress(final String vmName, final String privateIpAddress, final String publicIpAddress, final boolean add, final boolean firstIP,
final boolean sourceNat, final String vlanId, final String vlanGateway, final String vlanNetmask, final String vifMacAddress) throws Exception { final boolean sourceNat, final String vlanId, final String vlanGateway, final String vlanNetmask, final String vifMacAddress) throws Exception {
//String publicNeworkName = HypervisorHostHelper.getPublicNetworkNamePrefix(vlanId);
//Pair<Integer, VirtualDevice> publicNicInfo = vmMo.getNicDeviceIndex(publicNeworkName);
if (s_logger.isDebugEnabled()) {
//s_logger.debug("Find public NIC index, public network name: " + publicNeworkName + ", index: " + publicNicInfo.first());
}
boolean addVif = false; boolean addVif = false;
boolean removeVif = false; boolean removeVif = false;
if (add ) { // && publicNicInfo.first().intValue() == -1) { if (add) {
if (s_logger.isDebugEnabled()) { if (s_logger.isDebugEnabled()) {
s_logger.debug("Plug new NIC to associate" + privateIpAddress + " to " + publicIpAddress); s_logger.debug("Plug new NIC to associate" + privateIpAddress + " to " + publicIpAddress);
} }
addVif = true; addVif = true;
} else if (!add && firstIP) { } else if (!add && firstIP) {
removeVif = true; removeVif = true;
if (s_logger.isDebugEnabled()) {
//s_logger.debug("Unplug NIC " + publicNicInfo.first());
}
} }
/* if (addVif) {
plugPublicNic(vmMo, vlanId, vifMacAddress);
publicNicInfo = vmMo.getNicDeviceIndex(publicNeworkName);
if (publicNicInfo.first().intValue() >= 0) {
networkUsage(privateIpAddress, "addVif", "eth" + publicNicInfo.first());
}
}
*/
/* if (publicNicInfo.first().intValue() < 0) {
String msg = "Failed to find DomR VIF to associate/disassociate IP with.";
s_logger.error(msg);
throw new InternalErrorException(msg);
}
*/
String args = null; String args = null;
if (add) { if (add) {
@ -1558,25 +1547,6 @@ public class HypervDirectConnectResource extends ServerResourceBase implements
return null; return null;
} }
private File getSystemVMPatchIsoFile() {
// locate systemvm.iso
URL url = this.getClass().getClassLoader().getResource("vms/systemvm.iso");
File isoFile = null;
if (url != null) {
isoFile = new File(url.getPath());
}
if(isoFile == null || !isoFile.exists()) {
isoFile = new File("/usr/share/cloudstack-common/vms/systemvm.iso");
}
assert(isoFile != null);
if(!isoFile.exists()) {
s_logger.error("Unable to locate systemvm.iso in your setup at " + isoFile.toString());
}
return isoFile;
}
public File getSystemVMKeyFile() { public File getSystemVMKeyFile() {
URL url = this.getClass().getClassLoader().getResource("scripts/vm/systemvm/id_rsa.cloud"); URL url = this.getClass().getClassLoader().getResource("scripts/vm/systemvm/id_rsa.cloud");
File keyFile = null; File keyFile = null;
@ -1721,6 +1691,7 @@ public class HypervDirectConnectResource extends ServerResourceBase implements
public void setRunLevel(final int level) { public void setRunLevel(final int level) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
} }
protected String connect(final String vmName, final String ipAddress, final int port) { protected String connect(final String vmName, final String ipAddress, final int port) {
long startTick = System.currentTimeMillis(); long startTick = System.currentTimeMillis();
@ -1735,9 +1706,10 @@ public class HypervDirectConnectResource extends ServerResourceBase implements
sch = SocketChannel.open(); sch = SocketChannel.open();
sch.configureBlocking(true); sch.configureBlocking(true);
sch.socket().setSoTimeout(5000); sch.socket().setSoTimeout(5000);
// we need to connect to the public ip address to check the status of the VM
/*
InetSocketAddress addr = new InetSocketAddress(ipAddress, port); InetSocketAddress addr = new InetSocketAddress(ipAddress, port);
sch.connect(addr); sch.connect(addr);*/
return null; return null;
} catch (IOException e) { } catch (IOException e) {
s_logger.info("Could not connect to " + ipAddress + " due to " + e.toString()); s_logger.info("Could not connect to " + ipAddress + " due to " + e.toString());

View File

@ -28,7 +28,6 @@ import java.io.OutputStreamWriter;
import java.net.URL; import java.net.URL;
import java.nio.channels.Channels; import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel; import java.nio.channels.ReadableByteChannel;
import java.nio.file.Files;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -43,6 +42,7 @@ import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import com.google.common.io.Files;
import com.google.gson.Gson; import com.google.gson.Gson;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
@ -265,7 +265,7 @@ public class HypervDirectConnectResourceTest {
String newFileURIJSON = null; String newFileURIJSON = null;
File testVolTemp = new File(dstPath + File.separator + dstFileName); File testVolTemp = new File(dstPath + File.separator + dstFileName);
try { try {
Files.copy(srcFile.toPath(), testVolTemp.toPath()); Files.copy(srcFile, testVolTemp);
} catch (IOException e) { } catch (IOException e) {
; // NOP ; // NOP
} }
@ -671,7 +671,7 @@ public class HypervDirectConnectResourceTest {
+ "\"," + "\","
+ "\"type\":\"ROOT\",\"id\":9,\"size\":0}}"; + "\"type\":\"ROOT\",\"id\":9,\"size\":0}}";
DestroyCommand cmd = s_gson.fromJson(sample2, DestroyCommand.class); DestroyCommand cmd = s_gson.fromJson(sample2, DestroyCommand.class);
Answer ans = (Answer) s_hypervresource.executeRequest(cmd); Answer ans = s_hypervresource.executeRequest(cmd);
Assert.assertTrue(ans.getDetails(), ans.getResult()); Assert.assertTrue(ans.getDetails(), ans.getResult());
} }
@ -844,25 +844,25 @@ public class HypervDirectConnectResourceTest {
params.get("TestCoreMhz"), params.get("TestCoreMhz"),
params.get("TestMemoryMb"), params.get("TestMemoryMb"),
params.get("TestDom0MinMemoryMb"), params.get("TestDom0MinMemoryMb"),
s_gson.toJson((String) params.get("zone")), s_gson.toJson(params.get("zone")),
s_gson.toJson((String) params.get("pod")), s_gson.toJson(params.get("pod")),
s_gson.toJson((String) params.get("cluster")), s_gson.toJson(params.get("cluster")),
s_gson.toJson((String) params.get("ipaddress")), s_gson.toJson(params.get("ipaddress")),
s_gson.toJson((String) params s_gson.toJson(params
.get("private.mac.address")), .get("private.mac.address")),
s_gson.toJson((String) params.get( s_gson.toJson(params.get(
"private.ip.netmask")), "private.ip.netmask")),
s_gson.toJson((String) params.get("ipaddress")), s_gson.toJson(params.get("ipaddress")),
s_gson.toJson((String) params.get( s_gson.toJson(params.get(
"private.ip.netmask")), "private.ip.netmask")),
s_gson.toJson((String) params s_gson.toJson(params
.get("private.mac.address")), .get("private.mac.address")),
s_gson.toJson((String) params.get( s_gson.toJson(params.get(
"gateway.ip.address")), "gateway.ip.address")),
s_gson.toJson((String) params.get("ipaddress")), s_gson.toJson(params.get("ipaddress")),
s_gson.toJson((String) params s_gson.toJson(params
.get("DefaultVirtualDiskFolder")), .get("DefaultVirtualDiskFolder")),
s_gson.toJson((String) params s_gson.toJson(params
.get("DefaultVirtualDiskFolder")), .get("DefaultVirtualDiskFolder")),
s_gson.toJson(totalSpace), s_gson.toJson(totalSpace),
s_gson.toJson(usableCapacity) s_gson.toJson(usableCapacity)