CLOUDSTACK-6054: Changes for making vmsync work for hyper-v. Made changes to PingCommand and

StartupCommand to return the state of all vms on the host.
This commit is contained in:
Anshul Gangwar 2014-02-10 09:41:41 -08:00 committed by Devdeep Singh
parent c1cfaa2d1c
commit b86d45b003
5 changed files with 131 additions and 23 deletions

View File

@ -918,5 +918,6 @@ namespace HypervResource
public const string DeleteCommand = "org.apache.cloudstack.storage.command.DeleteCommand";
public const string DettachAnswer = "org.apache.cloudstack.storage.command.DettachAnswer";
public const string DettachCommand = "org.apache.cloudstack.storage.command.DettachCommand";
public const string HostVmStateReportCommand = "org.apache.cloudstack.HostVmStateReportCommand";
}
}

View File

@ -2103,42 +2103,76 @@ namespace HypervResource
}
}
// POST api/HypervResource/GetVncPortCommand
// POST api/HypervResource/GetVncPortCommand
[HttpPost]
[ActionName(CloudStackTypes.GetVncPortCommand)]
public JContainer GetVncPortCommand([FromBody]dynamic cmd)
{
using (log4net.NDC.Push(Guid.NewGuid().ToString()))
{
logger.Info(CloudStackTypes.GetVncPortCommand + cmd.ToString());
string details = null;
bool result = false;
string address = null;
int port = -9;
try
{
string vmName = (string)cmd.name;
var sys = wmiCallsV2.GetComputerSystem(vmName);
address = "instanceId=" + sys.Name ;
result = true;
}
catch (Exception sysEx)
{
details = CloudStackTypes.GetVncPortAnswer + " failed due to " + sysEx.Message;
logger.Error(details, sysEx);
}
object ansContent = new
{
result = result,
details = details,
address = address,
port = port
};
return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.GetVncPortAnswer);
}
}
// POST api/HypervResource/HostVmStateReportCommand
[HttpPost]
[ActionName(CloudStackTypes.GetVncPortCommand)]
public JContainer GetVncPortCommand([FromBody]dynamic cmd)
[ActionName(CloudStackTypes.HostVmStateReportCommand)]
public JContainer HostVmStateReportCommand([FromBody]dynamic cmd)
{
using (log4net.NDC.Push(Guid.NewGuid().ToString()))
{
logger.Info(CloudStackTypes.GetVncPortCommand + cmd.ToString());
logger.Info(CloudStackTypes.HostVmStateReportCommand + cmd.ToString());
string details = null;
bool result = false;
string address = null;
int port = -9;
Dictionary<string, string>[] hostVmStateReport = null;
try
{
string vmName = (string)cmd.name;
var sys = wmiCallsV2.GetComputerSystem(vmName);
address = "instanceId=" + sys.Name ;
result = true;
var vmCollection = wmiCallsV2.GetComputerSystemCollection();
hostVmStateReport = new Dictionary<string, string>[vmCollection.Count];
int i = 0;
foreach (ComputerSystem vm in vmCollection)
{
var dict = new Dictionary<string, string>();
dict.Add(vm.ElementName, EnabledState.ToCloudStackPowerState(vm.EnabledState));
hostVmStateReport[i++] = dict;
}
}
catch (Exception sysEx)
{
details = CloudStackTypes.GetVncPortAnswer + " failed due to " + sysEx.Message;
details = CloudStackTypes.HostVmStateReportCommand + " failed due to " + sysEx.Message;
logger.Error(details, sysEx);
}
object ansContent = new
{
result = result,
details = details,
address = address,
port = port
};
return ReturnCloudStackTypedJArray(ansContent, CloudStackTypes.GetVncPortAnswer);
return JArray.FromObject(hostVmStateReport);
}
}

View File

@ -42,6 +42,7 @@ namespace HypervResource
void MigrateVm(string vmName, string destination);
void DetachDisk(string displayName, string diskFileName);
ComputerSystem GetComputerSystem(string displayName);
ComputerSystem.ComputerSystemCollection GetComputerSystemCollection();
string GetDefaultDataRoot();
string GetDefaultVirtualDiskFolder();
ResourceAllocationSettingData GetDvdDriveSettings(VirtualSystemSettingData vmSettings);

View File

@ -1874,6 +1874,12 @@ namespace HypervResource
return null;
}
public ComputerSystem.ComputerSystemCollection GetComputerSystemCollection()
{
var wmiQuery = String.Format("Caption=\"Virtual Machine\"");
return ComputerSystem.GetInstances(wmiQuery);
}
public Dictionary<String, VmState> GetVmSync(String privateIpAddress)
{
List<String> vms = GetVmElementNames();
@ -2474,5 +2480,24 @@ namespace HypervResource
}
return result;
}
public static string ToCloudStackPowerState(UInt16 value)
{
string result = "Unknown";
switch (value)
{
case Enabled: result = "PowerOn"; break;
case Disabled: result = "PowerOff"; break;
case Paused: result = "PowerUnknown"; break;
case Suspended: result = "PowerUnknown"; break;
case Starting: result = "PowerOn"; break;
case Snapshotting: result = "PowerUnknown"; break; // NOT used
case Saving: result = "PowerOn"; break;
case Stopping: result = "PowerOff"; break;
case Pausing: result = "PowerUnknown"; break;
case Resuming: result = "PowerOn"; break;
}
return result;
}
}
}

View File

@ -62,6 +62,7 @@ import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.CheckRouterAnswer;
@ -139,6 +140,7 @@ import com.cloud.utils.StringUtils;
import com.cloud.utils.net.NetUtils;
import com.cloud.utils.ssh.SshHelper;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.PowerState;
import com.cloud.vm.VirtualMachineName;
@ -148,6 +150,7 @@ import com.cloud.vm.VirtualMachineName;
@Local(value = ServerResource.class)
public class HypervDirectConnectResource extends ServerResourceBase implements ServerResource {
public static final int DEFAULT_AGENT_PORT = 8250;
public static final String HOST_VM_STATE_REPORT_COMMAND = "org.apache.cloudstack.HostVmStateReportCommand";
private static final Logger s_logger = Logger.getLogger(HypervDirectConnectResource.class.getName());
private static final Gson s_gson = GsonHelper.getGson();
@ -209,6 +212,7 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
defaultStartRoutCmd.setPrivateIpAddress(_agentIp);
defaultStartRoutCmd.setStorageIpAddress(_agentIp);
defaultStartRoutCmd.setPool(_clusterGuid);
defaultStartRoutCmd.setHostVmStateReport(getHostVmStateReport());
s_logger.debug("Generated StartupRoutingCommand for _agentIp \"" + _agentIp + "\"");
@ -300,8 +304,7 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
@Override
public final PingCommand getCurrentStatus(final long id) {
// TODO, need to report VM states on host
PingCommand pingCmd = new PingRoutingCommand(getType(), id, null, null);
PingCommand pingCmd = new PingRoutingCommand(getType(), id, null, getHostVmStateReport());
if (s_logger.isDebugEnabled()) {
s_logger.debug("Ping host " + _name + " (IP " + _agentIp + ")");
@ -316,6 +319,50 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
return pingCmd;
}
public final ArrayList<Map<String, String>> requestHostVmStateReport() {
URI agentUri = null;
try {
agentUri = new URI("https", null, _agentIp, _port, "/api/HypervResource/" + HOST_VM_STATE_REPORT_COMMAND, null, null);
} catch (URISyntaxException e) {
String errMsg = "Could not generate URI for Hyper-V agent";
s_logger.error(errMsg, e);
return null;
}
String incomingCmd = postHttpRequest("{}", agentUri);
if (incomingCmd == null) {
return null;
}
ArrayList<Map<String, String>> result = null;
try {
result = s_gson.fromJson(incomingCmd, new TypeToken<ArrayList<HashMap<String, String>>>() {
}.getType());
} catch (Exception ex) {
String errMsg = "Failed to deserialize Command[] " + incomingCmd;
s_logger.error(errMsg, ex);
}
s_logger.debug("HostVmStateReportCommand received response "
+ s_gson.toJson(result));
if (!result.isEmpty()) {
return result;
}
return null;
}
protected HashMap<String, HostVmStateReportEntry> getHostVmStateReport() {
final HashMap<String, HostVmStateReportEntry> vmStates = new HashMap<String, HostVmStateReportEntry>();
ArrayList<Map<String, String>> vmList = requestHostVmStateReport();
if (vmList == null || vmList.isEmpty()) {
return null;
}
for (Map<String, String> vmMap : vmList) {
String name = (String)vmMap.keySet().toArray()[0];
vmStates.put(name, new HostVmStateReportEntry(PowerState.valueOf(vmMap.get(name)), _guid, null));
}
return vmStates;
}
// TODO: Is it valid to return NULL, or should we throw on error?
// Returns StartupCommand with fields revised with values known only to the
// host