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