This is an automated email from the ASF dual-hosted git repository.
rohit pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/master by this push:
new 81dfcbb server: Use ACPI event to reboot VM on KVM, and Use 'forced'
reboot option to stop and start the VM(s) (#4681)
81dfcbb is described below
commit 81dfcbb5f56b616b9edcf97fffedb26c187a7fc2
Author: sureshanaparti <[email protected]>
AuthorDate: Sat Mar 6 14:58:56 2021 +0530
server: Use ACPI event to reboot VM on KVM, and Use 'forced' reboot option
to stop and start the VM(s) (#4681)
* Updated libvirt's native reboot operation for VM on KVM using ACPI event,
and Added 'forced' reboot option to stop and start the VM (using
rebootVirtualMachine API)
* Added 'forced' reboot option for System VM and Router
- New parameter 'forced' in rebootSystemVm API, to stop and then start
System VM
- New parameter 'forced' in rebootRouter API, to force stop and then start
Router
* Added force reboot tests for User VM, System VM and Router
---
.../network/VirtualNetworkApplianceService.java | 2 +-
.../api/command/admin/router/RebootRouterCmd.java | 9 +-
.../command/admin/systemvm/RebootSystemVmCmd.java | 7 ++
.../api/command/user/vm/RebootVMCmd.java | 7 ++
.../com/cloud/vm/VirtualMachineManagerImpl.java | 6 +-
.../kvm/resource/LibvirtComputingResource.java | 31 +-----
.../router/VirtualNetworkApplianceManagerImpl.java | 6 +-
.../com/cloud/server/ManagementServerImpl.java | 35 ++++--
.../main/java/com/cloud/vm/UserVmManagerImpl.java | 40 ++++++-
.../vpc/MockVpcVirtualNetworkApplianceManager.java | 2 +-
test/integration/smoke/test_routers.py | 43 ++++++++
test/integration/smoke/test_ssvm.py | 121 ++++++++++++++++++++-
test/integration/smoke/test_vm_life_cycle.py | 34 ++++++
tools/marvin/marvin/lib/base.py | 8 +-
ui/src/config/section/compute.js | 1 +
ui/src/config/section/infra/routers.js | 1 +
ui/src/config/section/infra/systemVms.js | 3 +-
17 files changed, 303 insertions(+), 53 deletions(-)
diff --git
a/api/src/main/java/com/cloud/network/VirtualNetworkApplianceService.java
b/api/src/main/java/com/cloud/network/VirtualNetworkApplianceService.java
index 8504efd..92a664f 100644
--- a/api/src/main/java/com/cloud/network/VirtualNetworkApplianceService.java
+++ b/api/src/main/java/com/cloud/network/VirtualNetworkApplianceService.java
@@ -44,7 +44,7 @@ public interface VirtualNetworkApplianceService {
* the command specifying router's id
* @return router if successful
*/
- VirtualRouter rebootRouter(long routerId, boolean reprogramNetwork) throws
ConcurrentOperationException, ResourceUnavailableException,
InsufficientCapacityException;
+ VirtualRouter rebootRouter(long routerId, boolean reprogramNetwork,
boolean forced) throws ConcurrentOperationException,
ResourceUnavailableException, InsufficientCapacityException;
VirtualRouter upgradeRouter(UpgradeRouterCmd cmd);
diff --git
a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/RebootRouterCmd.java
b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/RebootRouterCmd.java
index 802e3df..764d304 100644
---
a/api/src/main/java/org/apache/cloudstack/api/command/admin/router/RebootRouterCmd.java
+++
b/api/src/main/java/org/apache/cloudstack/api/command/admin/router/RebootRouterCmd.java
@@ -49,6 +49,9 @@ public class RebootRouterCmd extends BaseAsyncCmd {
@Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType =
DomainRouterResponse.class, required = true, description = "the ID of the
router")
private Long id;
+ @Parameter(name = ApiConstants.FORCED, type = CommandType.BOOLEAN,
required = false, description = "Force reboot the router (Router is force
Stopped and then Started)", since = "4.16.0")
+ private Boolean forced;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -96,10 +99,14 @@ public class RebootRouterCmd extends BaseAsyncCmd {
return getId();
}
+ public boolean isForced() {
+ return (forced != null) ? forced : false;
+ }
+
@Override
public void execute() throws ConcurrentOperationException,
ResourceUnavailableException, InsufficientCapacityException {
CallContext.current().setEventDetails("Router Id: " +
this._uuidMgr.getUuid(VirtualMachine.class,getId()));
- VirtualRouter result = _routerService.rebootRouter(getId(), true);
+ VirtualRouter result = _routerService.rebootRouter(getId(), true,
isForced());
if (result != null) {
DomainRouterResponse response =
_responseGenerator.createDomainRouterResponse(result);
response.setResponseName("router");
diff --git
a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/RebootSystemVmCmd.java
b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/RebootSystemVmCmd.java
index ebc50ae..352fd3b 100644
---
a/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/RebootSystemVmCmd.java
+++
b/api/src/main/java/org/apache/cloudstack/api/command/admin/systemvm/RebootSystemVmCmd.java
@@ -52,6 +52,9 @@ public class RebootSystemVmCmd extends BaseAsyncCmd {
description = "The ID of the system virtual machine")
private Long id;
+ @Parameter(name = ApiConstants.FORCED, type = CommandType.BOOLEAN,
required = false, description = "Force reboot the system VM (System VM is
Stopped and then Started)", since = "4.16.0")
+ private Boolean forced;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -104,6 +107,10 @@ public class RebootSystemVmCmd extends BaseAsyncCmd {
return getId();
}
+ public boolean isForced() {
+ return (forced != null) ? forced : false;
+ }
+
@Override
public void execute() {
CallContext.current().setEventDetails("Vm Id: " +
this._uuidMgr.getUuid(VirtualMachine.class, getId()));
diff --git
a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RebootVMCmd.java
b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RebootVMCmd.java
index 5bdbbb6..d827a6b 100644
---
a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RebootVMCmd.java
+++
b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/RebootVMCmd.java
@@ -53,6 +53,9 @@ public class RebootVMCmd extends BaseAsyncCmd implements
UserCmd {
required=true, description="The ID of the virtual machine")
private Long id;
+ @Parameter(name = ApiConstants.FORCED, type = CommandType.BOOLEAN,
required = false, description = "Force reboot the VM (VM is Stopped and then
Started)", since = "4.16.0")
+ private Boolean forced;
+
@Parameter(name = ApiConstants.BOOT_INTO_SETUP, type =
CommandType.BOOLEAN, required = false, description = "Boot into hardware setup
menu or not", since = "4.15.0.0")
private Boolean bootIntoSetup;
@@ -64,6 +67,10 @@ public class RebootVMCmd extends BaseAsyncCmd implements
UserCmd {
return id;
}
+ public boolean isForced() {
+ return (forced != null) ? forced : false;
+ }
+
public Boolean getBootIntoSetup() {
return bootIntoSetup;
}
diff --git
a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
index dfec0b1..2bbb8cb 100755
---
a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
+++
b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -3458,7 +3458,6 @@ public class VirtualMachineManagerImpl extends
ManagerBase implements VirtualMac
final DeployDestination dest = new DeployDestination(dc, pod, cluster,
host);
try {
-
final Commands cmds = new Commands(Command.OnError.Stop);
RebootCommand rebootCmd = new RebootCommand(vm.getInstanceName(),
getExecuteInSequence(vm.getHypervisorType()));
VirtualMachineTO vmTo = getVmTO(vm.getId());
@@ -3476,7 +3475,10 @@ public class VirtualMachineManagerImpl extends
ManagerBase implements VirtualMac
}
return;
}
- s_logger.info("Unable to reboot VM " + vm + " on " +
dest.getHost() + " due to " + (rebootAnswer == null ? " no reboot answer" :
rebootAnswer.getDetails()));
+
+ String errorMsg = "Unable to reboot VM " + vm + " on " +
dest.getHost() + " due to " + (rebootAnswer == null ? "no reboot response" :
rebootAnswer.getDetails());
+ s_logger.info(errorMsg);
+ throw new CloudRuntimeException(errorMsg);
} catch (final OperationTimedoutException e) {
s_logger.warn("Unable to send the reboot command to host " +
dest.getHost() + " for the vm " + vm + " due to operation timeout", e);
throw new CloudRuntimeException("Failed to reboot the vm on host "
+ dest.getHost());
diff --git
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
index cfa5474..e380ef1 100644
---
a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
+++
b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
@@ -134,7 +134,6 @@ import
com.cloud.hypervisor.kvm.resource.LibvirtVMDef.GuestDef;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.GuestResourceDef;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InputDef;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef;
-import
com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef.GuestNetType;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.RngDef;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.RngDef.RngBackendModel;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.SCSIDef;
@@ -3228,35 +3227,15 @@ public class LibvirtComputingResource extends
ServerResourceBase implements Serv
String msg = null;
try {
dm = conn.domainLookupByName(vmName);
- // Get XML Dump including the secure information such as VNC
password
- // By passing 1, or VIR_DOMAIN_XML_SECURE flag
- //
https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainXMLFlags
- String vmDef = dm.getXMLDesc(1);
- final LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser();
- parser.parseDomainXML(vmDef);
- for (final InterfaceDef nic : parser.getInterfaces()) {
- if (nic.getNetType() == GuestNetType.BRIDGE &&
nic.getBrName().startsWith("cloudVirBr")) {
- try {
- final int vnetId =
Integer.parseInt(nic.getBrName().replaceFirst("cloudVirBr", ""));
- final String pifName = getPif(_guestBridgeName);
- final String newBrName = "br" + pifName + "-" + vnetId;
- vmDef = vmDef.replace("'" + nic.getBrName() + "'", "'"
+ newBrName + "'");
- s_logger.debug("VM bridge name is changed from " +
nic.getBrName() + " to " + newBrName);
- } catch (final NumberFormatException e) {
- continue;
- }
- }
- }
- s_logger.debug(vmDef);
- msg = stopVM(conn, vmName, false);
- msg = startVM(conn, vmName, vmDef);
+ // Perform ACPI based reboot
+ //
https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainReboot
+ //
https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainRebootFlagValues
+ // Send ACPI event to Reboot
+ dm.reboot(0x1);
return null;
} catch (final LibvirtException e) {
s_logger.warn("Failed to create vm", e);
msg = e.getMessage();
- } catch (final InternalErrorException e) {
- s_logger.warn("Failed to create vm", e);
- msg = e.getMessage();
} finally {
try {
if (dm != null) {
diff --git
a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
index 8e38fb9..2657b3f 100644
---
a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
+++
b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
@@ -510,7 +510,7 @@ Configurable, StateListener<VirtualMachine.State,
VirtualMachine.Event, VirtualM
@Override
@ActionEvent(eventType = EventTypes.EVENT_ROUTER_REBOOT, eventDescription
= "rebooting router Vm", async = true)
- public VirtualRouter rebootRouter(final long routerId, final boolean
reprogramNetwork) throws ConcurrentOperationException,
ResourceUnavailableException,
+ public VirtualRouter rebootRouter(final long routerId, final boolean
reprogramNetwork, final boolean forced) throws ConcurrentOperationException,
ResourceUnavailableException,
InsufficientCapacityException {
final Account caller = CallContext.current().getCallingAccount();
@@ -531,7 +531,7 @@ Configurable, StateListener<VirtualMachine.State,
VirtualMachine.Event, VirtualM
final UserVO user =
_userDao.findById(CallContext.current().getCallingUserId());
s_logger.debug("Stopping and starting router " + router + " as a part
of router reboot");
- if (stop(router, false, user, caller) != null) {
+ if (stop(router, forced, user, caller) != null) {
return startRouter(routerId, reprogramNetwork);
} else {
throw new CloudRuntimeException("Failed to reboot router " +
router);
@@ -1048,7 +1048,7 @@ Configurable, StateListener<VirtualMachine.State,
VirtualMachine.Event, VirtualM
}
_alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_DOMAIN_ROUTER,
backupRouter.getDataCenterId(), backupRouter.getPodIdToDeployIn(), title,
title);
try {
- rebootRouter(backupRouter.getId(), true);
+ rebootRouter(backupRouter.getId(), true, false);
} catch (final ConcurrentOperationException e) {
s_logger.warn("Fail to reboot " +
backupRouter.getInstanceName(), e);
} catch (final ResourceUnavailableException e) {
diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java
b/server/src/main/java/com/cloud/server/ManagementServerImpl.java
index 3ef1c20..18afeb4 100644
--- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java
@@ -2502,7 +2502,6 @@ public class ManagementServerImpl extends ManagerBase
implements ManagementServe
}
private ConsoleProxyVO stopConsoleProxy(final VMInstanceVO systemVm, final
boolean isForced) throws ResourceUnavailableException,
OperationTimedoutException, ConcurrentOperationException {
-
_itMgr.advanceStop(systemVm.getUuid(), isForced);
return _consoleProxyDao.findById(systemVm.getId());
}
@@ -2512,6 +2511,11 @@ public class ManagementServerImpl extends ManagerBase
implements ManagementServe
return _consoleProxyDao.findById(instanceId);
}
+ private ConsoleProxyVO forceRebootConsoleProxy(final VMInstanceVO
systemVm) throws ResourceUnavailableException, OperationTimedoutException,
ConcurrentOperationException {
+ _itMgr.advanceStop(systemVm.getUuid(), false);
+ return _consoleProxyMgr.startProxy(systemVm.getId(), true);
+ }
+
protected ConsoleProxyVO destroyConsoleProxy(final long instanceId) {
final ConsoleProxyVO proxy = _consoleProxyDao.findById(instanceId);
@@ -3401,6 +3405,11 @@ public class ManagementServerImpl extends ManagerBase
implements ManagementServe
return _secStorageVmDao.findById(instanceId);
}
+ private SecondaryStorageVmVO forceRebootSecondaryStorageVm(final
VMInstanceVO systemVm) throws ResourceUnavailableException,
OperationTimedoutException, ConcurrentOperationException {
+ _itMgr.advanceStop(systemVm.getUuid(), false);
+ return _secStorageVmMgr.startSecStorageVm(systemVm.getId());
+ }
+
protected SecondaryStorageVmVO destroySecondaryStorageVm(final long
instanceId) {
final SecondaryStorageVmVO secStorageVm =
_secStorageVmDao.findById(instanceId);
cleanupDownloadUrlsInZone(secStorageVm.getDataCenterId());
@@ -3570,12 +3579,24 @@ public class ManagementServerImpl extends ManagerBase
implements ManagementServe
throw ex;
}
- if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)) {
-
ActionEventUtils.startNestedActionEvent(EventTypes.EVENT_PROXY_REBOOT,
"rebooting console proxy Vm");
- return rebootConsoleProxy(cmd.getId());
- } else {
-
ActionEventUtils.startNestedActionEvent(EventTypes.EVENT_SSVM_REBOOT,
"rebooting secondary storage Vm");
- return rebootSecondaryStorageVm(cmd.getId());
+ try {
+ if (systemVm.getType().equals(VirtualMachine.Type.ConsoleProxy)) {
+
ActionEventUtils.startNestedActionEvent(EventTypes.EVENT_PROXY_REBOOT,
"rebooting console proxy Vm");
+ if (cmd.isForced()) {
+ return forceRebootConsoleProxy(systemVm);
+ }
+ return rebootConsoleProxy(cmd.getId());
+ } else {
+
ActionEventUtils.startNestedActionEvent(EventTypes.EVENT_SSVM_REBOOT,
"rebooting secondary storage Vm");
+ if (cmd.isForced()) {
+ return forceRebootSecondaryStorageVm(systemVm);
+ }
+ return rebootSecondaryStorageVm(cmd.getId());
+ }
+ } catch (final ResourceUnavailableException e) {
+ throw new CloudRuntimeException("Unable to reboot " + systemVm, e);
+ } catch (final OperationTimedoutException e) {
+ throw new CloudRuntimeException("Operation timed out - Unable to
reboot " + systemVm, e);
}
}
diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
index 31bad15..1eafefa 100644
--- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java
@@ -800,7 +800,7 @@ public class UserVmManagerImpl extends ManagerBase
implements UserVmManager, Vir
return true;
}
- if (rebootVirtualMachine(userId, vmId, false) == null) {
+ if (rebootVirtualMachine(userId, vmId, false, false) == null) {
s_logger.warn("Failed to reboot the vm " + vmInstance);
return false;
} else {
@@ -911,7 +911,7 @@ public class UserVmManagerImpl extends ManagerBase
implements UserVmManager, Vir
s_logger.debug("Vm " + vmInstance + " is stopped, not
rebooting it as a part of SSH Key reset");
return true;
}
- if (rebootVirtualMachine(userId, vmId, false) == null) {
+ if (rebootVirtualMachine(userId, vmId, false, false) == null) {
s_logger.warn("Failed to reboot the vm " + vmInstance);
return false;
} else {
@@ -948,7 +948,7 @@ public class UserVmManagerImpl extends ManagerBase
implements UserVmManager, Vir
return status;
}
- private UserVm rebootVirtualMachine(long userId, long vmId, boolean
enterSetup) throws InsufficientCapacityException, ResourceUnavailableException {
+ private UserVm rebootVirtualMachine(long userId, long vmId, boolean
enterSetup, boolean forced) throws InsufficientCapacityException,
ResourceUnavailableException {
UserVmVO vm = _vmDao.findById(vmId);
if (s_logger.isTraceEnabled()) {
@@ -963,6 +963,15 @@ public class UserVmManagerImpl extends ManagerBase
implements UserVmManager, Vir
if (vm.getState() == State.Running && vm.getHostId() != null) {
collectVmDiskStatistics(vm);
collectVmNetworkStatistics(vm);
+
+ if (forced) {
+ Host vmOnHost = _hostDao.findById(vm.getHostId());
+ if (vmOnHost == null || vmOnHost.getResourceState() !=
ResourceState.Enabled || vmOnHost.getStatus() != Status.Up ) {
+ throw new CloudRuntimeException("Unable to force reboot
the VM as the host: " + vm.getHostId() + " is not in the right state");
+ }
+ return forceRebootVirtualMachine(vmId, vm.getHostId(),
enterSetup);
+ }
+
DataCenterVO dc = _dcDao.findById(vm.getDataCenterId());
try {
if (dc.getNetworkType() == DataCenter.NetworkType.Advanced) {
@@ -986,7 +995,7 @@ public class UserVmManagerImpl extends ManagerBase
implements UserVmManager, Vir
throw new CloudRuntimeException("Concurrent operations on
starting router. " + e);
} catch (Exception ex){
throw new CloudRuntimeException("Router start failed due to" +
ex);
- }finally {
+ } finally {
if (s_logger.isInfoEnabled()) {
s_logger.info(String.format("Rebooting vm %s%s.",
vm.getInstanceName(), enterSetup? " entering hardware setup menu" : " as is"));
}
@@ -1007,6 +1016,24 @@ public class UserVmManagerImpl extends ManagerBase
implements UserVmManager, Vir
}
}
+ private UserVm forceRebootVirtualMachine(long vmId, long hostId, boolean
enterSetup) {
+ try {
+ if (stopVirtualMachine(vmId, false) != null) {
+ Map<VirtualMachineProfile.Param,Object> params = null;
+ if (enterSetup) {
+ params = new HashMap();
+ params.put(VirtualMachineProfile.Param.BootIntoSetup,
Boolean.TRUE);
+ }
+ return startVirtualMachine(vmId, null, null, hostId, params,
null).first();
+ }
+ } catch (ResourceUnavailableException e) {
+ throw new CloudRuntimeException("Unable to reboot the VM: " +
vmId, e);
+ } catch (CloudException e) {
+ throw new CloudRuntimeException("Unable to reboot the VM: " +
vmId, e);
+ }
+ return null;
+ }
+
@Override
@ActionEvent(eventType = EventTypes.EVENT_VM_UPGRADE, eventDescription =
"upgrading Vm")
/*
@@ -2894,7 +2921,7 @@ public class UserVmManagerImpl extends ManagerBase
implements UserVmManager, Vir
// Verify input parameters
UserVmVO vmInstance = _vmDao.findById(vmId);
if (vmInstance == null) {
- throw new InvalidParameterValueException("unable to find a virtual
machine with id " + vmId);
+ throw new InvalidParameterValueException("Unable to find a virtual
machine with id " + vmId);
}
_accountMgr.checkAccess(caller, null, true, vmInstance);
@@ -2916,7 +2943,8 @@ public class UserVmManagerImpl extends ManagerBase
implements UserVmManager, Vir
if (enterSetup != null && enterSetup &&
!HypervisorType.VMware.equals(vmInstance.getHypervisorType())) {
throw new InvalidParameterValueException("Booting into a hardware
setup menu is not implemented on " + vmInstance.getHypervisorType());
}
- UserVm userVm =
rebootVirtualMachine(CallContext.current().getCallingUserId(), vmId, enterSetup
== null ? false : cmd.getBootIntoSetup());
+
+ UserVm userVm =
rebootVirtualMachine(CallContext.current().getCallingUserId(), vmId, enterSetup
== null ? false : cmd.getBootIntoSetup(), cmd.isForced());
if (userVm != null ) {
// update the vmIdCountMap if the vm is in advanced shared network
with out services
final List<NicVO> nics = _nicDao.listByVmId(vmId);
diff --git
a/server/src/test/java/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java
b/server/src/test/java/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java
index abb1863..e734fdf 100644
---
a/server/src/test/java/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java
+++
b/server/src/test/java/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java
@@ -110,7 +110,7 @@ public class MockVpcVirtualNetworkApplianceManager extends
ManagerBase implement
* @see
com.cloud.network.VirtualNetworkApplianceService#rebootRouter(long, boolean)
*/
@Override
- public VirtualRouter rebootRouter(final long routerId, final boolean
reprogramNetwork) throws ConcurrentOperationException,
ResourceUnavailableException {
+ public VirtualRouter rebootRouter(final long routerId, final boolean
reprogramNetwork, final boolean forced) throws ConcurrentOperationException,
ResourceUnavailableException {
// TODO Auto-generated method stub
return null;
}
diff --git a/test/integration/smoke/test_routers.py
b/test/integration/smoke/test_routers.py
index 3a20d64..356bd21 100644
--- a/test/integration/smoke/test_routers.py
+++ b/test/integration/smoke/test_routers.py
@@ -815,3 +815,46 @@ class TestRouterServices(cloudstackTestCase):
"Router response after reboot is either is invalid\
or in stopped state")
return
+
+ @attr(tags=["advanced", "advancedns", "smoke", "dvs"],
required_hardware="false")
+ def test_10_reboot_router_forced(self):
+ """Test force reboot router
+ """
+
+ list_router_response = list_routers(
+ self.apiclient,
+ account=self.account.name,
+ domainid=self.account.domainid
+ )
+ self.assertEqual(
+ isinstance(list_router_response, list),
+ True,
+ "Check list response returns a valid list"
+ )
+ router = list_router_response[0]
+
+ public_ip = router.publicip
+
+ self.debug("Force rebooting the router with ID: %s" % router.id)
+ # Reboot the router
+ cmd = rebootRouter.rebootRouterCmd()
+ cmd.id = router.id
+ cmd.forced = True
+ self.apiclient.rebootRouter(cmd)
+
+ # List routers to check state of router
+ retries_cnt = 10
+ while retries_cnt >= 0:
+ router_response = list_routers(
+ self.apiclient,
+ id=router.id
+ )
+ if self.verifyRouterResponse(router_response, public_ip):
+ self.debug("Router is running successfully after force reboot")
+ return
+ time.sleep(10)
+ retries_cnt = retries_cnt - 1
+ self.fail(
+ "Router response after force reboot is either invalid\
+ or router in stopped state")
+ return
diff --git a/test/integration/smoke/test_ssvm.py
b/test/integration/smoke/test_ssvm.py
index bb83931..0392d9e 100644
--- a/test/integration/smoke/test_ssvm.py
+++ b/test/integration/smoke/test_ssvm.py
@@ -959,7 +959,122 @@ class TestSSVMs(cloudstackTestCase):
"basic",
"sg"],
required_hardware="true")
- def test_09_destroy_ssvm(self):
+ def test_09_reboot_ssvm_forced(self):
+ """Test force reboot SSVM
+ """
+
+ list_ssvm_response = list_ssvms(
+ self.apiclient,
+ systemvmtype='secondarystoragevm',
+ state='Running',
+ zoneid=self.zone.id
+ )
+
+ self.assertEqual(
+ isinstance(list_ssvm_response, list),
+ True,
+ "Check list response returns a valid list"
+ )
+
+ ssvm_response = list_ssvm_response[0]
+
+ hosts = list_hosts(
+ self.apiclient,
+ id=ssvm_response.hostid
+ )
+ self.assertEqual(
+ isinstance(hosts, list),
+ True,
+ "Check list response returns a valid list"
+ )
+
+ self.debug("Force rebooting SSVM: %s" % ssvm_response.id)
+ cmd = rebootSystemVm.rebootSystemVmCmd()
+ cmd.id = ssvm_response.id
+ cmd.forced = True
+ self.apiclient.rebootSystemVm(cmd)
+
+ ssvm_response = self.checkForRunningSystemVM(ssvm_response)
+ self.debug("SSVM State: %s" % ssvm_response.state)
+ self.assertEqual(
+ 'Running',
+ str(ssvm_response.state),
+ "Check whether SSVM is running or not"
+ )
+
+ # Wait for the agent to be up
+ self.waitForSystemVMAgent(ssvm_response.name)
+
+ # Wait until NFS stores mounted before running the script
+ time.sleep(90)
+ # Call to verify cloud process is running
+ self.test_03_ssvm_internals()
+
+ @attr(
+ tags=[
+ "advanced",
+ "advancedns",
+ "smoke",
+ "basic",
+ "sg"],
+ required_hardware="true")
+ def test_10_reboot_cpvm_forced(self):
+ """Test force reboot CPVM
+ """
+
+ list_cpvm_response = list_ssvms(
+ self.apiclient,
+ systemvmtype='consoleproxy',
+ state='Running',
+ zoneid=self.zone.id
+ )
+ self.assertEqual(
+ isinstance(list_cpvm_response, list),
+ True,
+ "Check list response returns a valid list"
+ )
+ cpvm_response = list_cpvm_response[0]
+
+ hosts = list_hosts(
+ self.apiclient,
+ id=cpvm_response.hostid
+ )
+ self.assertEqual(
+ isinstance(hosts, list),
+ True,
+ "Check list response returns a valid list"
+ )
+
+ self.debug("Force rebooting CPVM: %s" % cpvm_response.id)
+
+ cmd = rebootSystemVm.rebootSystemVmCmd()
+ cmd.id = cpvm_response.id
+ cmd.forced = True
+ self.apiclient.rebootSystemVm(cmd)
+
+ cpvm_response = self.checkForRunningSystemVM(cpvm_response)
+ self.debug("CPVM state: %s" % cpvm_response.state)
+ self.assertEqual(
+ 'Running',
+ str(cpvm_response.state),
+ "Check whether CPVM is running or not"
+ )
+
+ # Wait for the agent to be up
+ self.waitForSystemVMAgent(cpvm_response.name)
+
+ # Call to verify cloud process is running
+ self.test_04_cpvm_internals()
+
+ @attr(
+ tags=[
+ "advanced",
+ "advancedns",
+ "smoke",
+ "basic",
+ "sg"],
+ required_hardware="true")
+ def test_11_destroy_ssvm(self):
"""Test destroy SSVM
"""
@@ -1031,7 +1146,7 @@ class TestSSVMs(cloudstackTestCase):
"basic",
"sg"],
required_hardware="true")
- def test_10_destroy_cpvm(self):
+ def test_12_destroy_cpvm(self):
"""Test destroy CPVM
"""
@@ -1102,7 +1217,7 @@ class TestSSVMs(cloudstackTestCase):
"basic",
"sg"],
required_hardware="true")
- def test_11_ss_nfs_version_on_ssvm(self):
+ def test_13_ss_nfs_version_on_ssvm(self):
"""Test NFS Version on Secondary Storage mounted properly on SSVM
"""
diff --git a/test/integration/smoke/test_vm_life_cycle.py
b/test/integration/smoke/test_vm_life_cycle.py
index 08668e4..a64293b 100644
--- a/test/integration/smoke/test_vm_life_cycle.py
+++ b/test/integration/smoke/test_vm_life_cycle.py
@@ -500,6 +500,40 @@ class TestVMLifeCycle(cloudstackTestCase):
return
@attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"],
required_hardware="false")
+ def test_04_reboot_vm_forced(self):
+ """Test Force Reboot Virtual Machine
+ """
+
+ try:
+ self.debug("Force rebooting VM - ID: %s" % self.virtual_machine.id)
+ self.small_virtual_machine.reboot(self.apiclient, forced=True)
+ except Exception as e:
+ self.fail("Failed to force reboot VM: %s" % e)
+
+ list_vm_response = VirtualMachine.list(
+ self.apiclient,
+ id=self.small_virtual_machine.id
+ )
+ self.assertEqual(
+ isinstance(list_vm_response, list),
+ True,
+ "Check list response returns a valid list"
+ )
+
+ self.assertNotEqual(
+ len(list_vm_response),
+ 0,
+ "Check VM available in List Virtual Machines"
+ )
+
+ self.assertEqual(
+ list_vm_response[0].state,
+ "Running",
+ "Check virtual machine is in running state"
+ )
+ return
+
+ @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"],
required_hardware="false")
def test_06_destroy_vm(self):
"""Test destroy Virtual Machine
"""
diff --git a/tools/marvin/marvin/lib/base.py b/tools/marvin/marvin/lib/base.py
index 20e116a..a05f18b 100755
--- a/tools/marvin/marvin/lib/base.py
+++ b/tools/marvin/marvin/lib/base.py
@@ -723,10 +723,12 @@ class VirtualMachine:
raise Exception(response[1])
return
- def reboot(self, apiclient):
+ def reboot(self, apiclient, forced=None):
"""Reboot the instance"""
cmd = rebootVirtualMachine.rebootVirtualMachineCmd()
cmd.id = self.id
+ if forced:
+ cmd.forced = forced
apiclient.rebootVirtualMachine(cmd)
response = self.getState(apiclient, VirtualMachine.RUNNING)
@@ -4448,10 +4450,12 @@ class Router:
return apiclient.stopRouter(cmd)
@classmethod
- def reboot(cls, apiclient, id):
+ def reboot(cls, apiclient, id, forced=None):
"""Reboots the router"""
cmd = rebootRouter.rebootRouterCmd()
cmd.id = id
+ if forced:
+ cmd.forced = forced
return apiclient.rebootRouter(cmd)
@classmethod
diff --git a/ui/src/config/section/compute.js b/ui/src/config/section/compute.js
index 6acebf6..c3d2623 100644
--- a/ui/src/config/section/compute.js
+++ b/ui/src/config/section/compute.js
@@ -125,6 +125,7 @@ export default {
show: (record) => { return ['Running'].includes(record.state) },
args: (record, store) => {
var fields = []
+ fields.push('forced')
if (record.hypervisor === 'VMware') {
if (store.apis.rebootVirtualMachine.params.filter(x => x.name
=== 'bootintosetup').length > 0) {
fields.push('bootintosetup')
diff --git a/ui/src/config/section/infra/routers.js
b/ui/src/config/section/infra/routers.js
index 6ffa468..a338237 100644
--- a/ui/src/config/section/infra/routers.js
+++ b/ui/src/config/section/infra/routers.js
@@ -66,6 +66,7 @@ export default {
label: 'label.action.reboot.router',
message: 'message.action.reboot.router',
dataView: true,
+ args: ['forced'],
hidden: (record) => { return record.state === 'Running' }
},
{
diff --git a/ui/src/config/section/infra/systemVms.js
b/ui/src/config/section/infra/systemVms.js
index bc20b90..5c02734 100644
--- a/ui/src/config/section/infra/systemVms.js
+++ b/ui/src/config/section/infra/systemVms.js
@@ -47,7 +47,8 @@ export default {
label: 'label.action.reboot.systemvm',
message: 'message.action.reboot.systemvm',
dataView: true,
- show: (record) => { return record.state === 'Running' }
+ show: (record) => { return record.state === 'Running' },
+ args: ['forced']
},
{
api: 'scaleSystemVm',