server: Global setting to allow/disallow users to force stop a vm (#9569)

Global setting to allow/disallow users to force stop a vm

Fixes #6629

Co-authored-by: Suresh Kumar Anaparti <sureshkumar.anaparti@gmail.com>
Co-authored-by: Rohit Yadav <rohityadav89@gmail.com>
Co-authored-by: Bernardo De Marco Gonçalves <bernardomg2004@gmail.com>
This commit is contained in:
Abhisar Sinha 2024-09-05 09:46:45 +05:30 committed by GitHub
parent 36d37f70a8
commit b7a2b0419c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 31 additions and 2 deletions

View File

@ -30,6 +30,7 @@ public class ApiConstants {
public static final String ALGORITHM = "algorithm";
public static final String ALIAS = "alias";
public static final String ALLOCATED_ONLY = "allocatedonly";
public static final String ALLOW_USER_FORCE_STOP_VM = "allowuserforcestopvm";
public static final String ANNOTATION = "annotation";
public static final String API_KEY = "apikey";
public static final String ARCHIVED = "archived";

View File

@ -55,6 +55,7 @@ public class ListCapabilitiesCmd extends BaseCmd {
response.setAllowUserExpungeRecoverVM((Boolean)capabilities.get("allowUserExpungeRecoverVM"));
response.setAllowUserExpungeRecoverVolume((Boolean)capabilities.get("allowUserExpungeRecoverVolume"));
response.setAllowUserViewAllDomainAccounts((Boolean)capabilities.get("allowUserViewAllDomainAccounts"));
response.setAllowUserForceStopVM((Boolean)capabilities.get(ApiConstants.ALLOW_USER_FORCE_STOP_VM));
response.setKubernetesServiceEnabled((Boolean)capabilities.get("kubernetesServiceEnabled"));
response.setKubernetesClusterExperimentalFeaturesEnabled((Boolean)capabilities.get("kubernetesClusterExperimentalFeaturesEnabled"));
response.setCustomHypervisorDisplayName((String) capabilities.get("customHypervisorDisplayName"));

View File

@ -92,6 +92,10 @@ public class CapabilitiesResponse extends BaseResponse {
@Param(description = "true if users can see all accounts within the same domain, false otherwise")
private boolean allowUserViewAllDomainAccounts;
@SerializedName(ApiConstants.ALLOW_USER_FORCE_STOP_VM)
@Param(description = "true if users are allowed to force stop a vm, false otherwise", since = "4.20.0")
private boolean allowUserForceStopVM;
@SerializedName("kubernetesserviceenabled")
@Param(description = "true if Kubernetes Service plugin is enabled, false otherwise")
private boolean kubernetesServiceEnabled;
@ -192,6 +196,10 @@ public class CapabilitiesResponse extends BaseResponse {
this.allowUserViewAllDomainAccounts = allowUserViewAllDomainAccounts;
}
public void setAllowUserForceStopVM(boolean allowUserForceStopVM) {
this.allowUserForceStopVM = allowUserForceStopVM;
}
public void setKubernetesServiceEnabled(boolean kubernetesServiceEnabled) {
this.kubernetesServiceEnabled = kubernetesServiceEnabled;
}

View File

@ -4461,6 +4461,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
final boolean allowUserViewDestroyedVM = (QueryService.AllowUserViewDestroyedVM.valueIn(caller.getId()) | _accountService.isAdmin(caller.getId()));
final boolean allowUserExpungeRecoverVM = (UserVmManager.AllowUserExpungeRecoverVm.valueIn(caller.getId()) | _accountService.isAdmin(caller.getId()));
final boolean allowUserExpungeRecoverVolume = (VolumeApiServiceImpl.AllowUserExpungeRecoverVolume.valueIn(caller.getId()) | _accountService.isAdmin(caller.getId()));
final boolean allowUserForceStopVM = (UserVmManager.AllowUserForceStopVm.valueIn(caller.getId()) | _accountService.isAdmin(caller.getId()));
final boolean allowUserViewAllDomainAccounts = (QueryService.AllowUserViewAllDomainAccounts.valueIn(caller.getDomainId()));
@ -4488,6 +4489,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
capabilities.put("allowUserExpungeRecoverVM", allowUserExpungeRecoverVM);
capabilities.put("allowUserExpungeRecoverVolume", allowUserExpungeRecoverVolume);
capabilities.put("allowUserViewAllDomainAccounts", allowUserViewAllDomainAccounts);
capabilities.put(ApiConstants.ALLOW_USER_FORCE_STOP_VM, allowUserForceStopVM);
capabilities.put("kubernetesServiceEnabled", kubernetesServiceEnabled);
capabilities.put("kubernetesClusterExperimentalFeaturesEnabled", kubernetesClusterExperimentalFeaturesEnabled);
capabilities.put("customHypervisorDisplayName", HypervisorGuru.HypervisorCustomDisplayName.value());

View File

@ -51,12 +51,15 @@ public interface UserVmManager extends UserVmService {
String EnableDynamicallyScaleVmCK = "enable.dynamic.scale.vm";
String AllowDiskOfferingChangeDuringScaleVmCK = "allow.diskoffering.change.during.scale.vm";
String AllowUserExpungeRecoverVmCK ="allow.user.expunge.recover.vm";
String AllowUserForceStopVmCK = "allow.user.force.stop.vm";
ConfigKey<Boolean> EnableDynamicallyScaleVm = new ConfigKey<Boolean>("Advanced", Boolean.class, EnableDynamicallyScaleVmCK, "false",
"Enables/Disables dynamically scaling a vm", true, ConfigKey.Scope.Zone);
ConfigKey<Boolean> AllowDiskOfferingChangeDuringScaleVm = new ConfigKey<Boolean>("Advanced", Boolean.class, AllowDiskOfferingChangeDuringScaleVmCK, "false",
"Determines whether to allow or disallow disk offering change for root volume during scaling of a stopped or running vm", true, ConfigKey.Scope.Zone);
ConfigKey<Boolean> AllowUserExpungeRecoverVm = new ConfigKey<Boolean>("Advanced", Boolean.class, AllowUserExpungeRecoverVmCK, "false",
"Determines whether users can expunge or recover their vm", true, ConfigKey.Scope.Account);
ConfigKey<Boolean> AllowUserForceStopVm = new ConfigKey<Boolean>("Advanced", Boolean.class, AllowUserForceStopVmCK, "true",
"Determines whether users are allowed to force stop a vm", true, ConfigKey.Scope.Account);
ConfigKey<Boolean> DisplayVMOVFProperties = new ConfigKey<Boolean>("Advanced", Boolean.class, "vm.display.ovf.properties", "false",
"Set display of VMs OVF properties as part of VM details", true);

View File

@ -5348,6 +5348,13 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
public void finalizeExpunge(VirtualMachine vm) {
}
private void checkForceStopVmPermission(Account callingAccount) {
if (!AllowUserForceStopVm.valueIn(callingAccount.getId())) {
logger.error("Parameter [{}] can only be passed by Admin accounts or when the allow.user.force.stop.vm config is true for the account.", ApiConstants.FORCED);
throw new PermissionDeniedException("Account does not have the permission to force stop the vm.");
}
}
@Override
@ActionEvent(eventType = EventTypes.EVENT_VM_STOP, eventDescription = "stopping Vm", async = true)
public UserVm stopVirtualMachine(long vmId, boolean forced) throws ConcurrentOperationException {
@ -5365,6 +5372,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId);
}
if (forced) {
checkForceStopVmPermission(caller);
}
// check if vm belongs to AutoScale vm group in Disabled state
autoScaleManager.checkIfVmActionAllowed(vmId);
@ -8467,7 +8478,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
return new ConfigKey<?>[] {EnableDynamicallyScaleVm, AllowDiskOfferingChangeDuringScaleVm, AllowUserExpungeRecoverVm, VmIpFetchWaitInterval, VmIpFetchTrialMax,
VmIpFetchThreadPoolMax, VmIpFetchTaskWorkers, AllowDeployVmIfGivenHostFails, EnableAdditionalVmConfig, DisplayVMOVFProperties,
KvmAdditionalConfigAllowList, XenServerAdditionalConfigAllowList, VmwareAdditionalConfigAllowList, DestroyRootVolumeOnVmDestruction,
EnforceStrictResourceLimitHostTagCheck, StrictHostTags};
EnforceStrictResourceLimitHostTagCheck, StrictHostTags, AllowUserForceStopVm};
}
@Override

View File

@ -133,7 +133,10 @@ export default {
dataView: true,
groupAction: true,
groupMap: (selection, values) => { return selection.map(x => { return { id: x, forced: values.forced } }) },
args: ['forced'],
args: (record, store, group) => {
return (['Admin'].includes(store.userInfo.roletype) || store.features.allowuserforcestopvm)
? ['forced'] : []
},
show: (record) => { return ['Running'].includes(record.state) }
},
{