package org.zstack.simulator.kvm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import org.zstack.core.thread.AsyncThread;
import org.zstack.header.exception.CloudRuntimeException;
import org.zstack.header.rest.RESTFacade;
import org.zstack.kvm.KVMAgentCommands;
import org.zstack.kvm.KVMAgentCommands.*;
import org.zstack.kvm.KVMConstant;
import org.zstack.kvm.KVMConstant.KvmVmState;
import org.zstack.kvm.KVMSecurityGroupBackend;
import org.zstack.network.securitygroup.SecurityGroupRuleTO;
import org.zstack.simulator.AsyncRESTReplyer;
import org.zstack.utils.Utils;
import org.zstack.utils.gson.JSONObjectUtil;
import org.zstack.utils.logging.CLogger;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
@Controller
public class KVMSimulatorController {
private static final CLogger logger = Utils.getLogger(KVMSimulatorController.class);
/*
* getBean() cannot return the same Controller as servlet use for unittest case,
* Controller should be a singleton, however, getBean() returns another copy of it
* as if it's prototype
* we have to use a config as Controller can inject the same instance that unittest
* gets
*/
@Autowired
private KVMSimulatorConfig config;
@Autowired
private RESTFacade restf;
@Autowired
private VolumeSnapshotKvmSimulator snapshotKvmSimulator;
private AsyncRESTReplyer replyer = new AsyncRESTReplyer();
@RequestMapping(value=KVMConstant.KVM_HARDEN_CONSOLE_PATH, method=RequestMethod.POST)
public @ResponseBody String hardenVmConsole(HttpServletRequest req) {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
HardenVmConsoleCmd cmd = JSONObjectUtil.toObject(entity.getBody(), HardenVmConsoleCmd.class);
config.hardenVmConsoleCmds.add(cmd);
replyer.reply(entity, new AgentResponse());
return null;
}
@RequestMapping(value=KVMConstant.KVM_DELETE_CONSOLE_FIREWALL_PATH, method=RequestMethod.POST)
public @ResponseBody String deleteVmConsole(HttpServletRequest req) {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
DeleteVmConsoleFirewallCmd cmd = JSONObjectUtil.toObject(entity.getBody(), DeleteVmConsoleFirewallCmd.class);
config.deleteVmConsoleFirewallCmds.add(cmd);
replyer.reply(entity, new AgentResponse());
return null;
}
@RequestMapping(value=KVMConstant.KVM_VM_CHECK_STATE, method=RequestMethod.POST)
public @ResponseBody String checkVmState(HttpServletRequest req) {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
CheckVmStateCmd cmd = JSONObjectUtil.toObject(entity.getBody(), CheckVmStateCmd.class);
CheckVmStateRsp rsp = new CheckVmStateRsp();
Map<String, String> m = new HashMap<String, String>();
for (String vmUuid : cmd.vmUuids) {
Map<String, String> h = config.checkVmStatesConfig.get(cmd.hostUuid);
if (h != null) {
m.put(vmUuid, h.get(vmUuid));
}
}
rsp.states = m;
config.checkVmStateCmds.add(cmd);
replyer.reply(entity, rsp);
return null;
}
@RequestMapping(value=KVMConstant.KVM_ATTACH_NIC_PATH, method=RequestMethod.POST)
public @ResponseBody String attachNic(HttpServletRequest req) {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
doAttachNic(entity);
return null;
}
@AsyncThread
private void doAttachNic(HttpEntity<String> entity) {
AttachNicCommand cmd = JSONObjectUtil.toObject(entity.getBody(), AttachNicCommand.class);
AttachNicResponse rsp = new AttachNicResponse();
if (!config.attachNicSuccess) {
rsp.setSuccess(false);
rsp.setError("fail on purpose");
} else {
config.attachNicCommands.add(cmd);
config.attachedNics.put(cmd.getNic().getNicInternalName(), cmd.getNic());
}
replyer.reply(entity, rsp);
}
@RequestMapping(value=KVMConstant.KVM_ATTACH_ISO_PATH, method=RequestMethod.POST)
public @ResponseBody String attachIso(HttpServletRequest req) {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
AttachIsoCmd cmd = JSONObjectUtil.toObject(entity.getBody(), AttachIsoCmd.class);
config.attachIsoCmds.add(cmd);
reply(entity, new AttachIsoRsp());
return null;
}
@RequestMapping(value=KVMConstant.KVM_DETACH_ISO_PATH, method=RequestMethod.POST)
public @ResponseBody String detachIso(HttpServletRequest req) {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
DetachIsoCmd cmd = JSONObjectUtil.toObject(entity.getBody(), DetachIsoCmd.class);
config.detachIsoCmds.add(cmd);
reply(entity, new DetachIsoRsp());
return null;
}
@RequestMapping(value=KVMConstant.KVM_DETACH_NIC_PATH, method=RequestMethod.POST)
public @ResponseBody String detachNic(HttpServletRequest req) {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
doDetachNic(entity);
return null;
}
private void doDetachNic(HttpEntity<String> entity) {
DetachNicCommand cmd = JSONObjectUtil.toObject(entity.getBody(), DetachNicCommand.class);
DetachNicRsp rsp = new DetachNicRsp();
if (!config.detachNicSuccess) {
rsp.setError("on purpose");
rsp.setSuccess(false);
} else {
config.detachNicCommands.add(cmd);
}
replyer.reply(entity, rsp);
}
@RequestMapping(value=KVMConstant.KVM_MERGE_SNAPSHOT_PATH, method=RequestMethod.POST)
public @ResponseBody String mergeSnapshot(HttpServletRequest req) {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
MergeSnapshotCmd cmd = JSONObjectUtil.toObject(entity.getBody(), MergeSnapshotCmd.class);
MergeSnapshotRsp rsp = new MergeSnapshotRsp();
if (!config.mergeSnapshotSuccess) {
rsp.setError("on purpose");
rsp.setSuccess(false);
} else {
snapshotKvmSimulator.merge(cmd.getSrcPath(), cmd.getDestPath(), cmd.isFullRebase());
config.mergeSnapshotCmds.add(cmd);
logger.debug(entity.getBody());
}
replyer.reply(entity, rsp);
return null;
}
@RequestMapping(value=KVMConstant.KVM_TAKE_VOLUME_SNAPSHOT_PATH, method=RequestMethod.POST)
public @ResponseBody String takeSnapshot(HttpServletRequest req) {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
TakeSnapshotCmd cmd = JSONObjectUtil.toObject(entity.getBody(), TakeSnapshotCmd.class);
TakeSnapshotResponse rsp = new TakeSnapshotResponse();
if (config.snapshotSuccess) {
config.snapshotCmds.add(cmd);
rsp = snapshotKvmSimulator.takeSnapshot(cmd);
Long size = config.takeSnapshotCmdSize.get(cmd.getVolumeUuid());
rsp.setSize(size == null ? 1 : size);
} else {
rsp.setError("on purpose");
rsp.setSuccess(false);
}
replyer.reply(entity, rsp);
return null;
}
@RequestMapping(value=KVMConstant.KVM_PING_PATH, method=RequestMethod.POST)
public @ResponseBody String ping(HttpServletRequest req) {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
ping(entity);
return null;
}
@AsyncThread
private void ping(HttpEntity<String> entity) {
PingCmd cmd = JSONObjectUtil.toObject(entity.getBody(), PingCmd.class);
PingResponse rsp = new PingResponse();
if (!config.pingSuccess) {
rsp.setSuccess(false);
rsp.setError("on purpose");
}
Boolean s = config.pingSuccessMap.get(cmd.hostUuid);
if (s != null && !s) {
rsp.setSuccess(false);
rsp.setError("on purpose");
}
rsp.setHostUuid(config.connectHostUuids.get(cmd.hostUuid));
replyer.reply(entity, rsp);
}
@RequestMapping(value=KVMConstant.KVM_CONNECT_PATH, method=RequestMethod.POST)
public @ResponseBody String connect(@RequestBody String body) {
ConnectCmd cmd = JSONObjectUtil.toObject(body, ConnectCmd.class);
config.connectHostUuids.put(cmd.getHostUuid(), cmd.getHostUuid());
if (config.connectException) {
throw new CloudRuntimeException("connect exception on purpose");
}
ConnectResponse rsp = new ConnectResponse();
if (config.connectSuccess) {
config.connectCmds.add(cmd);
rsp.setSuccess(true);
rsp.setLibvirtVersion("1.0.0");
rsp.setQemuVersion("1.3.0");
rsp.setIptablesSucc(true);
logger.debug("KVM connected");
} else {
rsp.setSuccess(false);
rsp.setError("Fail connect on purpose");
}
return JSONObjectUtil.toJsonString(rsp);
}
@RequestMapping(value=KVMConstant.KVM_ECHO_PATH, method=RequestMethod.POST)
public @ResponseBody String echo() {
return "";
}
@RequestMapping(value=KVMConstant.KVM_DETACH_VOLUME, method=RequestMethod.POST)
private @ResponseBody String detachDataVolume(HttpServletRequest req) throws InterruptedException {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
doDetachDataVolume(entity);
return null;
}
@RequestMapping(value=KVMConstant.KVM_VM_SYNC_PATH, method=RequestMethod.POST)
private @ResponseBody String vmSync(HttpServletRequest req) throws InterruptedException {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
doVmSync(entity);
return null;
}
@AsyncThread
private void doVmSync(HttpEntity<String> entity) {
synchronized (config) {
VmSyncResponse rsp = new VmSyncResponse();
if (!config.vmSyncSuccess) {
rsp.setSuccess(false);
rsp.setError("on purpose");
reply(entity, rsp);
return;
}
HashMap<String, String> vms = new HashMap<String, String>();
for (Map.Entry<String, KvmVmState> e : config.vms.entrySet()) {
vms.put(e.getKey(), e.getValue().toString());
}
rsp.setStates(vms);
reply(entity, rsp);
}
}
@RequestMapping(value=KVMSecurityGroupBackend.SECURITY_GROUP_REFRESH_RULE_ON_HOST_PATH, method=RequestMethod.POST)
private @ResponseBody String refreshSecurityGroupRulesOnHost(HttpServletRequest req) throws InterruptedException {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
doRefreshSecurityGroupRulesOnHost(entity);
return null;
}
private void doRefreshSecurityGroupRulesOnHost(HttpEntity<String> entity) {
RefreshAllRulesOnHostCmd cmd = JSONObjectUtil.toObject(entity.getBody(), RefreshAllRulesOnHostCmd.class);
RefreshAllRulesOnHostResponse rsp = new RefreshAllRulesOnHostResponse();
if (!config.securityGroupSuccess) {
rsp.setError("fail to apply security group rules on purpose");
rsp.setSuccess(false);
} else {
config.securityGroups.clear();
for (SecurityGroupRuleTO rto : cmd.getRuleTOs()) {
config.securityGroups.put(rto.getVmNicInternalName(), rto);
logger.debug(String.format("successfully applied security group rules for vm nic[%s], %s", rto.getVmNicInternalName(), rto));
}
config.securityGroupRefreshAllRulesOnHostCmds.add(cmd);
}
reply(entity, rsp);
}
@RequestMapping(value=KVMSecurityGroupBackend.SECURITY_GROUP_APPLY_RULE_PATH, method=RequestMethod.POST)
private @ResponseBody String applySecurityGroupRules(HttpServletRequest req) throws InterruptedException {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
doApplySecurityGroupRules(entity);
return null;
}
@AsyncThread
private void doApplySecurityGroupRules(HttpEntity<String> entity) {
ApplySecurityGroupRuleCmd cmd = JSONObjectUtil.toObject(entity.getBody(), ApplySecurityGroupRuleCmd.class);
ApplySecurityGroupRuleResponse rsp = new ApplySecurityGroupRuleResponse();
if (!config.securityGroupSuccess) {
rsp.setError("fail to apply security group rules on purpose");
rsp.setSuccess(false);
} else {
for (SecurityGroupRuleTO rto : cmd.getRuleTOs()) {
config.securityGroups.put(rto.getVmNicInternalName(), rto);
logger.debug(String.format("succesfully applied security group rules for vm nic[%s], %s", rto.getVmNicInternalName(), rto));
}
}
reply(entity, rsp);
}
@AsyncThread
private void doDetachDataVolume(HttpEntity<String> entity) {
DetachDataVolumeCmd cmd = JSONObjectUtil.toObject(entity.getBody(), DetachDataVolumeCmd.class);
DetachDataVolumeResponse rsp = new DetachDataVolumeResponse();
if (!config.detachVolumeSuccess) {
rsp.setError("failed to detach data volume on purpose");
rsp.setSuccess(false);
} else {
config.detachDataVolumeCmds.add(cmd);
logger.debug(String.format("successfully detached data volume: %s", entity.getBody()));
}
reply(entity, rsp);
}
@RequestMapping(value=KVMConstant.KVM_ATTACH_VOLUME, method=RequestMethod.POST)
private @ResponseBody String attachDataVolume(HttpServletRequest req) throws InterruptedException {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
doAttachDataVolume(entity);
return null;
}
private void doAttachDataVolume(HttpEntity<String> entity) {
AttachDataVolumeCmd cmd = JSONObjectUtil.toObject(entity.getBody(), AttachDataVolumeCmd.class);
if (!config.attachVolumeSuccess) {
throw new CloudRuntimeException("fail to attach volume on purpose");
}
config.attachDataVolumeCmds.add(cmd);
logger.debug(String.format("successfully attached data volume: %s", entity.getBody()));
AttachDataVolumeResponse rsp = new AttachDataVolumeResponse();
reply(entity, rsp);
}
@RequestMapping(value=KVMConstant.KVM_HOST_CAPACITY_PATH, method=RequestMethod.POST)
public @ResponseBody String hostCapacity(@RequestBody String body) {
if (config.hostFactException) {
throw new CloudRuntimeException("Host capacity exception on purpose");
}
HostCapacityResponse rsp = new HostCapacityResponse();
if (config.hostFactSuccess) {
rsp.setSuccess(true);
rsp.setCpuNum(config.cpuNum);
rsp.setCpuSpeed(config.cpuSpeed);
rsp.setTotalMemory(config.totalMemory);
rsp.setUsedCpu(config.usedCpu);
rsp.setUsedMemory(config.usedMemory);
} else {
rsp.setSuccess(false);
rsp.setError("Fail host capacity on purpose");
}
return JSONObjectUtil.toJsonString(rsp);
}
@RequestMapping(value=KVMConstant.KVM_CHECK_PHYSICAL_NETWORK_INTERFACE_PATH, method=RequestMethod.POST)
public @ResponseBody String checkPhysicalInterface(@RequestBody String body) {
if (config.checkPhysicalInterfaceException) {
throw new CloudRuntimeException("checkPhysicalInterface exception on purpose");
}
CheckPhysicalNetworkInterfaceCmd cmd = JSONObjectUtil.toObject(body, CheckPhysicalNetworkInterfaceCmd.class);
CheckPhysicalNetworkInterfaceResponse rsp = new CheckPhysicalNetworkInterfaceResponse();
if (config.checkPhysicalInterfaceSuccess) {
rsp.setSuccess(true);
logger.debug(String.format("Checked physical interfaces: %s", cmd.getInterfaceNames()));
} else {
rsp.setFailedInterfaceNames(cmd.getInterfaceNames());
rsp.setSuccess(false);
rsp.setError("Fail checkPhysicalInterface on purpose");
}
return JSONObjectUtil.toJsonString(rsp);
}
private void reply(HttpEntity<String> entity, AgentResponse rsp) {
if (replyer == null) {
replyer = new AsyncRESTReplyer();
}
replyer.reply(entity, rsp);
}
@AsyncThread
private void createBridge(HttpEntity<String> entity) {
CreateBridgeCmd cmd = JSONObjectUtil.toObject(entity.getBody(), CreateBridgeCmd.class);
CreateBridgeResponse rsp = new CreateBridgeResponse();
if (config.createL2NoVlanNetworkSuccess) {
logger.debug(String.format("create bridge[%s] successfully on kvm simulator", cmd.getBridgeName()));
config.createBridgeCmds.add(cmd);
} else {
rsp.setError("Fail createBridge on purpose");
rsp.setSuccess(false);
}
reply(entity, rsp);
}
@RequestMapping(value=KVMConstant.KVM_REALIZE_L2NOVLAN_NETWORK_PATH, method=RequestMethod.POST)
private @ResponseBody String createBridge(HttpServletRequest req) throws InterruptedException {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
createBridge(entity);
return null;
}
@RequestMapping(value=KVMConstant.KVM_MIGRATE_VM_PATH, method=RequestMethod.POST)
private @ResponseBody String migrateVm(HttpServletRequest req) throws InterruptedException {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
migrateVm(entity);
return null;
}
@AsyncThread
private void migrateVm(HttpEntity<String> entity) {
MigrateVmCmd cmd = JSONObjectUtil.toObject(entity.getBody(), MigrateVmCmd.class);
MigrateVmResponse rsp = new MigrateVmResponse();
if (!config.migrateVmSuccess) {
rsp.setSuccess(false);
rsp.setError("on purpose");
} else {
synchronized (config.migrateVmCmds) {
config.migrateVmCmds.add(cmd);
}
logger.debug(String.format("successfully migrated vm: %s", entity.getBody()));
}
reply(entity, rsp);
}
@RequestMapping(value=KVMConstant.KVM_CHECK_L2NOVLAN_NETWORK_PATH, method=RequestMethod.POST)
private @ResponseBody String checkNoVlanBridge(HttpServletRequest req) throws InterruptedException {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
checkNoVlanBridge(entity);
return null;
}
@AsyncThread
private void checkNoVlanBridge(HttpEntity<String> entity) {
CheckBridgeCmd cmd = JSONObjectUtil.toObject(entity.getBody(), CheckBridgeCmd.class);
CheckBridgeResponse rsp = new CheckBridgeResponse();
if (!config.checkNoVlanBridgeSuccess) {
rsp.setError("on purpose");
rsp.setSuccess(false);
} else {
logger.debug(String.format("successfully checked bridge: %s", entity.getBody()));
}
reply(entity, rsp);
}
@RequestMapping(value=KVMConstant.KVM_CHECK_L2VLAN_NETWORK_PATH, method=RequestMethod.POST)
private @ResponseBody String checkVlanBridge(HttpServletRequest req) throws InterruptedException {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
checkVlanBridge(entity);
return null;
}
@AsyncThread
private void checkVlanBridge(HttpEntity<String> entity) {
CheckVlanBridgeCmd cmd = JSONObjectUtil.toObject(entity.getBody(), CheckVlanBridgeCmd.class);
CheckVlanBridgeResponse rsp = new CheckVlanBridgeResponse();
if (!config.checkVlanBridgeSuccess) {
rsp.setError("on purpose");
rsp.setSuccess(false);
} else {
logger.debug(String.format("successfully checked bridge: %s", entity.getBody()));
}
reply(entity, rsp);
}
@AsyncThread
private void createVlanBridge(HttpEntity<String> entity) {
CreateVlanBridgeCmd cmd = JSONObjectUtil.toObject(entity.getBody(), CreateVlanBridgeCmd.class);
CreateVlanBridgeResponse rsp = new CreateVlanBridgeResponse();
if (config.createL2VlanNetworkSuccess) {
config.vlanBridges.add(cmd);
logger.debug(String.format("create bridge[name:%s, vlan:%s] successfully on kvm simulator", cmd.getBridgeName(), cmd.getVlan()));
} else {
rsp.setError("Fail createVlanBridge on purpose");
rsp.setSuccess(false);
}
reply(entity, rsp);
}
@RequestMapping(value=KVMConstant.KVM_REALIZE_L2VLAN_NETWORK_PATH, method=RequestMethod.POST)
private @ResponseBody String createVlanBridge(HttpServletRequest req) throws InterruptedException {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
createVlanBridge(entity);
return null;
}
@RequestMapping(value=KVMConstant.KVM_START_VM_PATH, method=RequestMethod.POST)
private @ResponseBody String createVm(HttpServletRequest req) throws InterruptedException {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
createVm(entity);
return null;
}
@AsyncThread
private void createVm(HttpEntity<String> entity) {
StartVmCmd cmd = JSONObjectUtil.toObject(entity.getBody(), StartVmCmd.class);
StartVmResponse rsp = new StartVmResponse();
if (config.startVmSuccess) {
if (config.startVmFailureChance != 0) {
if (Math.random() <= config.startVmFailureChance) {
rsp.setError("on purpose");
rsp.setSuccess(false);
}
} else {
logger.debug(String.format("successfully start vm on kvm host, %s", entity.getBody()));
synchronized (config) {
config.vms.put(cmd.getVmInstanceUuid(), KvmVmState.Running);
logger.debug(String.format("current running vm[%s]", config.vms.size()));
}
config.startVmCmd = cmd;
}
} else {
String err = "fail start vm on purpose";
rsp.setError(err);
rsp.setSuccess(false);
}
replyer.reply(entity, rsp);
}
@RequestMapping(value=KVMConstant.KVM_STOP_VM_PATH, method=RequestMethod.POST)
private @ResponseBody String stopVm(HttpServletRequest req) throws InterruptedException {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
stopVm(entity);
return null;
}
private void stopVm(HttpEntity<String> entity) {
StopVmCmd cmd = JSONObjectUtil.toObject(entity.getBody(), StopVmCmd.class);
StopVmResponse rsp = new StopVmResponse();
if (config.stopVmSuccess) {
logger.debug(String.format("successfully stop vm on kvm host, %s", entity.getBody()));
synchronized (config) {
config.vms.put(cmd.getUuid(), KvmVmState.Shutdown);
}
config.stopVmCmds.add(cmd);
} else {
String err = "fail stop vm on purpose";
rsp.setError(err);
rsp.setSuccess(false);
}
replyer.reply(entity, rsp);
}
@RequestMapping(value = KVMConstant.KVM_PAUSE_VM_PATH, method = RequestMethod.POST)
private @ResponseBody String suspendVm(HttpServletRequest req) throws InterruptedException{
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
suspendVm(entity);
return null;
}
private void suspendVm(HttpEntity<String> entity) {
PauseVmCmd cmd = JSONObjectUtil.toObject(entity.getBody(), PauseVmCmd.class);
PauseVmResponse rsp = new PauseVmResponse();
if (config.pauseVmSuccess) {
logger.debug(String.format("successfully suspend vm on kvm host, %s", entity.getBody()));
synchronized (config) {
config.vms.put(cmd.getUuid(), KvmVmState.Suspended);
}
config.pauseVmCmds.add(cmd);
} else {
String err = "fail suspend vm on purpose";
rsp.setError(err);
rsp.setSuccess(false);
}
replyer.reply(entity, rsp);
}
@RequestMapping(value = KVMConstant.KVM_RESUME_VM_PATH, method = RequestMethod.POST)
private @ResponseBody String resumeVm(HttpServletRequest req) throws InterruptedException{
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
resumeVm(entity);
return null;
}
private void resumeVm(HttpEntity<String> entity) {
ResumeVmCmd cmd = JSONObjectUtil.toObject(entity.getBody(), ResumeVmCmd.class);
ResumeVmResponse rsp = new ResumeVmResponse();
if (config.resumeVmSuccess) {
logger.debug(String.format("successfully resume vm on kvm host, %s", entity.getBody()));
synchronized (config) {
config.vms.put(cmd.getUuid(), KvmVmState.Running);
}
config.resumeVmCmds.add(cmd);
} else {
String err = "fail resume vm on purpose";
rsp.setError(err);
rsp.setSuccess(false);
}
replyer.reply(entity, rsp);
}
@RequestMapping(value=KVMConstant.KVM_REBOOT_VM_PATH, method=RequestMethod.POST)
private @ResponseBody String rebootVm(HttpServletRequest req) throws InterruptedException {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
rebootVm(entity);
return null;
}
private void rebootVm(HttpEntity<String> entity) {
RebootVmCmd cmd = JSONObjectUtil.toObject(entity.getBody(), RebootVmCmd.class);
RebootVmResponse rsp = new RebootVmResponse();
if (config.rebootVmSuccess) {
logger.debug(String.format("successfully reboot vm on kvm host, %s", entity.getBody()));
synchronized (config) {
config.vms.put(cmd.getUuid(), KvmVmState.Running);
}
config.rebootVmCmds.add(cmd);
} else {
String err = "fail reboot vm on purpose";
rsp.setError(err);
rsp.setSuccess(false);
}
replyer.reply(entity, rsp);
}
@RequestMapping(value=KVMConstant.KVM_DESTROY_VM_PATH, method=RequestMethod.POST)
private @ResponseBody String destroyVm(HttpServletRequest req) throws InterruptedException {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
destroyVm(entity);
return null;
}
@AsyncThread
private void destroyVm(HttpEntity<String> entity) {
DestroyVmCmd cmd = JSONObjectUtil.toObject(entity.getBody(), DestroyVmCmd.class);
DestroyVmResponse rsp = new DestroyVmResponse();
if (config.destroyVmSuccess) {
config.destroyedVmUuid = cmd.getUuid();
logger.debug(String.format("successfully destroy vm on kvm host, %s", entity.getBody()));
synchronized (config) {
config.vms.remove(cmd.getUuid());
}
} else {
String err = "fail destroy vm on purpose";
rsp.setError(err);
rsp.setSuccess(false);
}
replyer.reply(entity, rsp);
}
@RequestMapping(value=KVMConstant.KVM_GET_VNC_PORT_PATH, method=RequestMethod.POST)
private @ResponseBody String getVncPort(HttpServletRequest req) throws InterruptedException {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
getVncPort(entity);
return null;
}
private void getVncPort(HttpEntity<String> entity) {
KVMAgentCommands.GetVncPortCmd cmd = JSONObjectUtil.toObject(entity.getBody(), KVMAgentCommands.GetVncPortCmd.class);
KVMAgentCommands.GetVncPortResponse rsp = new KVMAgentCommands.GetVncPortResponse();
rsp.setPort(config.consolePort);
logger.debug(String.format("successfully get console port[port:%s] for vm[uuid:%s]", rsp.getPort(), cmd.getVmUuid()));
replyer.reply(entity, rsp);
}
@RequestMapping(value=KVMConstant.KVM_LOGOUT_ISCSI_PATH, method=RequestMethod.POST)
private @ResponseBody String logoutIscsiTarget(HttpServletRequest req) throws InterruptedException {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
logoutIscsiTarget(entity);
return null;
}
private void logoutIscsiTarget(HttpEntity<String> entity) {
LogoutIscsiTargetCmd cmd = JSONObjectUtil.toObject(entity.getBody(), KVMAgentCommands.LogoutIscsiTargetCmd.class);
LogoutIscsiTargetRsp rsp = new LogoutIscsiTargetRsp();
synchronized (config.logoutIscsiTargetCmds) {
config.logoutIscsiTargetCmds.add(cmd);
}
logger.debug(String.format("logout iscsi target: %s", cmd.getTarget()));
replyer.reply(entity, rsp);
}
@RequestMapping(value=KVMConstant.KVM_LOGIN_ISCSI_PATH, method=RequestMethod.POST)
private @ResponseBody String loginIscsiTarget(HttpServletRequest req) throws InterruptedException {
HttpEntity<String> entity = restf.httpServletRequestToHttpEntity(req);
loginIscsiTarget(entity);
return null;
}
private void loginIscsiTarget(HttpEntity<String> entity) {
LoginIscsiTargetCmd cmd = JSONObjectUtil.toObject(entity.getBody(), KVMAgentCommands.LoginIscsiTargetCmd.class);
LoginIscsiTargetRsp rsp = new LoginIscsiTargetRsp();
synchronized (config.loginIscsiTargetCmds) {
config.loginIscsiTargetCmds.add(cmd);
}
logger.debug(String.format("login iscsi target: %s", cmd.getTarget()));
replyer.reply(entity, rsp);
}
@ExceptionHandler(Exception.class)
public ModelAndView handleAllException(Exception ex) {
logger.warn(ex.getMessage(), ex);
ModelAndView model = new ModelAndView("error/generic_error");
model.addObject("errMsg", ex.getMessage());
return model;
}
}