qvm-usb: always pass VM as object reference not a name
Make the API consistent. QubesOS/qubes-issues#531
This commit is contained in:
parent
d67636308f
commit
52fb410deb
@ -476,7 +476,7 @@ def usb_encode_device_for_qdb(device):
|
|||||||
""" encode actual device name (xenstore doesn't allow dot in key names, so translated it into underscore) """
|
""" encode actual device name (xenstore doesn't allow dot in key names, so translated it into underscore) """
|
||||||
return device.replace('.', '_')
|
return device.replace('.', '_')
|
||||||
|
|
||||||
def usb_list_vm(vm):
|
def usb_list_vm(qvmc, vm):
|
||||||
if not vm.is_running():
|
if not vm.is_running():
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
@ -512,7 +512,12 @@ def usb_list_vm(vm):
|
|||||||
"Invalid %s device 'connected-to' in VM '%s'" % (
|
"Invalid %s device 'connected-to' in VM '%s'" % (
|
||||||
dev_name, vm.name)
|
dev_name, vm.name)
|
||||||
continue
|
continue
|
||||||
connected_to = untrusted_connected_to
|
connected_to = qvmc.get_vm_by_name(untrusted_connected_to)
|
||||||
|
if connected_to is None:
|
||||||
|
print >>sys.stderr, \
|
||||||
|
"Device {} appears to be connected to {}, " \
|
||||||
|
"but such VM doesn't exist".format(
|
||||||
|
dev_name, untrusted_connected_to)
|
||||||
else:
|
else:
|
||||||
connected_to = None
|
connected_to = None
|
||||||
|
|
||||||
@ -531,7 +536,7 @@ def usb_list_vm(vm):
|
|||||||
return devices
|
return devices
|
||||||
|
|
||||||
|
|
||||||
def usb_list(qvmc=None, vm=None):
|
def usb_list(qvmc, vm=None):
|
||||||
"""
|
"""
|
||||||
Returns a dictionary of USB devices (for PVUSB backends running in all VM).
|
Returns a dictionary of USB devices (for PVUSB backends running in all VM).
|
||||||
The dictionary is keyed by 'name' (see below), each element is a dictionary itself:
|
The dictionary is keyed by 'name' (see below), each element is a dictionary itself:
|
||||||
@ -546,16 +551,14 @@ def usb_list(qvmc=None, vm=None):
|
|||||||
else:
|
else:
|
||||||
vm_list = [vm]
|
vm_list = [vm]
|
||||||
else:
|
else:
|
||||||
if qvmc is None:
|
|
||||||
raise QubesException("You must pass either qvm or vm argument")
|
|
||||||
vm_list = qvmc.values()
|
vm_list = qvmc.values()
|
||||||
|
|
||||||
devices_list = {}
|
devices_list = {}
|
||||||
for vm in vm_list:
|
for vm in vm_list:
|
||||||
devices_list.update(usb_list_vm(vm))
|
devices_list.update(usb_list_vm(qvmc, vm))
|
||||||
return devices_list
|
return devices_list
|
||||||
|
|
||||||
def usb_check_attached(device):
|
def usb_check_attached(qvmc, device):
|
||||||
"""Reread device attachment status"""
|
"""Reread device attachment status"""
|
||||||
vm = device['vm']
|
vm = device['vm']
|
||||||
untrusted_connected_to = vm.qdb.read(
|
untrusted_connected_to = vm.qdb.read(
|
||||||
@ -565,22 +568,27 @@ def usb_check_attached(device):
|
|||||||
raise QubesException(
|
raise QubesException(
|
||||||
"Invalid %s device 'connected-to' in VM '%s'" % (
|
"Invalid %s device 'connected-to' in VM '%s'" % (
|
||||||
device['device'], vm.name))
|
device['device'], vm.name))
|
||||||
connected_to = untrusted_connected_to
|
connected_to = qvmc.get_vm_by_name(untrusted_connected_to)
|
||||||
|
if connected_to is None:
|
||||||
|
print >>sys.stderr, \
|
||||||
|
"Device {} appears to be connected to {}, " \
|
||||||
|
"but such VM doesn't exist".format(
|
||||||
|
device['device'], untrusted_connected_to)
|
||||||
else:
|
else:
|
||||||
connected_to = None
|
connected_to = None
|
||||||
return connected_to
|
return connected_to
|
||||||
|
|
||||||
def usb_attach(vm, device, auto_detach=False, wait=True):
|
def usb_attach(qvmc, vm, device, auto_detach=False, wait=True):
|
||||||
if not vm.is_running():
|
if not vm.is_running():
|
||||||
raise QubesException("VM {} not running".format(vm.name))
|
raise QubesException("VM {} not running".format(vm.name))
|
||||||
|
|
||||||
if not device['vm'].is_running():
|
if not device['vm'].is_running():
|
||||||
raise QubesException("VM {} not running".format(device['vm'].name))
|
raise QubesException("VM {} not running".format(device['vm'].name))
|
||||||
|
|
||||||
connected_to = usb_check_attached(device)
|
connected_to = usb_check_attached(qvmc, device)
|
||||||
if connected_to:
|
if connected_to:
|
||||||
if auto_detach:
|
if auto_detach:
|
||||||
usb_detach(device)
|
usb_detach(qvmc, device)
|
||||||
else:
|
else:
|
||||||
raise QubesException("Device {} already connected, to {}".format(
|
raise QubesException("Device {} already connected, to {}".format(
|
||||||
device['name'], connected_to
|
device['name'], connected_to
|
||||||
@ -629,12 +637,13 @@ def usb_attach(vm, device, auto_detach=False, wait=True):
|
|||||||
f.seek(0)
|
f.seek(0)
|
||||||
f.write(''.join(policy))
|
f.write(''.join(policy))
|
||||||
|
|
||||||
def usb_detach(vm, device):
|
def usb_detach(qvmc, vm, device):
|
||||||
connected_to = usb_check_attached(device)
|
connected_to = usb_check_attached(qvmc, device)
|
||||||
# detect race conditions; there is still race here, but much smaller
|
# detect race conditions; there is still race here, but much smaller
|
||||||
if vm.name != connected_to:
|
if connected_to is None or connected_to.qid != vm.qid:
|
||||||
raise QubesException(
|
raise QubesException(
|
||||||
"Device {} not connected to VM {}".format(device['name'], vm.name))
|
"Device {} not connected to VM {}".format(
|
||||||
|
device['name'], vm.name))
|
||||||
|
|
||||||
p = vm.run_service('qubes.USBDetach', passio_popen=True, user='root')
|
p = vm.run_service('qubes.USBDetach', passio_popen=True, user='root')
|
||||||
(stdout, stderr) = p.communicate(
|
(stdout, stderr) = p.communicate(
|
||||||
|
@ -97,7 +97,7 @@ def main():
|
|||||||
backend_vm = qvm_collection.get_vm_by_name(args[1].split(":")[0])
|
backend_vm = qvm_collection.get_vm_by_name(args[1].split(":")[0])
|
||||||
if backend_vm is None:
|
if backend_vm is None:
|
||||||
parser.error("No such VM: {}".format(args[1].split(":")[0]))
|
parser.error("No such VM: {}".format(args[1].split(":")[0]))
|
||||||
dev_list = usb_list(vm=backend_vm)
|
dev_list = usb_list(qvm_collection, vm=backend_vm)
|
||||||
if not args[1] in dev_list.keys():
|
if not args[1] in dev_list.keys():
|
||||||
parser.error("Invalid device name: %s" % args[1])
|
parser.error("Invalid device name: %s" % args[1])
|
||||||
dev = dev_list[args[1]]
|
dev = dev_list[args[1]]
|
||||||
@ -108,7 +108,7 @@ def main():
|
|||||||
# kwargs['frontend'] = options.frontend
|
# kwargs['frontend'] = options.frontend
|
||||||
kwargs['auto_detach'] = options.auto_detach
|
kwargs['auto_detach'] = options.auto_detach
|
||||||
try:
|
try:
|
||||||
usb_attach(vm, dev, **kwargs)
|
usb_attach(qvm_collection, vm, dev, **kwargs)
|
||||||
except QubesException as e:
|
except QubesException as e:
|
||||||
print >> sys.stderr, "ERROR: %s" % str(e)
|
print >> sys.stderr, "ERROR: %s" % str(e)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@ -125,7 +125,7 @@ def main():
|
|||||||
# kwargs['frontend'] = options.frontend
|
# kwargs['frontend'] = options.frontend
|
||||||
# usb_detach(vm, **kwargs)
|
# usb_detach(vm, **kwargs)
|
||||||
#else:
|
#else:
|
||||||
usb_detach_all(vm)
|
usb_detach_all(qvm_collection, vm)
|
||||||
else:
|
else:
|
||||||
# Maybe usbvm:device?
|
# Maybe usbvm:device?
|
||||||
|
|
||||||
@ -137,25 +137,24 @@ def main():
|
|||||||
backend_vm = qvm_collection.get_vm_by_name(args[0].split(":")[0])
|
backend_vm = qvm_collection.get_vm_by_name(args[0].split(":")[0])
|
||||||
if backend_vm is None:
|
if backend_vm is None:
|
||||||
parser.error("No such VM: {}".format(args[0].split(":")[0]))
|
parser.error("No such VM: {}".format(args[0].split(":")[0]))
|
||||||
dev_list = usb_list(vm=backend_vm)
|
dev_list = usb_list(qvm_collection, vm=backend_vm)
|
||||||
if not args[0] in dev_list.keys():
|
if not args[0] in dev_list.keys():
|
||||||
parser.error("Invalid device name: %s" % args[0])
|
parser.error("Invalid device name: %s" % args[0])
|
||||||
dev = dev_list[args[0]]
|
dev = dev_list[args[0]]
|
||||||
attached_to = usb_check_attached(dev)
|
attached_to = usb_check_attached(qvm_collection, dev)
|
||||||
if attached_to is None:
|
if attached_to is None:
|
||||||
print >> sys.stderr, "WARNING: Device not connected to any VM"
|
print >> sys.stderr, "WARNING: Device not connected to any VM"
|
||||||
exit(0)
|
exit(0)
|
||||||
vm = qvm_collection.get_vm_by_name(attached_to)
|
usb_detach(qvm_collection, attached_to, dev)
|
||||||
usb_detach(vm, dev)
|
|
||||||
else:
|
else:
|
||||||
if len(args) > 0:
|
if len(args) > 0:
|
||||||
parser.error("Too many parameters")
|
parser.error("Too many parameters")
|
||||||
# do_list
|
# do_list
|
||||||
for dev in usb_list(qvmc=qvm_collection).values():
|
for dev in usb_list(qvm_collection).values():
|
||||||
attached_to = usb_check_attached(dev)
|
attached_to = dev['connected-to']
|
||||||
attached_to_str = ""
|
attached_to_str = ""
|
||||||
if attached_to:
|
if attached_to:
|
||||||
attached_to_str = " (attached to %s)" % (attached_to)
|
attached_to_str = " (attached to %s)" % (attached_to.name)
|
||||||
print "%s\t%s%s" % (dev['name'], dev['desc'], attached_to_str)
|
print "%s\t%s%s" % (dev['name'], dev['desc'], attached_to_str)
|
||||||
exit (0)
|
exit (0)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user