Bash script: Code To Attach USB by ID to VM in Qubes 4.0

I need a script solution that will consistently attach a USB to a qube & mount it.

@ jevank gave a solution that uses product ID, here: How To Attach A USB To VM Via the USB Name? - #3 by Emily

The solution works in 4.1.

Well several days trying everything, I just can’t get a solution to work in 4.0.

Do you have some working code for this?

I’ve never tried it on 4.0 (and you have probably switched away from it at this point), but I wrote a shitty bash function that needs id+name combination used in modern qubes as input (instead of just id) for this purpose:

usb-attach(){ # Attach multiple devices to a domain by name
# Use it like this:
# usb-attach <domain> <list_of_usb_device_names>
    if [ -z "$1" ]; then
        echo "Error: No target domain"
        return 1
    elif [ -z "$2" ]; then
        echo "Error: No devices to attach"
        return 1
    fi
    read -ra devices_target <<< "$2"
    readarray -t devices_all <<< $(qvm-device usb list | cat)
    echo "Attaching devices:"
    for device in "${devices_all[@]}"; do
        read -ra device_entry <<< "${device[@]}"
        for device_name in "${devices_target[@]}"; do
            if [ ${device_entry[1]} = $device_name ]; then
	            qvm-device usb attach "$1" ${device_entry[0]}
                echo ${device_entry[0]}
            fi
        done
    done
    unset \
        devices_target \
        devices_all \
        device \
        device_name \
        device_entry
}

I think it begs for improvement, especially the input parsing “solution”, so contributions are welcome.

How it works:

  1. Checks if inputs are present with this:

       if [ -z "$1" ]; then
           echo "Error: No target domain"
           return 1
       elif [ -z "$2" ]; then
           echo "Error: No devices to attach"
           return 1
       fi
    
  2. Splits the second input into array devices_target (spaces are delimiters):

    read -ra devices_target <<< "$2"

  3. Splits whatever qvm-device usb list | cat spits out into array of strings devices_all (newlines are delimiters):

    readarray -t devices_all <<< $(qvm-device usb list | cat)

    Pipe to cat is used to get rid of headings in the qvm-device’s output

  4. Checks each present devices’ name (device_entry[1]) against all given target names (device_name); if true, attaches the device:

       for device in "${devices_all[@]}"; do
           read -ra device_entry <<< "${device[@]}"
           for device_name in "${devices_target[@]}"; do
               if [ ${device_entry[1]} = $device_name ]; then
    	            qvm-device usb attach "$1" ${device_entry[0]}
                    echo ${device_entry[0]}
               fi
           done
       done
    
  5. Cleans up after itself because I don’t really know how to apply local

1 Like