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:
@ -105,14 +105,14 @@ def getDomainName(zkhandler, domain):
|
||||
# Helper functions
|
||||
#
|
||||
def change_state(zkhandler, dom_uuid, new_state):
|
||||
lock = zkhandler.exclusivelock(('domain.state', dom_uuid))
|
||||
with lock:
|
||||
zkhandler.write([
|
||||
(('domain.state', dom_uuid), new_state)
|
||||
])
|
||||
lock = zkhandler.exclusivelock(('domain.state', dom_uuid))
|
||||
with lock:
|
||||
zkhandler.write([
|
||||
(('domain.state', dom_uuid), new_state)
|
||||
])
|
||||
|
||||
# Wait for 1/2 second to allow state to flow to all nodes
|
||||
time.sleep(0.5)
|
||||
# Wait for 1/2 second to allow state to flow to all nodes
|
||||
time.sleep(0.5)
|
||||
|
||||
|
||||
#
|
||||
@ -262,6 +262,94 @@ def define_vm(zkhandler, config_data, target_node, node_limit, node_selector, no
|
||||
return True, 'Added new VM with Name "{}" and UUID "{}" to database.'.format(dom_name, dom_uuid)
|
||||
|
||||
|
||||
def attach_vm_device(zkhandler, domain, device_spec_xml):
|
||||
# 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)
|
||||
|
||||
# Verify that the VM is in a stopped state; freeing locks is not safe otherwise
|
||||
state = zkhandler.read(('domain.state', dom_uuid))
|
||||
if state != 'start':
|
||||
return False, 'ERROR: VM "{}" is not in started state; live-add unneccessary.'.format(domain)
|
||||
|
||||
# Tell the cluster to attach the device
|
||||
attach_device_string = 'attach_device {} {}'.format(dom_uuid, device_spec_xml)
|
||||
zkhandler.write([
|
||||
('base.cmd.domain', attach_device_string)
|
||||
])
|
||||
# Wait 1/2 second for the cluster to get the message and start working
|
||||
time.sleep(0.5)
|
||||
# Acquire a read lock, so we get the return exclusively
|
||||
lock = zkhandler.readlock('base.cmd.domain')
|
||||
with lock:
|
||||
try:
|
||||
result = zkhandler.read('base.cmd.domain').split()[0]
|
||||
if result == 'success-attach_device':
|
||||
message = 'Attached device on VM "{}"'.format(domain)
|
||||
success = True
|
||||
else:
|
||||
message = 'ERROR: Failed to attach device on VM "{}"; check node logs for details.'.format(domain)
|
||||
success = False
|
||||
except Exception:
|
||||
message = 'ERROR: Command ignored by node.'
|
||||
success = False
|
||||
|
||||
# Acquire a write lock to ensure things go smoothly
|
||||
lock = zkhandler.writelock('base.cmd.domain')
|
||||
with lock:
|
||||
time.sleep(0.5)
|
||||
zkhandler.write([
|
||||
('base.cmd.domain', '')
|
||||
])
|
||||
|
||||
return success, message
|
||||
|
||||
|
||||
def detach_vm_device(zkhandler, domain, device_spec_xml):
|
||||
# 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)
|
||||
|
||||
# Verify that the VM is in a stopped state; freeing locks is not safe otherwise
|
||||
state = zkhandler.read(('domain.state', dom_uuid))
|
||||
if state != 'start':
|
||||
return False, 'ERROR: VM "{}" is not in started state; live-add unneccessary.'.format(domain)
|
||||
|
||||
# Tell the cluster to detach the device
|
||||
detach_device_string = 'detach_device {} {}'.format(dom_uuid, device_spec_xml)
|
||||
zkhandler.write([
|
||||
('base.cmd.domain', detach_device_string)
|
||||
])
|
||||
# Wait 1/2 second for the cluster to get the message and start working
|
||||
time.sleep(0.5)
|
||||
# Acquire a read lock, so we get the return exclusively
|
||||
lock = zkhandler.readlock('base.cmd.domain')
|
||||
with lock:
|
||||
try:
|
||||
result = zkhandler.read('base.cmd.domain').split()[0]
|
||||
if result == 'success-detach_device':
|
||||
message = 'Attached device on VM "{}"'.format(domain)
|
||||
success = True
|
||||
else:
|
||||
message = 'ERROR: Failed to detach device on VM "{}"; check node logs for details.'.format(domain)
|
||||
success = False
|
||||
except Exception:
|
||||
message = 'ERROR: Command ignored by node.'
|
||||
success = False
|
||||
|
||||
# Acquire a write lock to ensure things go smoothly
|
||||
lock = zkhandler.writelock('base.cmd.domain')
|
||||
with lock:
|
||||
time.sleep(0.5)
|
||||
zkhandler.write([
|
||||
('base.cmd.domain', '')
|
||||
])
|
||||
|
||||
return success, message
|
||||
|
||||
|
||||
def modify_vm_metadata(zkhandler, domain, node_limit, node_selector, node_autostart, provisioner_profile, migration_method):
|
||||
dom_uuid = getDomainUUID(zkhandler, domain)
|
||||
if not dom_uuid:
|
||||
|
Reference in New Issue
Block a user