Add VM device hot attach/detach support

Adds a new API endpoint to support hot attach/detach of devices, and the
corresponding client-side logic to use this endpoint when doing VM
network/storage add/remove actions.

The live attach is now the default behaviour for these types of
additions and removals, and can be disabled if needed.

Closes #141
This commit is contained in:
2021-09-12 15:41:05 -04:00
parent 46f1d761f6
commit e962743e51
6 changed files with 500 additions and 83 deletions

View File

@ -2003,6 +2003,72 @@ class API_VM_Rename(Resource):
api.add_resource(API_VM_Rename, '/vm/<vm>/rename')
# /vm/<vm>/device
class API_VM_Device(Resource):
@RequestParser([
{'name': 'xml', 'required': True, 'helptext': "A Libvirt XML device document must be specified"},
])
@Authenticator
def post(self, vm, reqargs):
"""
Hot-attach device XML to {vm}
---
tags:
- vm
parameters:
- in: query
name: xml
type: string
required: true
description: The raw Libvirt XML definition of the device to attach
responses:
200:
description: OK
schema:
type: object
id: Message
400:
description: Bad request
schema:
type: object
id: Message
"""
return api_helper.vm_attach_device(vm, reqargs.get('xml', None))
@RequestParser([
{'name': 'xml', 'required': True, 'helptext': "A Libvirt XML device document must be specified"},
])
@Authenticator
def delete(self, vm, reqargs):
"""
Hot-detach device XML to {vm}
---
tags:
- vm
parameters:
- in: query
name: xml
type: string
required: true
description: The raw Libvirt XML definition of the device to detach
responses:
200:
description: OK
schema:
type: object
id: Message
400:
description: Bad request
schema:
type: object
id: Message
"""
return api_helper.vm_detach_device(vm, reqargs.get('xml', None))
api.add_resource(API_VM_Device, '/vm/<vm>/device')
##########################################################
# Client API - Network
##########################################################

View File

@ -491,6 +491,58 @@ def vm_define(zkhandler, xml, node, limit, selector, autostart, migration_method
return output, retcode
@ZKConnection(config)
def vm_attach_device(zkhandler, vm, device_spec_xml):
"""
Hot-attach a device (via XML spec) to a VM.
"""
try:
_ = etree.fromstring(device_spec_xml)
except Exception as e:
return {'message': 'XML is malformed or incorrect: {}'.format(e)}, 400
retflag, retdata = pvc_vm.attach_vm_device(zkhandler, vm, device_spec_xml)
if retflag:
retcode = 200
output = {
'message': retdata.replace('\"', '\'')
}
else:
retcode = 400
output = {
'message': 'WARNING: Failed to perform hot attach; device will be added on next VM start/restart.'
}
return output, retcode
@ZKConnection(config)
def vm_detach_device(zkhandler, vm, device_spec_xml):
"""
Hot-detach a device (via XML spec) from a VM.
"""
try:
_ = etree.fromstring(device_spec_xml)
except Exception as e:
return {'message': 'XML is malformed or incorrect: {}'.format(e)}, 400
retflag, retdata = pvc_vm.detach_vm_device(zkhandler, vm, device_spec_xml)
if retflag:
retcode = 200
output = {
'message': retdata.replace('\"', '\'')
}
else:
retcode = 400
output = {
'message': 'WARNING: Failed to perform hot detach; device will be removed on next VM start/restart.'
}
return output, retcode
@pvc_common.Profiler(config)
@ZKConnection(config)
def get_vm_meta(zkhandler, vm):