mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
1148 lines
56 KiB
C#
1148 lines
56 KiB
C#
// 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 System.Xml;
|
|
using Xunit;
|
|
|
|
namespace ServerResource.Tests
|
|
{
|
|
public class HypervResourceControllerTest
|
|
{
|
|
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 WmiCallsV2 wmiCallsV2 = new WmiCallsV2();
|
|
|
|
private static ILog s_logger = LogManager.GetLogger(typeof(HypervResourceControllerTest));
|
|
|
|
/// <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 HypervResourceControllerTest()
|
|
{
|
|
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);
|
|
|
|
|
|
// Delete all temporary files in local folder save the testVolWorks
|
|
foreach (var file in testPoolDir.GetFiles())
|
|
{
|
|
if (file.FullName == testVolWorks.FullName)
|
|
{
|
|
continue;
|
|
}
|
|
file.Delete();
|
|
file.Refresh();
|
|
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 ...
|
|
testSampleVolumeTempURIJSON = CreateTestDiskImageFromExistingImage(testVolWorks, testLocalStorePath, testSampleVolumeTempUUID);
|
|
s_logger.Info("Created " + testSampleVolumeTempURIJSON);
|
|
testSampleVolumeCorruptURIJSON = CreateTestDiskImageFromExistingImage(testVolWorks, testLocalStorePath, testSampleVolumeCorruptUUID);
|
|
s_logger.Info("Created " + testSampleVolumeCorruptURIJSON);
|
|
CreateTestDiskImageFromExistingImage(testVolWorks, testLocalStorePath, testSampleTemplateUUID);
|
|
testSampleTemplateURLJSON = JsonConvert.SerializeObject(testSampleTemplateUUID);
|
|
s_logger.Info("Created " + testSampleTemplateURLJSON + " in local storage.");
|
|
|
|
// ... including a secondary storage template:
|
|
CreateTestDiskImageFromExistingImage(testVolWorks, testSecondarStoreDir.FullName, "af39aa7f-2b12-37e1-86d3-e23f2f005101.vhdx");
|
|
s_logger.Info("Created " + "af39aa7f-2b12-37e1-86d3-e23f2f005101.vhdx" + " in secondary (NFS) 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(Skip="these are functional tests")]
|
|
public void TestPrimaryStorageDownloadCommandHTTP()
|
|
{
|
|
string downloadURI = "https://s3-eu-west-1.amazonaws.com/cshv3eu/SmallDisk.vhdx";
|
|
corePrimaryStorageDownloadCommandTestCycle(downloadURI);
|
|
}
|
|
|
|
private void corePrimaryStorageDownloadCommandTestCycle(string downloadURI)
|
|
{
|
|
// Arrange
|
|
HypervResourceController rsrcServer = new HypervResourceController();
|
|
dynamic jsonPSDCmd = JsonConvert.DeserializeObject(samplePrimaryDownloadCommand());
|
|
jsonPSDCmd.url = downloadURI;
|
|
|
|
// Act
|
|
dynamic jsonResult = rsrcServer.PrimaryStorageDownloadCommand(jsonPSDCmd);
|
|
|
|
// Assert
|
|
JObject ansAsProperty = jsonResult[0];
|
|
dynamic ans = ansAsProperty.GetValue(CloudStackTypes.PrimaryStorageDownloadAnswer);
|
|
Assert.True((bool)ans.result, "PrimaryStorageDownloadCommand did not succeed " + ans.details);
|
|
|
|
// Test that URL of downloaded template works for file creation.
|
|
dynamic jsonCreateCmd = JsonConvert.DeserializeObject(CreateCommandSample());
|
|
jsonCreateCmd.templateUrl = ans.installPath;
|
|
dynamic jsonAns2 = rsrcServer.CreateCommand(jsonCreateCmd);
|
|
JObject ansAsProperty2 = jsonAns2[0];
|
|
dynamic ans2 = ansAsProperty2.GetValue(CloudStackTypes.CreateAnswer);
|
|
|
|
Assert.True((bool)ans2.result, (string)ans2.details);
|
|
|
|
FileInfo newFile = new FileInfo((string)ans2.volume.path);
|
|
Assert.True(newFile.Length > 0, "The new file should have a size greater than zero");
|
|
newFile.Delete();
|
|
}
|
|
|
|
private string samplePrimaryDownloadCommand()
|
|
{
|
|
String cmdJson = "{\"localPath\":" + testLocalStorePathJSON +
|
|
",\"poolUuid\":\"" + testLocalStoreUUID + "\",\"poolId\":201," +
|
|
"\"secondaryStorageUrl\":\"nfs://10.70.176.36/mnt/cshv3/secondarystorage\"," +
|
|
"\"primaryStorageUrl\":\"nfs://" + HypervResourceController.config.StorageIpAddress + "E:\\\\Disks\\\\Disks\"," +
|
|
"\"url\":\"nfs://10.70.176.36/mnt/cshv3/secondarystorage/template/tmpl//2/204//af39aa7f-2b12-37e1-86d3-e23f2f005101.vhdx\"," +
|
|
"\"format\":\"VHDX\",\"accountId\":2,\"name\":\"204-2-5a1db1ac-932b-3e7e-a0e8-5684c72cb862\"" +
|
|
",\"contextMap\":{},\"wait\":10800}";
|
|
return cmdJson;
|
|
}
|
|
|
|
public string CreateCommandSample()
|
|
{
|
|
String sample = "{\"volId\":17,\"pool\":{\"id\":201,\"uuid\":\"" + testLocalStoreUUID + "\",\"host\":\"" + HypervResourceController.config.StorageIpAddress + "\"" +
|
|
",\"path\":" + testLocalStorePathJSON + ",\"port\":0,\"type\":\"Filesystem\"},\"diskCharacteristics\":{\"size\":0," +
|
|
"\"tags\":[],\"type\":\"ROOT\",\"name\":\"ROOT-15\",\"useLocalStorage\":true,\"recreatable\":true,\"diskOfferingId\":11," +
|
|
"\"volumeId\":17,\"hyperType\":\"Hyperv\"},\"templateUrl\":" + testSampleTemplateURLJSON + ",\"wait\":0}";
|
|
return sample;
|
|
}
|
|
|
|
[Fact(Skip="these are functional tests")]
|
|
public void TestDestroyCommand()
|
|
{
|
|
// Arrange
|
|
String sampleVolume = getSampleVolumeObjectTO();
|
|
String destroyCmd = //"{\"volume\":" + getSampleVolumeObjectTO() + "}";
|
|
"{\"volume\":{\"name\":\"" + testSampleVolumeTempUUIDNoExt
|
|
+ "\",\"storagePoolType\":\"Filesystem\","
|
|
+ "\"mountPoint\":"
|
|
+ testLocalStorePathJSON
|
|
+ ",\"path\":" + testSampleVolumeTempURIJSON
|
|
+ ",\"storagePoolUuid\":\"" + testLocalStoreUUID
|
|
+ "\","
|
|
+ "\"type\":\"ROOT\",\"id\":9,\"size\":0}}";
|
|
|
|
HypervResourceController rsrcServer = new HypervResourceController();
|
|
dynamic jsonDestroyCmd = JsonConvert.DeserializeObject(destroyCmd);
|
|
|
|
// Act
|
|
dynamic destroyAns = rsrcServer.DestroyCommand(jsonDestroyCmd);
|
|
|
|
// Assert
|
|
JObject ansAsProperty2 = destroyAns[0];
|
|
dynamic ans = ansAsProperty2.GetValue(CloudStackTypes.Answer);
|
|
String path = jsonDestroyCmd.volume.path;
|
|
Assert.True((bool)ans.result, "DestroyCommand did not succeed " + ans.details);
|
|
Assert.True(!File.Exists(path), "Failed to delete file " + path);
|
|
}
|
|
|
|
[Fact(Skip="these are functional tests")]
|
|
public void TestCreateCommand()
|
|
{
|
|
// 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();
|
|
|
|
Assert.True(Directory.Exists(testLocalStorePath));
|
|
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);
|
|
|
|
JObject ansAsProperty2 = jsonResult[0];
|
|
dynamic ans = ansAsProperty2.GetValue(CloudStackTypes.CreateAnswer);
|
|
Assert.NotNull(ans);
|
|
Assert.True((bool)ans.result, "Failed to CreateCommand due to " + (string)ans.result);
|
|
Assert.Equal(Directory.GetFiles(testLocalStorePath).Length, fileCount + 1);
|
|
FileInfo newFile = new FileInfo((string)ans.volume.path);
|
|
Assert.True(newFile.Length > 0, "The new file should have a size greater than zero");
|
|
newFile.Delete();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Possible additional tests: place an ISO in the drive
|
|
/// </summary>
|
|
[Fact(Skip="these are functional tests")]
|
|
public void TestStartStopCommand()
|
|
{
|
|
string vmName = TestStartCommand();
|
|
TestStopCommand(vmName);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
[Fact(Skip="these are functional tests")]
|
|
public void TestCopyCommandFromCifs()
|
|
{
|
|
// Arrange
|
|
string sampleCopyCommandForTemplateDownload =
|
|
#region string_literal
|
|
// org.apache.cloudstack.storage.command.CopyCommand
|
|
"{\"srcTO\":" +
|
|
"{\"org.apache.cloudstack.storage.to.TemplateObjectTO\":" +
|
|
"{\"path\":\"" + testCifsPath + "\"," +
|
|
"\"origUrl\":\"http://10.147.28.7/templates/5d67394c-4efd-4b62-966b-51aa53b35277.vhd.bz2\"," +
|
|
"\"uuid\":\"7e4ca941-cb1b-4113-ab9e-043960d0fb10\"," +
|
|
"\"id\":206," +
|
|
"\"format\":\"VHDX\"," +
|
|
"\"accountId\":2," +
|
|
"\"checksum\":\"4b31e2846cc67fc10ea7281986519a54\"," +
|
|
"\"hvm\":true," +
|
|
"\"displayText\":\"OS031\"," +
|
|
"\"imageDataStore\":" +
|
|
"{\"com.cloud.agent.api.to.NfsTO\":" +
|
|
"{\"_url\":\"" + testCifsUrl + "\"," + // Unique item here
|
|
"\"_role\":\"Image\"}" +
|
|
"}," + // end of imageDataStore
|
|
"\"hypervisorType\":\"Hyperv\"," +
|
|
"\"name\":\"" + testS3TemplateName + "\"}" +
|
|
"}," + // end of srcTO
|
|
"\"destTO\":" +
|
|
"{\"org.apache.cloudstack.storage.to.TemplateObjectTO\":" +
|
|
"{" +
|
|
"\"origUrl\":\"http://10.147.28.7/templates/5d67394c-4efd-4b62-966b-51aa53b35277.vhd.bz2\"," +
|
|
"\"uuid\":\"7e4ca941-cb1b-4113-ab9e-043960d0fb10\"," +
|
|
"\"id\":206," +
|
|
"\"format\":\"VHDX\"," +
|
|
"\"accountId\":2," +
|
|
"\"checksum\":\"4b31e2846cc67fc10ea7281986519a54\"," +
|
|
"\"hvm\":true," +
|
|
"\"displayText\":\"Test of CIFS Download\"," +
|
|
"\"imageDataStore\":" + getSamplePrimaryDataStoreInfo() + "," + // end of imageDataStore
|
|
"\"name\":\"" + testS3TemplateName + "\"," +
|
|
"\"hypervisorType\":\"Hyperv\"}" +
|
|
"}," +// end of destTO
|
|
"\"wait\":10800}"; // end of CopyCommand
|
|
#endregion
|
|
|
|
HypervResourceController rsrcServer;
|
|
dynamic jsonDownloadCopyCmd;
|
|
string dwnldDest;
|
|
dynamic jsonCloneCopyCmd;
|
|
string newVolName;
|
|
CopyCommandTestSetupCifs(null, sampleCopyCommandForTemplateDownload, out rsrcServer, out jsonDownloadCopyCmd, out dwnldDest, out jsonCloneCopyCmd, out newVolName);
|
|
|
|
// Act & Assert
|
|
DownloadTemplateToPrimaryStorage(rsrcServer, jsonDownloadCopyCmd, dwnldDest);
|
|
|
|
// Repeat to verify ability to detect existing file.
|
|
DownloadTemplateToPrimaryStorage(rsrcServer, jsonDownloadCopyCmd, dwnldDest);
|
|
|
|
File.Delete(dwnldDest);
|
|
}
|
|
|
|
[Fact(Skip="these are functional tests")]
|
|
public void TestCopyCommand()
|
|
{
|
|
// Arrange
|
|
string sampleCopyCommandToCreateVolumeFromTemplate =
|
|
#region string_literal
|
|
// org.apache.cloudstack.storage.command.CopyCommand
|
|
"{\"srcTO\":" +
|
|
"{\"org.apache.cloudstack.storage.to.TemplateObjectTO\":" +
|
|
"{" +
|
|
"\"origUrl\":\"http://people.apache.org/~bhaisaab/vms/ttylinux_pv.vhd\"," +
|
|
"\"uuid\":\"9873f1c0-bdcc-11e2-8baa-ea85dab5fcd0\"," +
|
|
"\"id\":5," +
|
|
"\"format\":\"VHDX\"," +
|
|
"\"accountId\":1," +
|
|
"\"checksum\":\"4b31e2846cc67fc10ea7281986519a54\"," +
|
|
"\"hvm\":false," +
|
|
"\"displayText\":\"tiny Linux\"," +
|
|
"\"imageDataStore\":" + getSamplePrimaryDataStoreInfo() + "," +
|
|
"\"name\":\"" + testS3TemplateName + "\"}" +
|
|
"}," + // end of srcTO
|
|
"\"destTO\":" +
|
|
"{\"org.apache.cloudstack.storage.to.VolumeObjectTO\":" +
|
|
"{\"uuid\":\"19ae8e67-cb2c-4ab4-901e-e0b864272b59\"," +
|
|
"\"volumeType\":\"ROOT\"," +
|
|
"\"dataStore\":" + getSamplePrimaryDataStoreInfo() + "," +
|
|
"\"name\":\"ROOT-5\"," +
|
|
"\"size\":52428800," +
|
|
"\"volumeId\":10," +
|
|
"\"vmName\":\"i-3-5-VM\"," +
|
|
"\"accountId\":3," +
|
|
"\"id\":10 }" +
|
|
"}," + // end of destTO
|
|
"\"wait\":0}"; // end of Copy Command
|
|
#endregion
|
|
//"name":"ROOT-8","size":140616708,"volumeId":8,"vmName":"s-8-VM","accountId":1,"id":8}},"contextMap":{},"wait":0}
|
|
|
|
string sampleCopyCommandForTemplateDownload =
|
|
#region string_literal
|
|
// org.apache.cloudstack.storage.command.CopyCommand
|
|
"{\"srcTO\":" +
|
|
"{\"org.apache.cloudstack.storage.to.TemplateObjectTO\":" +
|
|
"{\"path\":\"" + testS3TemplateName + ".vhdx" + "\"," +
|
|
"\"origUrl\":\"http://10.147.28.7/templates/5d67394c-4efd-4b62-966b-51aa53b35277.vhd.bz2\"," +
|
|
"\"uuid\":\"7e4ca941-cb1b-4113-ab9e-043960d0fb10\"," +
|
|
"\"id\":206," +
|
|
"\"format\":\"VHDX\"," +
|
|
"\"accountId\":2," +
|
|
"\"checksum\":\"4b31e2846cc67fc10ea7281986519a54\"," +
|
|
"\"hvm\":true," +
|
|
"\"displayText\":\"OS031\"," +
|
|
"\"imageDataStore\":" +
|
|
"{\"com.cloud.agent.api.to.S3TO\":" +
|
|
"{\"id\":1," +
|
|
"\"uuid\":\"95a64c8f-2128-4502-b5b4-0d7aa77406d2\"," +
|
|
"\"accessKey\":\"" + AgentSettings.Default.testS3AccessKey + "\"," +
|
|
"\"secretKey\":\"" + AgentSettings.Default.testS3SecretKey + "\"," +
|
|
"\"endPoint\":\"" + AgentSettings.Default.testS3Endpoint + "\"," +
|
|
"\"bucketName\":\"" + AgentSettings.Default.testS3Bucket + "\"," +
|
|
"\"httpsFlag\":false," +
|
|
"\"created\":\"May 19, 2013 4:17:25 PM\"}" +
|
|
"}," + // end of imageDataStore
|
|
"\"name\":\"" + testS3TemplateName + "\"}" +
|
|
"}," + // end of srcTO
|
|
"\"destTO\":" +
|
|
"{\"org.apache.cloudstack.storage.to.TemplateObjectTO\":" +
|
|
"{" +
|
|
"\"origUrl\":\"http://10.147.28.7/templates/5d67394c-4efd-4b62-966b-51aa53b35277.vhd.bz2\"," +
|
|
"\"uuid\":\"7e4ca941-cb1b-4113-ab9e-043960d0fb10\"," +
|
|
"\"id\":206," +
|
|
"\"format\":\"VHDX\"," +
|
|
"\"accountId\":2," +
|
|
"\"checksum\":\"4b31e2846cc67fc10ea7281986519a54\"," +
|
|
"\"hvm\":true," +
|
|
"\"displayText\":\"OS031\"," +
|
|
"\"imageDataStore\":" + getSamplePrimaryDataStoreInfo() + "," + // end of imageDataStore
|
|
"\"name\":\"" + testS3TemplateName + "\"}" +
|
|
"}," +// end of destTO
|
|
"\"wait\":10800}"; // end of CopyCommand
|
|
#endregion
|
|
|
|
HypervResourceController rsrcServer;
|
|
dynamic jsonDownloadCopyCmd;
|
|
string dwnldDest;
|
|
dynamic jsonCloneCopyCmd;
|
|
string newVolName;
|
|
CopyCommandTestSetup(sampleCopyCommandToCreateVolumeFromTemplate, sampleCopyCommandForTemplateDownload, out rsrcServer, out jsonDownloadCopyCmd, out dwnldDest, out jsonCloneCopyCmd, out newVolName);
|
|
|
|
// Act & Assert
|
|
DownloadTemplateToPrimaryStorage(rsrcServer, jsonDownloadCopyCmd, dwnldDest);
|
|
CreateVolumeFromTemplate(rsrcServer, jsonCloneCopyCmd, newVolName);
|
|
|
|
// Repeat to verify ability to detect existing file.
|
|
DownloadTemplateToPrimaryStorage(rsrcServer, jsonDownloadCopyCmd, dwnldDest);
|
|
|
|
File.Delete(dwnldDest);
|
|
File.Delete(newVolName);
|
|
}
|
|
|
|
private static void CreateVolumeFromTemplate(HypervResourceController rsrcServer, dynamic jsonCloneCopyCmd, string newVolName)
|
|
{
|
|
dynamic copyResult = rsrcServer.CopyCommand(jsonCloneCopyCmd);
|
|
|
|
// Assert
|
|
Assert.NotNull(copyResult[0][CloudStackTypes.CopyCmdAnswer]);
|
|
Assert.True((bool)copyResult[0][CloudStackTypes.CopyCmdAnswer].result, "CopyCommand did not succeed " + copyResult[0][CloudStackTypes.CopyCmdAnswer].details);
|
|
Assert.True(File.Exists(newVolName), "CopyCommand failed to generate " + newVolName);
|
|
}
|
|
|
|
private static void DownloadTemplateToPrimaryStorage(HypervResourceController rsrcServer, dynamic jsonDownloadCopyCmd, string dwnldDest)
|
|
{
|
|
dynamic dwnldResult = rsrcServer.CopyCommand(jsonDownloadCopyCmd);
|
|
|
|
// Assert
|
|
Assert.NotNull(dwnldResult[0][CloudStackTypes.CopyCmdAnswer]);
|
|
Assert.True((bool)dwnldResult[0][CloudStackTypes.CopyCmdAnswer].result, "CopyCommand did not succeed " + dwnldResult[0][CloudStackTypes.CopyCmdAnswer].details);
|
|
Assert.True(File.Exists(dwnldDest), "CopyCommand failed to generate " + dwnldDest);
|
|
}
|
|
|
|
[Fact(Skip="these are functional tests")]
|
|
public void TestCopyCommandBz2Img()
|
|
{
|
|
// Arrange
|
|
string sampleCopyCommandToCreateVolumeFromTemplate =
|
|
#region string_literal
|
|
// org.apache.cloudstack.storage.command.CopyCommand
|
|
"{\"srcTO\":" +
|
|
"{\"org.apache.cloudstack.storage.to.TemplateObjectTO\":" +
|
|
"{" +
|
|
"\"origUrl\":\"http://people.apache.org/~bhaisaab/vms/ttylinux_pv.vhd\"," +
|
|
"\"uuid\":\"9873f1c0-bdcc-11e2-8baa-ea85dab5fcd0\"," +
|
|
"\"id\":5," +
|
|
"\"format\":\"VHD\"," +
|
|
"\"accountId\":1," +
|
|
"\"checksum\":\"f613f38c96bf039f2e5cbf92fa8ad4f8\"," +
|
|
"\"hvm\":false," +
|
|
"\"displayText\":\"tiny Linux\"," +
|
|
"\"imageDataStore\":" + getSamplePrimaryDataStoreInfo() + "," +
|
|
"\"name\":\"" + testSystemVMTemplateNameNoExt + "\"}" +
|
|
"}," + // end of srcTO
|
|
"\"destTO\":" +
|
|
"{\"org.apache.cloudstack.storage.to.VolumeObjectTO\":" +
|
|
"{\"uuid\":\"19ae8e67-cb2c-4ab4-901e-e0b864272b59\"," +
|
|
"\"volumeType\":\"ROOT\"," +
|
|
"\"dataStore\":" + getSamplePrimaryDataStoreInfo() + "," +
|
|
"\"name\":\"ROOT-5\"," +
|
|
"\"size\":52428800," +
|
|
"\"volumeId\":10," +
|
|
"\"vmName\":\"i-3-5-VM\"," +
|
|
"\"accountId\":1," +
|
|
"\"id\":10}" +
|
|
"}," + // end of destTO
|
|
"\"wait\":0}"; // end of Copy Command
|
|
#endregion
|
|
|
|
string sampleCopyCommandForTemplateDownload =
|
|
#region string_literal
|
|
// org.apache.cloudstack.storage.command.CopyCommand
|
|
"{\"srcTO\":" +
|
|
"{\"org.apache.cloudstack.storage.to.TemplateObjectTO\":" +
|
|
"{\"path\":\"" + testSystemVMTemplateName + "\"," +
|
|
"\"origUrl\":\"http://10.147.28.7/templates/5d67394c-4efd-4b62-966b-51aa53b35277.vhd.bz2\"," +
|
|
"\"uuid\":\"7e4ca941-cb1b-4113-ab9e-043960d0fb10\"," +
|
|
"\"id\":206," +
|
|
"\"format\":\"VHD\"," +
|
|
"\"accountId\":1," +
|
|
"\"checksum\": \"f613f38c96bf039f2e5cbf92fa8ad4f8\"," +
|
|
"\"hvm\":true," +
|
|
"\"displayText\":\"OS031\"," +
|
|
"\"imageDataStore\":" +
|
|
"{\"com.cloud.agent.api.to.S3TO\":" +
|
|
"{\"id\":1," +
|
|
"\"uuid\":\"95a64c8f-2128-4502-b5b4-0d7aa77406d2\"," +
|
|
"\"accessKey\":\"" + AgentSettings.Default.testS3AccessKey + "\"," +
|
|
"\"secretKey\":\"" + AgentSettings.Default.testS3SecretKey + "\"," +
|
|
"\"endPoint\":\"" + AgentSettings.Default.testS3Endpoint + "\"," +
|
|
"\"bucketName\":\"" + AgentSettings.Default.testS3Bucket + "\"," +
|
|
"\"httpsFlag\":false," +
|
|
"\"created\":\"May 19, 2013 4:17:25 PM\"}" +
|
|
"}," + // end of imageDataStore
|
|
"\"name\":\"" + testSystemVMTemplateNameNoExt + "\"}" +
|
|
"}," + // end of srcTO
|
|
"\"destTO\":" +
|
|
"{\"org.apache.cloudstack.storage.to.TemplateObjectTO\":" +
|
|
"{" +
|
|
"\"origUrl\":\"http://10.147.28.7/templates/5d67394c-4efd-4b62-966b-51aa53b35277.vhd.bz2\"," +
|
|
"\"uuid\":\"7e4ca941-cb1b-4113-ab9e-043960d0fb10\"," +
|
|
"\"id\":206," +
|
|
"\"format\":\"VHD\"," +
|
|
"\"accountId\":1," +
|
|
"\"checksum\": \"f613f38c96bf039f2e5cbf92fa8ad4f8\"," +
|
|
"\"hvm\":true," +
|
|
"\"displayText\":\"OS031\"," +
|
|
"\"imageDataStore\":" + getSamplePrimaryDataStoreInfo() + "," + // end of imageDataStore
|
|
"\"name\":\"" + testSystemVMTemplateNameNoExt + "\"}" +
|
|
"}," +// end of destTO
|
|
"\"wait\":10800}"; // end of CopyCommand
|
|
#endregion
|
|
|
|
HypervResourceController rsrcServer;
|
|
dynamic jsonDownloadCopyCmd;
|
|
string dwnldDest;
|
|
dynamic jsonCloneCopyCmd;
|
|
string newVolName;
|
|
CopyCommandTestSetup(sampleCopyCommandToCreateVolumeFromTemplate, sampleCopyCommandForTemplateDownload, out rsrcServer, out jsonDownloadCopyCmd, out dwnldDest, out jsonCloneCopyCmd, out newVolName);
|
|
|
|
// Act & Assert
|
|
DownloadTemplateToPrimaryStorage(rsrcServer, jsonDownloadCopyCmd, dwnldDest);
|
|
CreateVolumeFromTemplate(rsrcServer, jsonCloneCopyCmd, newVolName);
|
|
|
|
File.Delete(dwnldDest);
|
|
File.Delete(newVolName);
|
|
}
|
|
|
|
private static void CopyCommandTestSetup(string sampleCopyCommandToCreateVolumeFromTemplate, string sampleCopyCommandForTemplateDownload, out HypervResourceController rsrcServer, out dynamic jsonDownloadCopyCmd, out string dwnldDest, out dynamic jsonCloneCopyCmd, out string newVolName)
|
|
{
|
|
rsrcServer = new HypervResourceController();
|
|
jsonDownloadCopyCmd = JsonConvert.DeserializeObject(sampleCopyCommandForTemplateDownload);
|
|
TemplateObjectTO dwnldTemplate = TemplateObjectTO.ParseJson(jsonDownloadCopyCmd.destTO);
|
|
dwnldDest = dwnldTemplate.FullFileName;
|
|
|
|
jsonCloneCopyCmd = JsonConvert.DeserializeObject(sampleCopyCommandToCreateVolumeFromTemplate);
|
|
VolumeObjectTO newVol = VolumeObjectTO.ParseJson(jsonCloneCopyCmd.destTO);
|
|
newVol.format = dwnldTemplate.format;
|
|
newVolName = dwnldTemplate.FullFileName;
|
|
|
|
if (File.Exists(dwnldDest))
|
|
{
|
|
File.Delete(dwnldDest);
|
|
}
|
|
if (File.Exists(newVolName))
|
|
{
|
|
File.Delete(newVolName);
|
|
}
|
|
}
|
|
|
|
private static void CopyCommandTestSetupCifs(string sampleCopyCommandToCreateVolumeFromTemplate, string sampleCopyCommandForTemplateDownload, out HypervResourceController rsrcServer, out dynamic jsonDownloadCopyCmd, out string dwnldDest, out dynamic jsonCloneCopyCmd, out string newVolName)
|
|
{
|
|
rsrcServer = new HypervResourceController();
|
|
jsonDownloadCopyCmd = JsonConvert.DeserializeObject(sampleCopyCommandForTemplateDownload);
|
|
TemplateObjectTO dwnldTemplate = TemplateObjectTO.ParseJson(jsonDownloadCopyCmd.destTO);
|
|
dwnldDest = dwnldTemplate.FullFileName;
|
|
|
|
if (File.Exists(dwnldDest))
|
|
{
|
|
File.Delete(dwnldDest);
|
|
}
|
|
newVolName = null;
|
|
jsonCloneCopyCmd = null;
|
|
}
|
|
|
|
[Fact(Skip="these are functional tests")]
|
|
public void TestModifyStoragePoolCommand()
|
|
{
|
|
// Create dummy folder
|
|
String folderName = Path.Combine(".", "Dummy");
|
|
if (!Directory.Exists(folderName))
|
|
{
|
|
Directory.CreateDirectory(folderName);
|
|
}
|
|
|
|
var pool = new
|
|
{ // From java class StorageFilerTO
|
|
type = Enum.GetName(typeof(StoragePoolType), StoragePoolType.Filesystem),
|
|
host = "127.0.0.1",
|
|
port = -1,
|
|
path = folderName,
|
|
uuid = Guid.NewGuid().ToString(),
|
|
userInfo = string.Empty // Used in future to hold credential
|
|
};
|
|
|
|
var cmd = new
|
|
{
|
|
add = true,
|
|
pool = pool,
|
|
localPath = folderName
|
|
};
|
|
JToken tok = JToken.FromObject(cmd);
|
|
HypervResourceController controller = new HypervResourceController();
|
|
|
|
// Act
|
|
dynamic jsonResult = controller.ModifyStoragePoolCommand(tok);
|
|
|
|
// Assert
|
|
dynamic ans = jsonResult[0][CloudStackTypes.ModifyStoragePoolAnswer];
|
|
Assert.True((bool)ans.result, (string)ans.details); // always succeeds
|
|
|
|
// Clean up
|
|
var cmd2 = new
|
|
{
|
|
pool = pool,
|
|
localPath = folderName
|
|
};
|
|
JToken tok2 = JToken.FromObject(cmd);
|
|
|
|
// Act
|
|
dynamic jsonResult2 = controller.DeleteStoragePoolCommand(tok2);
|
|
|
|
// Assert
|
|
dynamic ans2 = jsonResult2[0][CloudStackTypes.Answer];
|
|
Assert.True((bool)ans2.result, (string)ans2.details); // always succeeds
|
|
}
|
|
|
|
[Fact(Skip="these are functional tests")]
|
|
public void CreateStoragePoolCommand()
|
|
{
|
|
var cmd = new { localPath = "NULL" };
|
|
JToken tok = JToken.FromObject(cmd);
|
|
HypervResourceController controller = new HypervResourceController();
|
|
|
|
// Act
|
|
dynamic jsonResult = controller.CreateStoragePoolCommand(tok);
|
|
|
|
// Assert
|
|
dynamic ans = jsonResult[0][CloudStackTypes.Answer];
|
|
Assert.True((bool)ans.result, (string)ans.details); // always succeeds
|
|
}
|
|
|
|
[Fact(Skip="these are functional tests")]
|
|
public void MaintainCommand()
|
|
{
|
|
// Omit HostEnvironment object, as this is a series of settings currently not used.
|
|
var cmd = new { };
|
|
JToken tok = JToken.FromObject(cmd);
|
|
HypervResourceController controller = new HypervResourceController();
|
|
|
|
// Act
|
|
dynamic jsonResult = controller.MaintainCommand(tok);
|
|
|
|
// Assert
|
|
dynamic ans = jsonResult[0][CloudStackTypes.MaintainAnswer];
|
|
Assert.True((bool)ans.result, (string)ans.details); // always succeeds
|
|
}
|
|
|
|
[Fact(Skip="these are functional tests")]
|
|
public void SetupCommand()
|
|
{
|
|
// Omit HostEnvironment object, as this is a series of settings currently not used.
|
|
var cmd = new { multipath = false, needSetup = true };
|
|
JToken tok = JToken.FromObject(cmd);
|
|
HypervResourceController controller = new HypervResourceController();
|
|
|
|
// Act
|
|
dynamic jsonResult = controller.SetupCommand(tok);
|
|
|
|
// Assert
|
|
dynamic ans = jsonResult[0][CloudStackTypes.SetupAnswer];
|
|
Assert.True((bool)ans.result, (string)ans.details); // always succeeds
|
|
}
|
|
|
|
[Fact(Skip="these are functional tests")]
|
|
public void TestPassingUserdataToVm()
|
|
{
|
|
// Sample data
|
|
String key = "cloudstack-vm-userdata";
|
|
String value = "username=root;password=1pass@word1";
|
|
|
|
// Find the VM
|
|
List<String> vmNames = wmiCallsV2.GetVmElementNames();
|
|
|
|
// Get associated WMI object
|
|
var vm = wmiCallsV2.GetComputerSystem(AgentSettings.Default.testKvpVmName);
|
|
|
|
// Get existing KVP
|
|
var vmSettings = wmiCallsV2.GetVmSettings(vm);
|
|
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.
|
|
string[] kvpProps = kvpInfo.HostExchangeItems;
|
|
|
|
// If the value already exists, delete it
|
|
foreach (var item in kvpProps)
|
|
{
|
|
String wmiObjectXml = item;
|
|
String existingKey;
|
|
String existingValue;
|
|
ParseKVP(wmiObjectXml, out existingKey, out existingValue);
|
|
|
|
if (existingKey == key)
|
|
{
|
|
wmiCallsV2.DeleteHostKvpItem(vm, existingKey);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Add new user data
|
|
wmiCallsV2.AddUserData(vm, value);
|
|
|
|
// 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;
|
|
|
|
// If the value already exists, delete it
|
|
bool userDataInPlace = false;
|
|
foreach (var item in kvpProps)
|
|
{
|
|
String wmiObjectXml = item;
|
|
String existingKey;
|
|
String existingValue;
|
|
ParseKVP(wmiObjectXml, out existingKey, out existingValue);
|
|
|
|
if (existingKey == key && existingValue == value)
|
|
{
|
|
// wmiCallsV2.DeleteHostKvpItem(vm, existingKey);
|
|
userDataInPlace = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Assert.True(userDataInPlace, "User data key / value did no save properly");
|
|
}
|
|
|
|
private static void ParseKVP(String wmiObjectXml, out String existingKey, out String existingValue)
|
|
{
|
|
// Reference: http://blogs.msdn.com/b/virtual_pc_guy/archive/2008/12/05/enumerating-parent-kvp-data.aspx
|
|
|
|
// Create XML parser
|
|
var xmlDoc = new XmlDocument();
|
|
|
|
// Load WMI object
|
|
xmlDoc.LoadXml(wmiObjectXml);
|
|
|
|
// Use xpath to get name and value
|
|
var namePropXpath = "/INSTANCE/PROPERTY[@NAME='Name']/VALUE";
|
|
var nameNode = xmlDoc.SelectSingleNode(namePropXpath);
|
|
existingKey = nameNode.InnerText;
|
|
var dataPropXpath = "/INSTANCE/PROPERTY[@NAME='Data']/VALUE";
|
|
var dataNode = xmlDoc.SelectSingleNode(dataPropXpath);
|
|
existingValue = dataNode.InnerText;
|
|
}
|
|
|
|
[Fact(Skip="these are functional tests")]
|
|
public void GetVmStatsCommandFail()
|
|
{
|
|
// Use WMI to find existing VMs
|
|
List<String> vmNames = new List<String>();
|
|
vmNames.Add("FakeVM");
|
|
|
|
var cmd = new
|
|
{
|
|
hostGuid = "FAKEguid",
|
|
hostName = AgentSettings.Default.host,
|
|
vmNames = vmNames
|
|
};
|
|
JToken tok = JToken.FromObject(cmd);
|
|
HypervResourceController controller = new HypervResourceController();
|
|
|
|
// Act
|
|
dynamic jsonResult = controller.GetVmStatsCommand(tok);
|
|
|
|
// Assert
|
|
dynamic ans = jsonResult[0][CloudStackTypes.GetVmStatsAnswer];
|
|
Assert.True((bool)ans.result, (string)ans.details); // always succeeds, fake VM means no answer for the named VM
|
|
}
|
|
|
|
[Fact(Skip="these are functional tests")]
|
|
public void GetVmStatsCommand()
|
|
{
|
|
// Use WMI to find existing VMs
|
|
List<String> vmNames = wmiCallsV2.GetVmElementNames();
|
|
|
|
var cmd = new
|
|
{
|
|
hostGuid = "FAKEguid",
|
|
hostName = AgentSettings.Default.host,
|
|
vmNames = vmNames
|
|
};
|
|
JToken tok = JToken.FromObject(cmd);
|
|
HypervResourceController controller = new HypervResourceController();
|
|
|
|
// Act
|
|
dynamic jsonResult = controller.GetVmStatsCommand(tok);
|
|
|
|
// Assert
|
|
dynamic ans = jsonResult[0][CloudStackTypes.GetVmStatsAnswer];
|
|
Assert.True((bool)ans.result, (string)ans.details);
|
|
}
|
|
|
|
[Fact(Skip="these are functional tests")]
|
|
public void GetStorageStatsCommand()
|
|
{
|
|
// TODO: Update sample data to unsure it is using correct info.
|
|
String sample = String.Format(
|
|
#region string_literal
|
|
"{{\"" +
|
|
"id\":{0}," +
|
|
"\"localPath\":{1}," +
|
|
"\"pooltype\":\"Filesystem\"," +
|
|
"\"contextMap\":{{}}," +
|
|
"\"wait\":0}}",
|
|
JsonConvert.SerializeObject(AgentSettings.Default.testLocalStoreUUID),
|
|
JsonConvert.SerializeObject(AgentSettings.Default.testLocalStorePath)
|
|
);
|
|
#endregion
|
|
var cmd = JsonConvert.DeserializeObject(sample);
|
|
JToken tok = JToken.FromObject(cmd);
|
|
HypervResourceController controller = new HypervResourceController();
|
|
|
|
// Act
|
|
dynamic jsonResult = controller.GetStorageStatsCommand(tok);
|
|
|
|
// Assert
|
|
dynamic ans = jsonResult[0][CloudStackTypes.GetStorageStatsAnswer];
|
|
Assert.True((bool)ans.result, (string)ans.details);
|
|
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.
|
|
[Fact(Skip="these are functional tests")]
|
|
public void GetHostStatsCommand()
|
|
{
|
|
// Arrange
|
|
long hostIdVal = 5;
|
|
HypervResourceController controller = new HypervResourceController();
|
|
string sample = string.Format(
|
|
#region string_literal
|
|
"{{" +
|
|
"\"hostGuid\":\"B4AE5970-FCBF-4780-9F8A-2D2E04FECC34-HypervResource\"," +
|
|
"\"hostName\":\"CC-SVR11\"," +
|
|
"\"hostId\":{0}," +
|
|
"\"contextMap\":{{}}," +
|
|
"\"wait\":0}}",
|
|
JsonConvert.SerializeObject(hostIdVal));
|
|
#endregion
|
|
var cmd = JsonConvert.DeserializeObject(sample);
|
|
JToken tok = JToken.FromObject(cmd);
|
|
|
|
// Act
|
|
dynamic jsonResult = controller.GetHostStatsCommand(tok);
|
|
|
|
// Assert
|
|
dynamic ans = jsonResult[0][CloudStackTypes.GetHostStatsAnswer];
|
|
Assert.True((bool)ans.result);
|
|
Assert.True(hostIdVal == (long)ans.hostStats.hostId);
|
|
Assert.True(0.0 < (double)ans.hostStats.totalMemoryKBs);
|
|
Assert.True(0.0 < (double)ans.hostStats.freeMemoryKBs);
|
|
Assert.True(0.0 <= (double)ans.hostStats.networkReadKBs);
|
|
Assert.True(0.0 <= (double)ans.hostStats.networkWriteKBs);
|
|
Assert.True(0.0 <= (double)ans.hostStats.cpuUtilization);
|
|
Assert.True(100.0 >= (double)ans.hostStats.cpuUtilization);
|
|
Assert.True("host".Equals((string)ans.hostStats.entityType));
|
|
Assert.True(String.IsNullOrEmpty((string)ans.details));
|
|
}
|
|
|
|
[Fact(Skip="these are functional tests")]
|
|
public void GetHostStatsCommandFail()
|
|
{
|
|
// Arrange
|
|
HypervResourceController controller = new HypervResourceController();
|
|
var cmd = new { GetHostStatsCommand = new { hostId = "badvalueType" } };
|
|
JToken tokFail = JToken.FromObject(cmd);
|
|
|
|
// Act
|
|
dynamic jsonResult = controller.GetHostStatsCommand(tokFail);
|
|
|
|
// Assert
|
|
dynamic ans = jsonResult[0][CloudStackTypes.GetHostStatsAnswer];
|
|
Assert.False((bool)ans.result);
|
|
Assert.Null((string)ans.hostStats);
|
|
Assert.NotNull(ans.details);
|
|
}
|
|
|
|
[Fact(Skip="these are functional tests")]
|
|
public void TestStartupCommand()
|
|
{
|
|
// Arrange
|
|
HypervResourceController controller = new HypervResourceController();
|
|
String sampleStartupRoutingCommand =
|
|
#region string_literal
|
|
"[{\"" + CloudStackTypes.StartupRoutingCommand + "\":{" +
|
|
"\"cpus\":0," +
|
|
"\"speed\":0," +
|
|
"\"memory\":0," +
|
|
"\"dom0MinMemory\":0," +
|
|
"\"poolSync\":false," +
|
|
"\"vms\":{}," +
|
|
"\"hypervisorType\":\"Hyperv\"," +
|
|
"\"hostDetails\":{" +
|
|
"\"com.cloud.network.Networks.RouterPrivateIpStrategy\":\"HostLocal\"" +
|
|
"}," +
|
|
"\"type\":\"Routing\"," +
|
|
"\"dataCenter\":\"1\"," +
|
|
"\"pod\":\"1\"," +
|
|
"\"cluster\":\"1\"," +
|
|
"\"guid\":\"16f85622-4508-415e-b13a-49a39bb14e4d\"," +
|
|
"\"name\":\"localhost\"," +
|
|
"\"version\":\"4.2.0\"," +
|
|
"\"privateIpAddress\":\"1\"," +
|
|
"\"storageIpAddress\":\"1\"," +
|
|
"\"contextMap\":{}," +
|
|
"\"wait\":0}}]";
|
|
#endregion
|
|
|
|
uint cores;
|
|
uint mhz;
|
|
wmiCallsV2.GetProcessorResources(out cores, out mhz);
|
|
ulong memory_mb;
|
|
ulong freememory;
|
|
wmiCallsV2.GetMemoryResources(out memory_mb, out freememory);
|
|
memory_mb *= 1024;
|
|
long capacityBytes;
|
|
long availableBytes;
|
|
HypervResourceController.GetCapacityForLocalPath(wmiCallsV2.GetDefaultVirtualDiskFolder(),
|
|
out capacityBytes, out availableBytes);
|
|
var DefaultVirtualDiskFolder = JsonConvert.SerializeObject(wmiCallsV2.GetDefaultVirtualDiskFolder());
|
|
string expected =
|
|
#region string_literal
|
|
"[{\"" + CloudStackTypes.StartupRoutingCommand + "\":{" +
|
|
"\"cpus\":" + cores + "," +
|
|
"\"speed\":" + mhz + "," +
|
|
"\"memory\":" + memory_mb + "," +
|
|
"\"dom0MinMemory\":" + (AgentSettings.Default.dom0MinMemory * 1024 * 1024) + "," +
|
|
"\"poolSync\":false," +
|
|
"\"vms\":{}," +
|
|
"\"hypervisorType\":\"Hyperv\"," +
|
|
"\"hostDetails\":{" +
|
|
"\"com.cloud.network.Networks.RouterPrivateIpStrategy\":\"HostLocal\"" +
|
|
"}," +
|
|
"\"type\":\"Routing\"," +
|
|
"\"dataCenter\":\"1\"," +
|
|
"\"pod\":\"1\"," +
|
|
"\"cluster\":\"1\"," +
|
|
"\"guid\":\"16f85622-4508-415e-b13a-49a39bb14e4d\"," +
|
|
"\"name\":\"localhost\"," +
|
|
"\"version\":\"4.2.0\"," +
|
|
"\"privateIpAddress\":\"" + AgentSettings.Default.private_ip_address + "\"," +
|
|
"\"storageIpAddress\":\"" + AgentSettings.Default.private_ip_address + "\"," +
|
|
"\"contextMap\":{}," +
|
|
"\"wait\":0," +
|
|
"\"privateNetmask\":\"" + AgentSettings.Default.private_ip_netmask + "\"," +
|
|
"\"privateMacAddress\":\"" + AgentSettings.Default.private_mac_address + "\"," +
|
|
"\"storageNetmask\":\"" + AgentSettings.Default.private_ip_netmask + "\"," +
|
|
"\"storageMacAddress\":\"" + AgentSettings.Default.private_mac_address + "\"," +
|
|
"\"gatewayIpAddress\":\"" + AgentSettings.Default.gateway_ip_address + "\"" +
|
|
",\"caps\":\"hvm\"" +
|
|
"}}," +
|
|
"{\"com.cloud.agent.api.StartupStorageCommand\":{" +
|
|
"\"poolInfo\":{" +
|
|
"\"uuid\":\"16f85622-4508-415e-b13a-49a39bb14e4d\"," +
|
|
"\"host\":\"" + AgentSettings.Default.private_ip_address + "\"," +
|
|
"\"localPath\":" + DefaultVirtualDiskFolder + "," +
|
|
"\"hostPath\":" + DefaultVirtualDiskFolder + "," +
|
|
"\"poolType\":\"Filesystem\"," +
|
|
"\"capacityBytes\":" + capacityBytes + "," +
|
|
"\"availableBytes\":" + availableBytes + "," +
|
|
"\"details\":null" +
|
|
"}," +
|
|
"\"guid\":\"16f85622-4508-415e-b13a-49a39bb14e4d\"," +
|
|
"\"dataCenter\":\"1\"," +
|
|
"\"resourceType\":\"STORAGE_POOL\"" +
|
|
"}}]";
|
|
#endregion
|
|
|
|
dynamic jsonArray = JsonConvert.DeserializeObject(sampleStartupRoutingCommand);
|
|
|
|
// Act
|
|
dynamic jsonResult = controller.StartupCommand(jsonArray);
|
|
|
|
// Assert
|
|
string actual = JsonConvert.SerializeObject(jsonResult);
|
|
Assert.Equal(expected, actual);
|
|
}
|
|
|
|
|
|
private static string TestStartCommand()
|
|
{
|
|
// Arrange
|
|
HypervResourceController rsrcServer = new HypervResourceController();
|
|
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);
|
|
string vmCmdName = jsonStartCmd.vm.name.Value;
|
|
var vm = wmiCallsV2.GetComputerSystem(vmCmdName);
|
|
var vmSettings = wmiCallsV2.GetVmSettings(vm);
|
|
var memSettings = wmiCallsV2.GetMemSettings(vmSettings);
|
|
var procSettings = wmiCallsV2.GetProcSettings(vmSettings);
|
|
dynamic jsonObj = JsonConvert.DeserializeObject(sample);
|
|
var vmInfo = jsonObj.vm;
|
|
string vmName = vmInfo.name;
|
|
var nicInfo = vmInfo.nics;
|
|
int vcpus = vmInfo.cpus;
|
|
int memSize = vmInfo.maxRam / 1048576;
|
|
Assert.True((long)memSettings.VirtualQuantity == memSize);
|
|
Assert.True((long)memSettings.Reservation == memSize);
|
|
Assert.True((long)memSettings.Limit == memSize);
|
|
Assert.True((int)procSettings.VirtualQuantity == vcpus);
|
|
Assert.True((int)procSettings.Reservation == vcpus);
|
|
Assert.True((int)procSettings.Limit == 100000);
|
|
|
|
// examine NIC for correctness
|
|
var nicSettingsViaVm = wmiCallsV2.GetEthernetPortSettings(vm);
|
|
Assert.True(nicSettingsViaVm.Length > 0, "Should be at least one ethernet port on VM");
|
|
string expectedMac = (string)jsonStartCmd.vm.nics[0].mac;
|
|
string strippedExpectedMac = expectedMac.Replace(":", string.Empty);
|
|
Assert.Equal(nicSettingsViaVm[0].Address.ToLower(), strippedExpectedMac.ToLower());
|
|
|
|
// Assert switchport has correct VLAN
|
|
var ethernetConnections = wmiCallsV2.GetEthernetConnections(vm);
|
|
var vlanSettings = wmiCallsV2.GetVlanSettings(ethernetConnections[0]);
|
|
string isolationUri = (string)jsonStartCmd.vm.nics[0].isolationUri;
|
|
string vlan = isolationUri.Replace("vlan://", string.Empty);
|
|
Assert.Equal(vlanSettings.AccessVlanId.ToString(), vlan);
|
|
|
|
return vmName;
|
|
}
|
|
|
|
private static void TestStopCommand(string vmName)
|
|
{
|
|
// Arrange
|
|
HypervResourceController rsrcServer = new HypervResourceController();
|
|
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);
|
|
var finalVm = wmiCallsV2.GetComputerSystem(vmName);
|
|
Assert.True(wmiCallsV2.GetComputerSystem(vmName) == null);
|
|
}
|
|
}
|
|
}
|