blob: d2e92bd5a2b6c1314316df683e3a937c295c3bdd [file] [log] [blame]
// 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.List;
import java.util.Map;
import java.util.Properties;
import javax.naming.ConfigurationException;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
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.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 {
protected Logger logger = LogManager.getLogger(getClass());
// 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());
logger.info("Cleaned up by delete file " + file.getPath());
}
s_testSampleVolumeTempURIJSON = createTestDiskImageFromExistingImage(testVolWorks, s_testLocalStorePath, s_testSampleVolumeTempUUID);
logger.info("Created " + s_testSampleVolumeTempURIJSON);
s_testSampleVolumeCorruptURIJSON = createTestDiskImageFromExistingImage(testVolWorks, s_testLocalStorePath, s_testSampleVolumeCorruptUUID);
logger.info("Created " + s_testSampleVolumeCorruptURIJSON);
createTestDiskImageFromExistingImage(testVolWorks, s_testLocalStorePath, s_testSampleTemplateUUID);
s_testSampleTemplateURLJSON = s_testSampleTemplateUUID;
logger.info("Created " + s_testSampleTemplateURLJSON + " in local storage.");
// Create secondary storage template:
createTestDiskImageFromExistingImage(testVolWorks, testSecondarStoreDir.getAbsolutePath(), "af39aa7f-2b12-37e1-86d3-e23f2f005101.vhdx");
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");
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
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);
logger.debug("Commands[] toJson is " + cmdsStr);
Command[] result = s_gson.fromJson(cmdsStr, Command[].class);
logger.debug("Commands[] fromJson is " + s_gson.toJson(result));
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);
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);
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
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
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";
}
logger.debug("TestInitialize returned " + result);
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()) {
logger.error(ans.getDetails());
} else {
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;
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);
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}";
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) {
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) {
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 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.");
}
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;
}
}