mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-10-26 08:42:29 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			1148 lines
		
	
	
		
			58 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			1148 lines
		
	
	
		
			58 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);
 | |
|         }
 | |
|     }
 | |
| }
 |