// 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. package com.cloud.hypervisor.hyperv.test; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.URL; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import javax.naming.ConfigurationException; import org.apache.log4j.Logger; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import com.google.common.io.Files; import com.google.gson.Gson; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.CreateStoragePoolCommand; import com.cloud.agent.api.DeleteStoragePoolCommand; import com.cloud.agent.api.GetHostStatsAnswer; import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.GetStorageStatsAnswer; import com.cloud.agent.api.GetStorageStatsCommand; import com.cloud.agent.api.GetVmStatsAnswer; import com.cloud.agent.api.GetVmStatsCommand; import com.cloud.agent.api.HostVmStateReportEntry; import com.cloud.agent.api.ModifyStoragePoolCommand; import com.cloud.agent.api.StartAnswer; import com.cloud.agent.api.StartCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupRoutingCommand; import com.cloud.agent.api.StartupStorageCommand; import com.cloud.agent.api.StopAnswer; import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.storage.CreateAnswer; import com.cloud.agent.api.storage.CreateCommand; import com.cloud.agent.api.storage.DestroyCommand; import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; import com.cloud.hypervisor.Hypervisor; import com.cloud.hypervisor.hyperv.resource.HypervDirectConnectResource; import com.cloud.network.Networks.RouterPrivateIpStrategy; import com.cloud.serializer.GsonHelper; import com.cloud.storage.Storage; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.utils.PropertiesUtil; import com.cloud.utils.exception.CloudRuntimeException; /** * Functional test suit for Hyper-V plugin. * * mvn clean build -DskipTests=false **/ public class HypervDirectConnectResourceTest { private static final Logger s_logger = Logger.getLogger(HypervDirectConnectResourceTest.class.getName()); // TODO: make this a config parameter private static final String sampleLegitDiskImageURL = "http://s3-eu-west-1.amazonaws.com/cshv3eu/SmallDisk.vhdx"; private static final Gson s_gson = GsonHelper.getGson(); private static final HypervDirectConnectResource s_hypervresource = new HypervDirectConnectResource(); private static String s_testLocalStoreUUID = "5fe2bad3-d785-394e-9949-89786b8a63d2"; private static String s_testLocalStorePath = "." + File.separator + "var" + File.separator + "test" + File.separator + "storagepool"; private static String s_testSecondaryStoreLocalPath = "." + File.separator + "var" + File.separator + "test" + File.separator + "secondary"; // TODO: differentiate between NFS and HTTP template URLs. private static String s_testSampleTemplateUUID = "TestCopiedLocalTemplate.vhdx"; private static String s_testSampleTemplateURL = s_testSampleTemplateUUID; // test volumes are both a minimal size vhdx. Changing the extension to .vhd // makes on corrupt. private static String s_testSampleVolumeWorkingUUID = "TestVolumeLegit.vhdx"; private static String s_testSampleVolumeWorkingUUIDNoExt = "TestVolumeLegit"; private static String s_testSampleVolumeCorruptUUID = "TestVolumeCorrupt.vhd"; private static String s_testSampleVolumeTempUUID = "TestVolumeTemp.vhdx"; private static String s_testSampleVolumeWorkingURIJSON; private static String s_testSampleVolumeCorruptURIJSON; private static String s_testSampleVolumeTempURIJSON; private static String s_testSampleTemplateURLJSON; private static String s_testLocalStorePathJSON; private static String s_agentExecutable; private static Process s_agentProc; private static String s_testPrimaryDataStoreHost; public HypervDirectConnectResourceTest() { } /** * Prep test environment. **/ @Before public final void setUp() throws ConfigurationException { // Obtain script locations from agent.properties final Map<String, Object> params = PropertiesUtil.toMap(loadProperties()); // Used to create existing StoragePool in preparation for the // ModifyStoragePool params.put("local.storage.uuid", s_testLocalStoreUUID); // Make sure secondary store is available. File testSecondarStoreDir = new File(s_testSecondaryStoreLocalPath); if (!testSecondarStoreDir.exists()) { testSecondarStoreDir.mkdirs(); } Assert.assertTrue("Need to be able to create the folder " + s_testSecondaryStoreLocalPath, testSecondarStoreDir.exists()); try { params.put("local.secondary.storage.path", testSecondarStoreDir.getCanonicalPath()); } catch (IOException e1) { // TODO Auto-generated catch block Assert.fail("No canonical path for " + testSecondarStoreDir.getAbsolutePath()); } // Clean up old test files in local storage folder: File testPoolDir = new File(s_testLocalStorePath); if (!testPoolDir.exists()) { testPoolDir.mkdirs(); } Assert.assertTrue("To simulate local file system Storage Pool, " + " you need folder at " + testPoolDir.getPath(), testPoolDir.exists() && testPoolDir.isDirectory()); try { s_testLocalStorePath = testPoolDir.getCanonicalPath(); } catch (IOException e) { Assert.fail("No canonical path for " + testPoolDir.getAbsolutePath()); } params.put("local.storage.path", s_testLocalStorePath); File testVolWorks = new File(s_testLocalStorePath + File.separator + s_testSampleVolumeWorkingUUID); if (!testVolWorks.exists()) { ReadableByteChannel rbc; try { URL sampleLegitDiskImageURL = new URL("http://s3-eu-west-1.amazonaws.com/cshv3eu/SmallDisk.vhdx"); rbc = Channels.newChannel(sampleLegitDiskImageURL.openStream()); FileOutputStream fos = new FileOutputStream(testVolWorks); fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } Assert.assertTrue("Need to put a sample working virtual disk at " + testVolWorks.getPath(), testVolWorks.exists()); try { s_testSampleVolumeWorkingURIJSON = s_gson.toJson(testVolWorks.getCanonicalPath()); } catch (IOException e) { Assert.fail("No canonical path for " + testPoolDir.getAbsolutePath()); } FilenameFilter vhdsFilt = new FilenameFilter() { @Override public boolean accept(final File directory, final String fileName) { return fileName.endsWith(".vhdx") || fileName.endsWith(".vhd"); } }; for (File file : testPoolDir.listFiles(vhdsFilt)) { if (file.getName().equals(testVolWorks.getName())) { continue; } Assert.assertTrue("Should have deleted file " + file.getPath(), file.delete()); s_logger.info("Cleaned up by delete file " + file.getPath()); } s_testSampleVolumeTempURIJSON = createTestDiskImageFromExistingImage(testVolWorks, s_testLocalStorePath, s_testSampleVolumeTempUUID); s_logger.info("Created " + s_testSampleVolumeTempURIJSON); s_testSampleVolumeCorruptURIJSON = createTestDiskImageFromExistingImage(testVolWorks, s_testLocalStorePath, s_testSampleVolumeCorruptUUID); s_logger.info("Created " + s_testSampleVolumeCorruptURIJSON); createTestDiskImageFromExistingImage(testVolWorks, s_testLocalStorePath, s_testSampleTemplateUUID); s_testSampleTemplateURLJSON = s_testSampleTemplateUUID; s_logger.info("Created " + s_testSampleTemplateURLJSON + " in local storage."); // Create secondary storage template: createTestDiskImageFromExistingImage(testVolWorks, testSecondarStoreDir.getAbsolutePath(), "af39aa7f-2b12-37e1-86d3-e23f2f005101.vhdx"); s_logger.info("Created " + "af39aa7f-2b12-37e1-86d3-e23f2f005101.vhdx" + " in secondary (NFS) storage."); s_testLocalStorePathJSON = s_gson.toJson(s_testLocalStorePath); String agentIp = (String)params.get("ipaddress"); s_logger.info("Test using agent IP address " + agentIp); params.put("agentIp", agentIp); setTestJsonResult(params); s_hypervresource.configure("hypervresource", params); // Verify sample template is in place storage pool s_logger.info("setUp complete, sample StoragePool at " + s_testLocalStorePathJSON + " sample template at " + s_testSampleTemplateURLJSON); s_agentExecutable = (String)params.get("agent.executable"); s_testPrimaryDataStoreHost = (String)params.get("ipaddress"); agentCreation(); } private String createTestDiskImageFromExistingImage(final File srcFile, final String dstPath, final String dstFileName) { String newFileURIJSON = null; File testVolTemp = new File(dstPath + File.separator + dstFileName); try { Files.copy(srcFile, testVolTemp); } catch (IOException e) { ; // NOP } Assert.assertTrue("Should be a temporary file created from the valid volume) at " + testVolTemp.getPath(), testVolTemp.exists()); try { newFileURIJSON = s_gson.toJson(testVolTemp.getCanonicalPath()); } catch (IOException e) { Assert.fail("No file at " + testVolTemp.getAbsolutePath()); } return newFileURIJSON; } @Test public final void testGetVmStatsCommand() { // Sample GetVmStatsCommand List<String> vmNames = new ArrayList<String>(); vmNames.add("i-2-11-VM"); GetVmStatsCommand cmd = new GetVmStatsCommand(vmNames, "1", "localhost"); s_hypervresource.executeRequest(cmd); GetVmStatsAnswer ans = (GetVmStatsAnswer)s_hypervresource.executeRequest(cmd); Assert.assertTrue(ans.getDetails(), ans.getResult()); } public final void testStartupCommand() { StartupRoutingCommand defaultStartRoutCmd = new StartupRoutingCommand(0, 0, 0, 0, null, Hypervisor.HypervisorType.Hyperv, RouterPrivateIpStrategy.HostLocal); // Identity within the data centre is decided by CloudStack kernel, // and passed via ServerResource.configure() defaultStartRoutCmd.setDataCenter("1"); defaultStartRoutCmd.setPod("1"); defaultStartRoutCmd.setCluster("1"); defaultStartRoutCmd.setGuid("1"); defaultStartRoutCmd.setName("1"); defaultStartRoutCmd.setPrivateIpAddress("1"); defaultStartRoutCmd.setStorageIpAddress("1"); defaultStartRoutCmd.setCpus(12); // TODO: does version need to be hard coded. defaultStartRoutCmd.setVersion("4.2.0"); StartupCommand scmd = defaultStartRoutCmd; Command[] cmds = {scmd}; String cmdsStr = s_gson.toJson(cmds); s_logger.debug("Commands[] toJson is " + cmdsStr); Command[] result = s_gson.fromJson(cmdsStr, Command[].class); s_logger.debug("Commands[] fromJson is " + s_gson.toJson(result)); s_logger.debug("Commands[] first element has type" + result[0].toString()); } // @Test public final void testJson() { StartupStorageCommand sscmd = null; com.cloud.agent.api.StoragePoolInfo pi = new com.cloud.agent.api.StoragePoolInfo("test123", "192.168.0.1", "c:\\", "c:\\", StoragePoolType.Filesystem, 100L, 50L); sscmd = new StartupStorageCommand(); sscmd.setPoolInfo(pi); sscmd.setGuid(pi.getUuid()); sscmd.setDataCenter("foo"); sscmd.setResourceType(Storage.StorageResourceType.STORAGE_POOL); s_logger.debug("StartupStorageCommand fromJson is " + s_gson.toJson(sscmd)); } @Test public final void testBadGetVmStatsCommand() { // Sample GetVmStatsCommand List<String> vmNames = new ArrayList<String>(); vmNames.add("FakeVM"); GetVmStatsCommand vmStatsCmd = new GetVmStatsCommand(vmNames, "1", "localhost"); GetVmStatsAnswer ans = (GetVmStatsAnswer)s_hypervresource.executeRequest(vmStatsCmd); Assert.assertTrue(ans.getDetails(), ans.getResult()); } @Test public final void testCreateStoragePoolCommand() { String folderName = "." + File.separator + "Dummy"; StoragePoolVO pool = createTestStoragePoolVO(folderName); CreateStoragePoolCommand cmd = new CreateStoragePoolCommand(true, pool); s_logger.debug("TestCreateStoragePoolCommand sending " + s_gson.toJson(cmd)); Answer ans = s_hypervresource.executeRequest(cmd); Assert.assertTrue(ans.getResult()); } @Test public final void testModifyStoragePoolCommand() { // Create dummy folder String folderName = "." + File.separator + "Dummy"; StoragePoolVO pool = createTestStoragePoolVO(folderName); ModifyStoragePoolCommand cmd = new ModifyStoragePoolCommand(true, pool, folderName); Answer ans = s_hypervresource.executeRequest(cmd); Assert.assertTrue(ans.getResult()); DeleteStoragePoolCommand delCmd = new DeleteStoragePoolCommand(pool, folderName); Answer ans2 = s_hypervresource.executeRequest(delCmd); Assert.assertTrue(ans2.getResult()); } // Check @Test public final void testModifyStoragePoolCommand2() { // Should return existing pool // Create dummy folder String folderName = "." + File.separator + "Dummy"; File folder = new File(folderName); if (!folder.exists()) { if (!folder.mkdir()) { Assert.assertTrue(false); } } // Use same spec for pool s_logger.info("Createing pool at : " + folderName); StoragePoolVO pool = new StoragePoolVO(StoragePoolType.Filesystem, "127.0.0.1", -1, folderName); pool.setUuid(s_testLocalStoreUUID); ModifyStoragePoolCommand cmd = new ModifyStoragePoolCommand(true, pool, folderName); Answer ans = s_hypervresource.executeRequest(cmd); Assert.assertTrue(ans.getResult()); DeleteStoragePoolCommand delCmd = new DeleteStoragePoolCommand(pool, folderName); Answer ans2 = s_hypervresource.executeRequest(delCmd); Assert.assertTrue(ans2.getResult()); } public final StoragePoolVO createTestStoragePoolVO(final String folderName) { File folder = new File(folderName); if (!folder.exists()) { if (!folder.mkdir()) { Assert.assertTrue(false); } } // Use same spec for pool s_logger.info("Createing pool at : " + folderName); StoragePoolVO pool = new StoragePoolVO(StoragePoolType.Filesystem, "127.0.0.1", -1, folderName); return pool; } @Test public final void testInitialize() { StartupCommand[] startCmds = s_hypervresource.initialize(); Command[] cmds = new Command[] {startCmds[0], startCmds[1]}; String result = s_gson.toJson(cmds); if (result == null) { result = "NULL"; } s_logger.debug("TestInitialize returned " + result); s_logger.debug("TestInitialize expected " + _setTestJsonResultStr); Assert.assertTrue("StartupCommand[] not what we expected", _setTestJsonResultStr.equals(result)); return; } @Test public final void testPrimaryStorageDownloadCommandHTTP() { PrimaryStorageDownloadCommand cmd = samplePrimaryDownloadCommand(); cmd.setUrl("http://s3-eu-west-1.amazonaws.com/cshv3eu/SmallDisk.vhdx"); corePrimaryStorageDownloadCommandTestCycle(cmd); } private void corePrimaryStorageDownloadCommandTestCycle(final PrimaryStorageDownloadCommand cmd) { PrimaryStorageDownloadAnswer ans = (PrimaryStorageDownloadAnswer)s_hypervresource.executeRequest(cmd); if (!ans.getResult()) { s_logger.error(ans.getDetails()); } else { s_logger.debug(ans.getDetails()); } Assert.assertTrue(ans.getDetails(), ans.getResult()); // Test that returned URL works. // CreateCommand createCmd = CreateCommandSample(); // CreateCommand testCreateCmd = new // CreateCommand(createCmd.getDiskCharacteristics(), // ans.getInstallPath(), createCmd.getPool()); // CreateAnswer ans2 = // (CreateAnswer)s_hypervresource.executeRequest(testCreateCmd); // Assert.assertTrue(ans2.getDetails(), ans2.getResult()); } private PrimaryStorageDownloadCommand samplePrimaryDownloadCommand() { String cmdJson = "{\"localPath\":" + s_testLocalStorePathJSON + ",\"poolUuid\":\"" + s_testLocalStoreUUID + "\",\"poolId\":201," + "\"secondaryStorageUrl\":" + "\"nfs://10.70.176.36/mnt/cshv3/secondarystorage\"," + "\"primaryStorageUrl\":" + "\"nfs://10.70.176.29E:\\\\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}"; PrimaryStorageDownloadCommand cmd = s_gson.fromJson(cmdJson, PrimaryStorageDownloadCommand.class); return cmd; } public final CreateCommand createCommandSample() { String sample = "{\"volId\":17,\"pool\":{\"id\":201,\"uuid\":\"" + s_testLocalStoreUUID + "\",\"host\":\"10.70.176.29\"" + ",\"path\":" + s_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\":" + s_testSampleTemplateURLJSON + ",\"wait\":0}"; CreateCommand cmd = s_gson.fromJson(sample, CreateCommand.class); return cmd; } @Test public final void testCreateCommand() { String sample = "{\"volId\":10,\"pool\":{\"id\":201,\"uuid\":\"" + s_testLocalStoreUUID + "\",\"host\":\"10.70.176.29\"" + ",\"path\":" + s_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\":" + s_testSampleTemplateURLJSON + ",\"contextMap\":{},\"wait\":0}"; File destDir = new File(s_testLocalStorePath); Assert.assertTrue(destDir.isDirectory()); File testSampleTemplateURLFile = new File(s_testLocalStorePath + File.separator + s_gson.fromJson(s_testSampleTemplateURLJSON, String.class)); Assert.assertTrue("The template that create should make" + " volumes from is missing from path " + testSampleTemplateURLFile.getPath(), testSampleTemplateURLFile.exists()); int fileCount = destDir.listFiles().length; s_logger.debug(" test local store has " + fileCount + "files"); // Test requires there to be a template at the tempalteUrl, which is its // location in the local file system. CreateCommand cmd = s_gson.fromJson(sample, CreateCommand.class); CreateAnswer ans = (CreateAnswer)s_hypervresource.executeRequest(cmd); Assert.assertTrue(ans.getDetails(), ans.getResult()); Assert.assertTrue("CreateCommand should add a file to the folder", fileCount + 1 == destDir.listFiles().length); File newFile = new File(ans.getVolume().getPath()); Assert.assertTrue("The new file should have a size greater than zero", newFile.length() > 0); newFile.delete(); } @Test public final void testStartCommandCorruptDiskImage() { String sampleStart = "{\"vm\":{\"id\":16,\"name\":\"i-3-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\":[" + "{\"id\":18,\"name\":\"" + s_testSampleVolumeCorruptUUID + "\"," + "\"mountPoint\":" + s_testSampleVolumeCorruptURIJSON + "," + "\"path\":" + s_testSampleVolumeCorruptURIJSON + ",\"size\":0," + "\"type\":\"ROOT\"," + "\"storagePoolType\":\"Filesystem\"," + "\"storagePoolUuid\":\"" + s_testLocalStoreUUID + "\"" + ",\"deviceId\":0}," + "{\"id\":16,\"name\":\"Hyper-V Sample2\",\"size\":0," + "\"type\":\"ISO\",\"storagePoolType\":\"ISO\"," + "\"deviceId\":3}]," + "\"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}"; StartCommand cmd = s_gson.fromJson(sampleStart, StartCommand.class); StartAnswer ans = (StartAnswer)s_hypervresource.executeRequest(cmd); Assert.assertFalse(ans.getDetails(), ans.getResult()); } @Test public final void testStartStopCommand() { String sample = getSampleStartCommand(); StartAnswer sans = simpleVmStart(sample); Assert.assertTrue(sans.getDetails(), sans.getResult()); StopAnswer stopAns = simpleVmStop(); Assert.assertTrue(stopAns.getDetails(), stopAns.getResult()); } @Test public final void testStartStartCommand() { String sample = getSampleStartCommand(); StartAnswer sans = simpleVmStart(sample); Assert.assertTrue(sans.getDetails(), sans.getResult()); simpleVmStart(sample); StopAnswer ans = simpleVmStop(); Assert.assertTrue(ans.getDetails(), ans.getResult()); } private StopAnswer simpleVmStop() { String sampleStop = "{\"isProxy\":false,\"vmName\":\"i-2-17-VM\"," + "\"contextMap\":{},\"wait\":0}"; StopCommand cmd = s_gson.fromJson(sampleStop, StopCommand.class); StopAnswer ans = (StopAnswer)s_hypervresource.executeRequest(cmd); return ans; } private StartAnswer simpleVmStart(final String sample) { StartCommand cmd = s_gson.fromJson(sample, StartCommand.class); s_logger.info("StartCommand sample " + s_gson.toJson(cmd)); StartAnswer ans = (StartAnswer)s_hypervresource.executeRequest(cmd); return ans; } @Test public final void testDestroyCommand() { // TODO: how does the command vary when we are only deleting a vm versus // deleting a volume? // String sample2 = "{\"volume\":" + getSampleVolumeObjectTO() + "}"; String sample2 = "{\"volume\":{\"name\":\"" + s_testSampleVolumeWorkingUUIDNoExt + "\",\"storagePoolType\":\"Filesystem\"," + "\"mountPoint\":" + s_testLocalStorePathJSON + ",\"path\":" + s_testSampleVolumeTempURIJSON + ",\"storagePoolUuid\":\"" + s_testLocalStoreUUID + "\"," + "\"type\":\"ROOT\",\"id\":9,\"size\":0}}"; DestroyCommand cmd = s_gson.fromJson(sample2, DestroyCommand.class); Answer ans = s_hypervresource.executeRequest(cmd); Assert.assertTrue(ans.getDetails(), ans.getResult()); } @Test public final void testGetStorageStatsCommand() { // TODO: Update sample data to unsure it is using correct info. String sample = "{\"id\":\"" + s_testLocalStoreUUID + "\",\"localPath\":" + s_testLocalStorePathJSON + "," + "\"pooltype\":\"Filesystem\"," + "\"contextMap\":{},\"wait\":0}"; s_logger.info("Sample JSON: " + sample); GetStorageStatsCommand cmd = s_gson.fromJson(sample, GetStorageStatsCommand.class); s_hypervresource.executeRequest(cmd); GetStorageStatsAnswer ans = (GetStorageStatsAnswer)s_hypervresource.executeRequest(cmd); Assert.assertTrue(ans.getDetails(), ans.getResult()); Assert.assertTrue(ans.getByteUsed() != ans.getCapacityBytes()); } @After public final void agentTerminate() { // Write carriage return line feed to script's stdin OutputStream scriptInput = s_agentProc.getOutputStream(); OutputStreamWriter siw = new OutputStreamWriter(scriptInput); try { BufferedWriter writer = new BufferedWriter(siw); writer.write("\r\n"); writer.flush(); writer.close(); } catch (IOException ex) { s_logger.debug("Error closing agent at " + s_agentExecutable + " message " + ex.getMessage()); } } private void agentCreation() { // Launch script try { List<String> exeArgs = new ArrayList<String>(); exeArgs.add(s_agentExecutable); exeArgs.add("--console"); // when we launch from the shell, we need to use Cygwin's path to // the exe ProcessBuilder builder = new ProcessBuilder(exeArgs); builder.redirectErrorStream(true); s_agentProc = builder.start(); Thread.sleep(4000); } catch (Exception ex) { s_logger.debug("Error calling starting aget at " + s_agentExecutable + " message " + ex.getMessage()); } } @Test public final void testGetHostStatsCommand() { // Arrange long hostIdVal = 123; GetHostStatsCommand cmd = new GetHostStatsCommand("1", "testHost", hostIdVal); // Act GetHostStatsAnswer ans = (GetHostStatsAnswer)s_hypervresource.executeRequest(cmd); // Assert Assert.assertTrue(ans.getResult()); Assert.assertTrue(0.0 < ans.getTotalMemoryKBs()); Assert.assertTrue(0.0 < ans.getFreeMemoryKBs()); Assert.assertTrue(0.0 <= ans.getNetworkReadKBs()); Assert.assertTrue(0.0 <= ans.getNetworkWriteKBs()); Assert.assertTrue(0.0 <= ans.getCpuUtilization()); Assert.assertTrue(100 >= ans.getCpuUtilization()); Assert.assertTrue(ans.getEntityType().equals("host")); Assert.assertTrue(ans.getDetails() == null); } public static Properties loadProperties() throws ConfigurationException { Properties properties = new Properties(); final File file = PropertiesUtil.findConfigFile("agent.properties"); if (file == null) { throw new ConfigurationException("Unable to find agent.properties."); } s_logger.info("agent.properties found at " + file.getAbsolutePath()); try { properties.load(new FileInputStream(file)); } catch (final FileNotFoundException ex) { throw new CloudRuntimeException("Cannot find the file: " + file.getAbsolutePath(), ex); } catch (final IOException ex) { throw new CloudRuntimeException("IOException in reading " + file.getAbsolutePath(), ex); } return properties; } private String _setTestJsonResultStr = null; public final void setTestJsonResult(final Map<String, Object> params) { File dir = new File((String)params.get("DefaultVirtualDiskFolder")); long usableCapacity = dir.getUsableSpace() - 4294967296L; long totalSpace = dir.getTotalSpace() - 4294967296L; // TODO: add test to verify capacity statistics change _setTestJsonResultStr = String.format("[{\"com.cloud.agent.api.StartupRoutingCommand\":{" + "\"cpus\":%s," + "\"speed\":%s," + "\"memory\":%s," + "\"dom0MinMemory\":%s," + "\"poolSync\":false," + "\"vms\":{}," + "\"caps\":\"hvm\"," + "\"hypervisorType\":\"Hyperv\"," + "\"hostDetails\":{" + "\"com.cloud.network.Networks.RouterPrivateIpStrategy\":" + "\"HostLocal\"" + "}," + "\"type\":\"Routing\"," + "\"dataCenter\":%s," + "\"pod\":%s," + "\"cluster\":%s," + "\"guid\":\"16f85622-4508-415e-b13a-49a39bb14e4d\"," + "\"name\":\"hypervresource\"," + "\"version\":\"4.2.0\"," + "\"privateIpAddress\":%s," + "\"privateMacAddress\":%s," + "\"privateNetmask\":%s," + "\"storageIpAddress\":%s," + "\"storageNetmask\":%s," + "\"storageMacAddress\":%s," + "\"gatewayIpAddress\":%s," + "\"contextMap\":{}," + "\"wait\":0" + "}}," + "{\"com.cloud.agent.api.StartupStorageCommand\":{" + "\"totalSize\":0," + "\"poolInfo\":{" + "\"uuid\":\"16f85622-4508-415e-b13a-49a39bb14e4d\"," + "\"host\":%s," + "\"localPath\":%s," + "\"hostPath\":%s," + "\"poolType\":\"Filesystem\"," + "\"capacityBytes\":%s," + "\"availableBytes\":%s" + "}," + "\"resourceType\":\"STORAGE_POOL\"," + "\"hostDetails\":{}," + "\"type\":\"Storage\"," + "\"dataCenter\":\"1\"," + "\"guid\":" + "\"16f85622-4508-415e-b13a-49a39bb14e4d\"," + "\"contextMap\":{}," + "\"wait\":0" + "}}]", params.get("TestCoreCount"), params.get("TestCoreMhz"), params.get("TestMemoryMb"), params.get("TestDom0MinMemoryMb"), s_gson.toJson(params.get("zone")), s_gson.toJson(params.get("pod")), s_gson.toJson(params.get("cluster")), s_gson.toJson(params.get("ipaddress")), s_gson.toJson(params.get("private.mac.address")), s_gson.toJson(params.get("private.ip.netmask")), s_gson.toJson(params.get("ipaddress")), s_gson.toJson(params.get("private.ip.netmask")), s_gson.toJson(params.get("private.mac.address")), s_gson.toJson(params.get("gateway.ip.address")), s_gson.toJson(params.get("ipaddress")), s_gson.toJson(params.get("DefaultVirtualDiskFolder")), s_gson.toJson(params.get("DefaultVirtualDiskFolder")), s_gson.toJson(totalSpace), s_gson.toJson(usableCapacity)); } public static String getSamplePrimaryDataStoreInfo() { String samplePrimaryDataStoreInfo = "{\"org.apache.cloudstack.storage.to.PrimaryDataStoreTO\":" + "{\"uuid\":\"" + s_testLocalStoreUUID + "\"," + "\"id\":201," + "\"host\":\"" + s_testPrimaryDataStoreHost + "\"," + "\"type\":\"Filesystem\"," // Not used in // PrimaryDataStoreTO + "\"poolType\":\"Filesystem\"," // Not used in // PrimaryDataStoreTO + "\"path\":" + s_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\":\"" + s_testSampleVolumeWorkingUUIDNoExt + "\"," + "\"size\":52428800," + "\"volumeId\":10," // "\"vmName\":\"i-3-5-VM\"," + // TODO: required? + "\"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; } }