From 5f193a6134a10bf6ce5fd312f172f82fc6baf6c1 Mon Sep 17 00:00:00 2001 From: "Joshua M. Boniface" Date: Sat, 6 Nov 2021 03:53:44 -0400 Subject: [PATCH] Perform automatic shutdown/stop on VM disable Instead of requiring the VM to already be stopped, instead allow disable state changes to perform a shutdown first. Also add a force option which will do a hard stop instead of a shutdown. References #148 --- api-daemon/pvcapid/flaskapi.py | 8 +++++++- api-daemon/pvcapid/helper.py | 10 +++++----- daemon-common/vm.py | 16 ++++++++++++---- docs/manuals/swagger.json | 6 ++++++ 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/api-daemon/pvcapid/flaskapi.py b/api-daemon/pvcapid/flaskapi.py index 67811d64..8ced00de 100755 --- a/api-daemon/pvcapid/flaskapi.py +++ b/api-daemon/pvcapid/flaskapi.py @@ -1868,6 +1868,7 @@ class API_VM_State(Resource): "helptext": "A valid state must be specified", "required": True, }, + {"name": "force"}, {"name": "wait"}, ] ) @@ -1890,6 +1891,10 @@ class API_VM_State(Resource): - stop - restart - disable + - in: query + name: force + type: boolean + description: Whether to force stop instead of shutdown VM during disable - in: query name: wait type: boolean @@ -1907,6 +1912,7 @@ class API_VM_State(Resource): id: Message """ state = reqargs.get("state", None) + force = bool(strtobool(reqargs.get("force", "false"))) wait = bool(strtobool(reqargs.get("wait", "false"))) if state == "start": @@ -1918,7 +1924,7 @@ class API_VM_State(Resource): if state == "restart": return api_helper.vm_restart(vm, wait) if state == "disable": - return api_helper.vm_disable(vm) + return api_helper.vm_disable(vm, force) abort(400) diff --git a/api-daemon/pvcapid/helper.py b/api-daemon/pvcapid/helper.py index 8239a108..79df15c6 100755 --- a/api-daemon/pvcapid/helper.py +++ b/api-daemon/pvcapid/helper.py @@ -719,11 +719,11 @@ def vm_start(zkhandler, name): @ZKConnection(config) -def vm_restart(zkhandler, name, wait): +def vm_restart(zkhandler, name, wait=False): """ Restart a VM in the PVC cluster. """ - retflag, retdata = pvc_vm.restart_vm(zkhandler, name, wait) + retflag, retdata = pvc_vm.restart_vm(zkhandler, name, wait=wait) if retflag: retcode = 200 @@ -767,11 +767,11 @@ def vm_stop(zkhandler, name): @ZKConnection(config) -def vm_disable(zkhandler, name): +def vm_disable(zkhandler, name, force=False): """ - Disable a (stopped) VM in the PVC cluster. + Disable (shutdown or force stop if required)a VM in the PVC cluster. """ - retflag, retdata = pvc_vm.disable_vm(zkhandler, name) + retflag, retdata = pvc_vm.disable_vm(zkhandler, name, force=force) if retflag: retcode = 200 diff --git a/daemon-common/vm.py b/daemon-common/vm.py index 1ef27c98..6e1d66cc 100644 --- a/daemon-common/vm.py +++ b/daemon-common/vm.py @@ -837,21 +837,29 @@ def stop_vm(zkhandler, domain): return True, 'Forcibly stopping VM "{}".'.format(domain) -def disable_vm(zkhandler, domain): +def disable_vm(zkhandler, domain, force=False): # Validate that VM exists in cluster dom_uuid = getDomainUUID(zkhandler, domain) if not dom_uuid: return False, 'ERROR: Could not find VM "{}" in the cluster!'.format(domain) - # Get state and verify we're OK to proceed + # Get state and perform a shutdown/stop if VM is online current_state = zkhandler.read(("domain.state", dom_uuid)) if current_state != "stop": - return False, 'ERROR: VM "{}" must be stopped before disabling!'.format(domain) + if force: + change_state(zkhandler, dom_uuid, "stop") + # Wait for the command to be registered by the node + time.sleep(0.5) + else: + change_state(zkhandler, dom_uuid, "shutdown") + # Wait for the shutdown to complete + while zkhandler.read(("domain.state", dom_uuid)) != "stop": + time.sleep(0.5) # Set the VM to disable change_state(zkhandler, dom_uuid, "disable") - return True, 'Marked VM "{}" as disable.'.format(domain) + return True, 'Disabled VM "{}".'.format(domain) def update_vm_sriov_nics(zkhandler, dom_uuid, source_node, target_node): diff --git a/docs/manuals/swagger.json b/docs/manuals/swagger.json index 9cc23b24..cc6320f5 100644 --- a/docs/manuals/swagger.json +++ b/docs/manuals/swagger.json @@ -6680,6 +6680,12 @@ "required": true, "type": "string" }, + { + "description": "Whether to force stop instead of shutdown VM during disable", + "in": "query", + "name": "force", + "type": "boolean" + }, { "description": "Whether to block waiting for the state change to complete", "in": "query",