mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
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:
parent
c1cfaa2d1c
commit
b86d45b003
@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user