qvm-usb: always pass VM as object reference not a name

Make the API consistent.

QubesOS/qubes-issues#531
This commit is contained in:
Marek Marczykowski-Górecki 2016-06-02 02:44:38 +02:00
parent d67636308f
commit 52fb410deb
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
2 changed files with 33 additions and 25 deletions

View File

@ -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) """
return device.replace('.', '_')
def usb_list_vm(vm):
def usb_list_vm(qvmc, vm):
if not vm.is_running():
return {}
@ -512,7 +512,12 @@ def usb_list_vm(vm):
"Invalid %s device 'connected-to' in VM '%s'" % (
dev_name, vm.name)
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:
connected_to = None
@ -531,7 +536,7 @@ def usb_list_vm(vm):
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).
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:
vm_list = [vm]
else:
if qvmc is None:
raise QubesException("You must pass either qvm or vm argument")
vm_list = qvmc.values()
devices_list = {}
for vm in vm_list:
devices_list.update(usb_list_vm(vm))
devices_list.update(usb_list_vm(qvmc, vm))
return devices_list
def usb_check_attached(device):
def usb_check_attached(qvmc, device):
"""Reread device attachment status"""
vm = device['vm']
untrusted_connected_to = vm.qdb.read(
@ -565,22 +568,27 @@ def usb_check_attached(device):
raise QubesException(
"Invalid %s device 'connected-to' in VM '%s'" % (
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:
connected_to = None
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():
raise QubesException("VM {} not running".format(vm.name))
if not device['vm'].is_running():
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 auto_detach:
usb_detach(device)
usb_detach(qvmc, device)
else:
raise QubesException("Device {} already connected, to {}".format(
device['name'], connected_to
@ -629,12 +637,13 @@ def usb_attach(vm, device, auto_detach=False, wait=True):
f.seek(0)
f.write(''.join(policy))
def usb_detach(vm, device):
connected_to = usb_check_attached(device)
def usb_detach(qvmc, vm, device):
connected_to = usb_check_attached(qvmc, device)
# 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(
"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')
(stdout, stderr) = p.communicate(

View File

@ -97,7 +97,7 @@ def main():
backend_vm = qvm_collection.get_vm_by_name(args[1].split(":")[0])
if backend_vm is None:
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():
parser.error("Invalid device name: %s" % args[1])
dev = dev_list[args[1]]
@ -108,7 +108,7 @@ def main():
# kwargs['frontend'] = options.frontend
kwargs['auto_detach'] = options.auto_detach
try:
usb_attach(vm, dev, **kwargs)
usb_attach(qvm_collection, vm, dev, **kwargs)
except QubesException as e:
print >> sys.stderr, "ERROR: %s" % str(e)
sys.exit(1)
@ -125,7 +125,7 @@ def main():
# kwargs['frontend'] = options.frontend
# usb_detach(vm, **kwargs)
#else:
usb_detach_all(vm)
usb_detach_all(qvm_collection, vm)
else:
# Maybe usbvm:device?
@ -137,25 +137,24 @@ def main():
backend_vm = qvm_collection.get_vm_by_name(args[0].split(":")[0])
if backend_vm is None:
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():
parser.error("Invalid device name: %s" % 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:
print >> sys.stderr, "WARNING: Device not connected to any VM"
exit(0)
vm = qvm_collection.get_vm_by_name(attached_to)
usb_detach(vm, dev)
usb_detach(qvm_collection, attached_to, dev)
else:
if len(args) > 0:
parser.error("Too many parameters")
# do_list
for dev in usb_list(qvmc=qvm_collection).values():
attached_to = usb_check_attached(dev)
for dev in usb_list(qvm_collection).values():
attached_to = dev['connected-to']
attached_to_str = ""
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)
exit (0)