PVUSB: xm/xend support

You can see the following slides to understand the usage.
http://www.xen.org/files/xensummit_intel09/PVUSBStatusUpdate.pdf
Limitations:
"xm usb-hc-create" accepts up to 16 ports, but, current usbfront
can work with up to 15 ports. This may be bug and I'm preparing
to fix it.

This xm/xend support requires linux-2.6.18-xen.hg c/s 939 or above.
I recommend latest tip.

Signed-off-by: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
This commit is contained in:
Keir Fraser committed 2009-12-11 08:52:17 +00:00
1 parent 04656384a1
commit fc63162a09
10 files changed
+803 -1

No files matched your search

+338
View File
@@ -0,0 +1,338 @@
#============================================================================
# This library is free software; you can redistribute it and/or
# modify it under the terms of version 2.1 of the GNU Lesser General Public
# License as published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#============================================================================
# Copyright (C) 2009, FUJITSU LABORATORIES LTD.
# Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
#============================================================================
"""Support for VUSB Devices.
"""
import os
import os.path
import sys
import re
import string
from xen.util import utils
SYSFS_USB_DEVS_PATH = '/bus/usb/devices'
SYSFS_USB_DEV_BDEVICECLASS_PATH = '/bDeviceClass'
SYSFS_USB_DEV_BDEVICESUBCLASS_PATH = '/bDeviceSubClass'
SYSFS_USB_DEV_DEVNUM_PATH = '/devnum'
SYSFS_USB_DEV_IDVENDOR_PATH = '/idVendor'
SYSFS_USB_DEV_IDPRODUCT_PATH = '/idProduct'
SYSFS_USB_DEV_MANUFACTURER_PATH = '/manufacturer'
SYSFS_USB_DEV_PRODUCT_PATH = '/product'
SYSFS_USB_DEV_SERIAL_PATH = '/serial'
SYSFS_USB_DEV_DRIVER_PATH = '/driver'
SYSFS_USB_DRIVER_BIND_PATH = '/bind'
SYSFS_USB_DRIVER_UNBIND_PATH = '/unbind'
SYSFS_USBBACK_PATH = '/bus/usb/drivers/usbback'
SYSFS_PORTIDS_PATH = '/port_ids'
USBHUB_CLASS_CODE = '09'
def get_usb_bDeviceClass(dev):
try:
sysfs_mnt = utils.find_sysfs_mount()
sysfs_usb_dev_path = \
os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_BDEVICECLASS_PATH):
usb_deviceclass = \
os.popen('cat ' + sysfs_usb_dev_path + \
SYSFS_USB_DEV_BDEVICECLASS_PATH).readline()
return usb_deviceclass.splitlines()[0]
else:
return ""
except:
return None
def get_usb_bDeviceSubClass(dev):
try:
sysfs_mnt = utils.find_sysfs_mount()
sysfs_usb_dev_path = \
os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_BDEVICESUBCLASS_PATH):
usb_devicesubclass = \
os.popen('cat ' + sysfs_usb_dev_path + \
SYSFS_USB_DEV_BDEVICESUBCLASS_PATH).readline()
return usb_devicesubclass.splitlines()[0]
else:
return ""
except:
return None
def get_usb_devnum(dev):
try:
sysfs_mnt = utils.find_sysfs_mount()
sysfs_usb_dev_path = \
os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_DEVNUM_PATH):
usb_devicesubclass = \
os.popen('cat ' + sysfs_usb_dev_path + \
SYSFS_USB_DEV_DEVNUM_PATH).readline()
return usb_devicesubclass.splitlines()[0]
else:
return ""
except:
return None
def get_usb_idvendor(dev):
try:
sysfs_mnt = utils.find_sysfs_mount()
sysfs_usb_dev_path = \
os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_IDVENDOR_PATH):
usb_idvendor = \
os.popen('cat ' + sysfs_usb_dev_path + \
SYSFS_USB_DEV_IDVENDOR_PATH).readline()
return usb_idvendor.splitlines()[0]
else:
return ""
except:
return None
def get_usb_idproduct(dev):
try:
sysfs_mnt = utils.find_sysfs_mount()
sysfs_usb_dev_path = \
os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_IDPRODUCT_PATH):
usb_idproduct = \
os.popen('cat ' + sysfs_usb_dev_path + \
SYSFS_USB_DEV_IDPRODUCT_PATH).readline()
return usb_idproduct.splitlines()[0]
else:
return ""
except:
return None
def get_usb_manufacturer(dev):
try:
sysfs_mnt = utils.find_sysfs_mount()
sysfs_usb_dev_path = \
os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_MANUFACTURER_PATH):
usb_manufacturer = \
os.popen('cat ' + sysfs_usb_dev_path + \
SYSFS_USB_DEV_MANUFACTURER_PATH).readline()
return usb_manufacturer.splitlines()[0]
else:
return ""
except:
return None
def get_usb_product(dev):
try:
sysfs_mnt = utils.find_sysfs_mount()
sysfs_usb_dev_path = \
os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_PRODUCT_PATH):
usb_product = \
os.popen('cat ' + sysfs_usb_dev_path + \
SYSFS_USB_DEV_PRODUCT_PATH).readline()
return usb_product.splitlines()[0]
else:
return ""
except:
return None
def get_usb_serial(dev):
try:
sysfs_mnt = utils.find_sysfs_mount()
sysfs_usb_dev_path = \
os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_SERIAL_PATH):
usb_serial = \
os.popen('cat ' + sysfs_usb_dev_path + \
SYSFS_USB_DEV_SERIAL_PATH).readline()
return usb_serial.splitlines()[0]
else:
return ""
except:
return None
def get_usbdevice_info_by_lsusb(dev):
try:
vend = get_usb_idvendor(dev)
prod = get_usb_idproduct(dev)
output = os.popen('lsusb -d ' + vend + ':' + prod).readline().split()
text = ""
if len(output) > 6:
for str in output[6:]:
if text != "":
text= text + ' '
text = text + str
return text
else:
return ""
except:
return None
def get_usbdevice_info(dev):
try:
manuf = get_usb_manufacturer(dev)
prod = get_usb_product(dev)
if manuf == "" or prod == "":
return get_usbdevice_info_by_lsusb(dev)
else:
return manuf + ' ' + prod
except:
return None
def usb_device_is_hub(dev):
usb_classcode = get_usb_bDeviceClass(dev)
if (usb_classcode == USBHUB_CLASS_CODE):
return True
else:
return False
def get_all_usb_names():
usb_names = []
try:
sysfs_mnt = utils.find_sysfs_mount()
usb_names = os.popen('ls ' + sysfs_mnt + SYSFS_USB_DEVS_PATH).read().split()
except:
pass
return usb_names
def get_usb_devices():
devs = []
for name in get_all_usb_names():
dev_match = re.match(r"(^(?P<bus>[0-9]{1,2})[-,])" + \
r"(?P<root_port>[0-9]{1,2})" + \
r"(?P<port>([\.,]{1}[0-9]{1,2}){0,5})$", name)
if dev_match is not None:
dev = dev_match.group('bus') + '-' \
+ dev_match.group('root_port') \
+ dev_match.group('port')
if (usb_device_is_hub(dev)):
continue
else:
devs.append(dev)
return devs
def get_usb_intfs(dev):
intfs = []
try:
search = re.compile(r'^' + dev + ':')
except:
raise UsbDeviceParseError("Invalid expression.")
for name in get_all_usb_names():
if search.match(name):
intfs.append(name)
return intfs
def get_assigned_buses():
buses = []
try:
sysfs_mnt = utils.find_sysfs_mount()
if os.path.exists(sysfs_mnt + SYSFS_USBBACK_PATH + SYSFS_PORTIDS_PATH):
portids = \
os.popen('cat ' + sysfs_mnt + SYSFS_USBBACK_PATH + SYSFS_PORTIDS_PATH).read().splitlines()
for portid in portids:
buses.append(portid.split(':')[0])
except:
raise UsbDeviceParseError("Can't get assigned buses from port_ids.")
return buses
def get_assigned_bus(domid, dev, port):
bus = ""
try:
sysfs_mnt = utils.find_sysfs_mount()
if os.path.exists(sysfs_mnt + SYSFS_USBBACK_PATH + SYSFS_PORTIDS_PATH):
portids = \
os.popen('cat ' + sysfs_mnt + SYSFS_USBBACK_PATH + SYSFS_PORTIDS_PATH).read().splitlines()
for portid in portids:
if portid.split(':')[1] == str(domid) and portid.split(':')[2] == str(dev) and portid.split(':')[3] == str(port):
bus = portid.split(':')[0]
except:
raise UsbDeviceParseError("Can't get assigned bus (%d:%d:%d)." % (domid, dev, port))
return bus
def bus_is_assigned(bus):
assigned = False
try:
sysfs_mnt = utils.find_sysfs_mount()
if os.path.exists(sysfs_mnt + SYSFS_USBBACK_PATH + SYSFS_PORTIDS_PATH):
portids = \
os.popen('cat ' + sysfs_mnt + SYSFS_USBBACK_PATH + SYSFS_PORTIDS_PATH).read().splitlines()
for portid in portids:
if portid.split(':')[0] == bus:
assigned = True
except:
raise UsbDeviceParseError("Can't get assignment status: (%s)." % bus)
return assigned
def usb_intf_is_binded(intf):
if os.path.exists(SYSFS_USBBACK_PATH + '/' + intf):
return True
else:
return False
def usb_device_is_connected(dev):
try:
sysfs_mnt = utils.find_sysfs_mount()
sysfs_dev_path = \
os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev)
if os.path.exists(sysfs_dev_path):
return True
else:
return False
except:
raise UsbDeviceParseError("Can't get connection status (%s)." % dev)
def unbind_usb_device(dev):
try:
sysfs_mnt = utils.find_sysfs_mount()
for intf in get_usb_intfs(dev):
sysfs_usb_intf_path = \
os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, intf)
if os.path.exists(sysfs_usb_intf_path + SYSFS_USB_DEV_DRIVER_PATH):
fd = os.open(sysfs_usb_intf_path + \
SYSFS_USB_DEV_DRIVER_PATH + \
SYSFS_USB_DRIVER_UNBIND_PATH, os.O_WRONLY)
os.write(fd, intf)
os.close(fd)
except:
raise UsbDeviceBindingError("can't unbind intf (%s). " % intf)
def bind_usb_device(dev):
try:
sysfs_mnt = utils.find_sysfs_mount()
for intf in get_usb_intfs(dev):
sysfs_usb_intf_path = \
os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, intf)
if os.path.exists(sysfs_usb_intf_path + SYSFS_USB_DEV_DRIVER_PATH):
unbind_usb_device(dev)
fd = os.open(sysfs_mnt + SYSFS_USBBACK_PATH + \
SYSFS_USB_DRIVER_BIND_PATH, os.O_WRONLY)
os.write(fd, intf)
os.close(fd)
except:
raise UsbDeviceBindingError("can't bind intf (%s). " % intf)
class UsbDeviceParseError(Exception):
def __init__(self,msg):
self.message = msg
def __str__(self):
return 'vusb: Error parsing USB device info: '+self.message
class UsbDeviceBindingError(Exception):
def __init__(self,msg):
self.message = msg
def __str__(self):
return 'vusb: Failed to bind/unbind USB device: ' + \
self.message
+82
View File
@@ -1400,6 +1400,14 @@ class XendConfig(dict):
(vscsi_devs, vscsi_mode))
return vscsi_devs_uuid
if dev_type == 'vusb':
vusb_devs_uuid = sxp.child_value(config, 'uuid',
uuid.createString())
vusb_dict = self.vusb_convert_sxp_to_dict(config)
vusb_dict['uuid'] = vusb_devs_uuid
target['devices'][vusb_devs_uuid] = (dev_type, vusb_dict)
return vusb_devs_uuid
for opt_val in config[1:]:
try:
opt, val = opt_val
@@ -1776,6 +1784,68 @@ class XendConfig(dict):
return dev_config
def vusb_convert_sxp_to_dict(self, dev_sxp):
"""Convert vusb device sxp to dict
@param dev_sxp: device configuration
@type dev_sxp: SXP object (parsed config)
@return: dev_config
@rtype: dictionary
"""
# Parsing USB devices SXP.
#
# USB device's SXP looks like this:
#
# [device,
# [vusb,
# [usb-ver, 2],
# [num-ports, 8],
# [port,
# [1, 1-1],
# [2, 1-2],
# [3, ''],
# [4, ''],
# [5, ''],
# [6, ''],
# [7, 6-2.1],
# [8, '']
# ]
# ],
# [vusb,
# [usb-ver, 1],
# [num-ports, 2],
# [port,
# [1, 4-1],
# [2, 4-2]
# ]
# ]
# ]
#
# The dict looks like this
#
# { usb-ver: 2,
# num-ports: 8,
# port-1: 1-1,
# port-2: 1-2,
# port-3: "",
# port-4: "",
# port-5: "",
# port-6: "",
# port-7: "",
# port-8: "" }
dev_config = {}
dev_config['usb-ver'] = sxp.child(dev_sxp, 'usb-ver')[1]
dev_config['num-ports'] = sxp.child(dev_sxp, 'num-ports')[1]
ports = sxp.child(dev_sxp, 'port')
for port in ports[1:]:
try:
num, bus = port
dev_config['port-%i' % int(num)] = str(bus)
except TypeError:
pass
return dev_config
def console_add(self, protocol, location, other_config = {}):
dev_uuid = uuid.createString()
if protocol == 'vt100':
@@ -2002,6 +2072,18 @@ class XendConfig(dict):
for pci_dev_info in dev_info['devs']:
sxpr.append(dev_dict_to_sxp(pci_dev_info))
sxprs.append((dev_type, sxpr))
elif dev_type == 'vusb':
sxpr = ['vusb', ['uuid', dev_info['uuid']],
['usb-ver', dev_info['usb-ver']],
['num-ports', dev_info['num-ports']]]
port_sxpr = ['port']
for i in range(1, int(dev_info['num-ports']) + 1):
if dev_info.has_key('port-%i' % i):
port_sxpr.append([i, str(dev_info['port-%i' % i])])
else:
port_sxpr.append([i, ""])
sxpr.append(port_sxpr)
sxprs.append((dev_type, sxpr))
else:
sxpr = self.device_sxpr(dev_type = dev_type,
dev_info = dev_info,
+2 -1
View File
@@ -19,7 +19,7 @@
# A collection of DevControllers
#
from xen.xend.server import blkif, netif, tpmif, pciif, iopif, irqif, vfbif, vscsiif, netif2
from xen.xend.server import blkif, netif, tpmif, pciif, iopif, irqif, vfbif, vscsiif, netif2, vusbif
from xen.xend.server.BlktapController import BlktapController, Blktap2Controller
from xen.xend.server.ConsoleController import ConsoleController
@@ -48,6 +48,7 @@ class XendDevices:
'vkbd': vfbif.VkbdifController,
'console': ConsoleController,
'vscsi': vscsiif.VSCSIController,
'vusb': vusbif.VUSBController,
}
#@classmethod
+31
View File
@@ -1102,6 +1102,27 @@ class XendDomainInfo:
return True
def vusb_device_configure(self, dev_sxp, devid):
"""Configure a virtual root port.
"""
dev_class = sxp.name(dev_sxp)
if dev_class != 'vusb':
return False
dev_config = {}
ports = sxp.child(dev_sxp, 'port')
for port in ports[1:]:
try:
num, bus = port
dev_config['port-%i' % int(num)] = str(bus)
except TypeError:
pass
dev_control = self.getDeviceController(dev_class)
dev_control.reconfigureDevice(devid, dev_config)
return True
def device_configure(self, dev_sxp, devid = None):
"""Configure an existing device.
@@ -1123,6 +1144,9 @@ class XendDomainInfo:
if dev_class == 'vscsi':
return self.vscsi_device_configure(dev_sxp)
if dev_class == 'vusb':
return self.vusb_device_configure(dev_sxp, devid)
for opt_val in dev_sxp[1:]:
try:
dev_config[opt_val[0]] = opt_val[1]
@@ -1378,6 +1402,13 @@ class XendDomainInfo:
return dev_info
return None
def _getDeviceInfo_vusb(self, devid):
for dev_type, dev_info in self.info.all_devices_sxpr():
if dev_type != 'vusb':
continue
return dev_info
return None
def _get_assigned_pci_devices(self, devid = 0):
if self.domid is not None:
return get_assigned_pci_devices(self.domid)
+15
View File
@@ -24,6 +24,7 @@ import xen.lowlevel.xc
from xen.util import Brctl
from xen.util import pci as PciUtil
from xen.util import vscsi_util
from xen.util import vusb_util
from xen.xend import XendAPIStore
from xen.xend import osdep
from xen.xend.XendConstants import *
@@ -478,6 +479,20 @@ class XendNode:
return
def add_usbdev(self, busid):
# if the adding usb device should be owned by usbback
# and is probed by other usb drivers, seize it!
bus, intf = busid.split(':')
buses = vusb_util.get_assigned_buses()
if str(bus) in buses:
if not vusb_util.usb_intf_is_binded(busid):
log.debug("add_usb(): %s is binded to other driver" % busid)
vusb_util.unbind_usb_device(bus)
vusb_util.bind_usb_device(bus)
return
def remove_usbdev(self, busid):
log.debug("remove_usbdev(): Not implemented.")
## def network_destroy(self, net_uuid):
## del self.networks[net_uuid]
+12
View File
@@ -60,6 +60,18 @@ class UdevEventProtocol(protocol.Protocol):
log.info("Removing scsi device %s", hctl)
XendNode.instance().remove_PSCSI(hctl)
elif (udev_event.get('SUBSYSTEM', None) == 'usb'):
busid = udev_event.get('KERNEL', None)
if busid:
if len(busid.split(':')) != 2:
return
if (udev_event['ACTION'] == 'add'):
log.info("Adding usb device %s", busid)
XendNode.instance().add_usbdev(busid)
elif (udev_event['ACTION'] == 'remove'):
log.info("Removing usb device %s", busid)
XendNode.instance().remove_usbdev(busid)
elif (udev_event.get('SUBSYSTEM', None) == 'net'):
interface = udev_event.get('INTERFACE', None)
if (udev_event['ACTION'] == 'add'):
+126
View File
@@ -0,0 +1,126 @@
#============================================================================
# This library is free software; you can redistribute it and/or
# modify it under the terms of version 2.1 of the GNU Lesser General Public
# License as published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#============================================================================
# Copyright (C) 2009, FUJITSU LABORATORIES LTD.
# Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
#============================================================================
"""Support for virtual USB host controllers.
"""
import re
import string
import types
from xen.xend import sxp
from xen.xend.XendError import VmError
from xen.xend.XendLogging import log
from xen.xend.server.DevController import DevController
from xen.xend.server.DevConstants import xenbusState
from xen.xend.xenstore.xstransact import xstransact
from xen.util import vusb_util
class VUSBController(DevController):
"""VUSB Devices.
"""
def __init__(self, vm):
"""Create a VUSB Devices.
"""
DevController.__init__(self, vm)
def sxprs(self):
"""@see DevController.sxprs"""
devslist = []
for devid in self.deviceIDs():
vusb_config = []
backid = self.readFrontend(devid, 'backend-id')
vusb_config.append(['backend-id', backid])
state = self.readFrontend(devid, 'state')
vusb_config.append(['state', state])
backpath = self.readFrontend(devid, 'backend')
vusb_config.append(['backend', backpath])
usbver = self.readBackend(devid, 'usb-ver')
vusb_config.append(['usb-ver', usbver])
numports = self.readBackend(devid, 'num-ports')
vusb_config.append(['num-ports', numports])
portpath = "port/"
ports = ['port']
for i in range(1, int(numports) + 1):
bus = self.readBackend(devid, portpath + '%i' % i)
ports.append(['%i' % i, str(bus)])
vusb_config.append(ports)
devslist.append([devid, vusb_config])
return devslist
def getDeviceDetails(self, config):
"""@see DevController.getDeviceDetails"""
back = {}
devid = self.allocateDeviceID()
usbver = config.get('usb-ver', '')
numports = config.get('num-ports', '')
back['usb-ver'] = str(usbver)
back['num-ports'] = str(numports)
for i in range(1, int(numports) + 1):
back['port/%i' % i] = config['port-%i' % i]
return (devid, back, {})
def getDeviceConfiguration(self, devid, transaction = None):
"""@see DevController.configuration"""
config = DevController.getDeviceConfiguration(self, devid, transaction)
if transaction is None:
hcinfo = self.readBackend(devid, 'usb-ver', 'num-ports')
else:
hcinfo = self.readBackendTxn(transaction, devid,
'usb-ver', 'num-ports')
(usbver, numports) = hcinfo
config['usb-ver'] = str(usbver)
config['num-ports'] = str(numports)
for i in range(1, int(numports) + 1):
if transaction is None:
config['port-%i' % i] = self.readBackend(devid, 'port/%i' % i)
else:
config['port-%i' % i] = self.readBackendTxn(transaction, devid,
'port/%i' % i)
return config
def reconfigureDevice(self, devid, config):
"""@see DevController.reconfigureDevice"""
cur_config = self.getDeviceConfiguration(devid)
numports = cur_config['num-ports']
for i in range(1, int(numports) + 1):
if config.has_key('port-%i' % i):
if not config['port-%i' % i] == cur_config['port-%i' % i]:
if not cur_config['port-%i' % i] == "":
vusb_util.unbind_usb_device(cur_config['port-%i' % i])
self.writeBackend(devid, 'port/%i' % i,
config['port-%i' % i])
if not config['port-%i' % i] == "":
vusb_util.bind_usb_device(config['port-%i' % i])
return self.readBackend(devid, 'uuid')
def waitForBackend(self, devid):
return (0, "ok - no hotplug")
def waitForBackend_destroy(self, backpath):
return 0
def migrate(self, deviceConfig, network, dst, step, domName):
raise VmError('Migration not permitted with assigned USB device.')
+45
View File
@@ -350,6 +350,18 @@ gopts.var('vscsi', val='PDEV,VDEV[,DOM]',
use="""Add a SCSI device to a domain. The physical device is PDEV,
which is exported to the domain as VDEV(X:X:X:X).""")
gopts.var('vusb', val="usbver=USBVER,numports=NUMPORTS," + \
"port_1=PORT1,port_2=PORT2,port_3=PORT3,port_4=PORT4" + \
"port_5=PORT5,port_6=PORT6,port_7=PORT7,port_8=PORT8" + \
"port_9=PORT9,port_10=PORT10,port_11=PORT11,port_12=PORT12" + \
"port_13=PORT13,port_14=PORT14,port_15=PORT15,port_16=PORT16",
fn=append_value, default=[],
use="""Add a Virtual USB Host Controller to a domain.
The USB Spec Version is usbver (1|2, default: 2).
usbver=1 means USB1.1, usbver=2 mens USB2.0.
The number of root ports is numports (1 to 16, default: 8).
This option may be repeated to add more than one host controller.""")
gopts.var('ioports', val='FROM[-TO]',
fn=append_value, default=[],
use="""Add a legacy I/O range to a domain, using given params (in hex).
@@ -849,6 +861,38 @@ def configure_vscsis(config_devs, vals):
device.append(['backend', config['backend']])
config_devs.append(['device', device])
def configure_vusbs(config_devs, vals):
"""Create the config for virtual usb host controllers.
"""
for f in vals.vusb:
d = comma_sep_kv_to_dict(f)
config = ['vusb']
usbver = 2
if d.has_key('usbver'):
usbver = int(d['usbver'])
if usbver == 1 or usbver == 2:
config.append(['usb-ver', str(usbver)])
else:
err('Invalid vusb option: ' + 'usbver')
numports = 8
if d.has_key('numports'):
numports = d['numports']
if int(numports) < 1 or int(numports) > 16:
err('Invalid vusb option: ' + 'numports')
config.append(['num-ports', str(numports)])
port_config = []
for i in range(1, int(numports) + 1):
if d.has_key('port_%i' % i):
port_config.append(['%i' % i, str(d['port_%i' % i])])
else:
port_config.append(['%i' % i, ""])
port_config.insert(0, 'port')
config.append(port_config)
config_devs.append(['device', config])
def configure_ioports(config_devs, vals):
"""Create the config for legacy i/o ranges.
"""
@@ -1103,6 +1147,7 @@ def make_config(vals):
configure_disks(config_devs, vals)
configure_pci(config_devs, vals)
configure_vscsis(config_devs, vals)
configure_vusbs(config_devs, vals)
configure_ioports(config_devs, vals)
configure_irq(config_devs, vals)
configure_vifs(config_devs, vals)
+151
View File
@@ -39,6 +39,7 @@ import xml.dom.minidom
from xen.util.blkif import blkdev_name_to_number
from xen.util import vscsi_util
from xen.util.pci import *
from xen.util import vusb_util
import warnings
warnings.filterwarnings('ignore', category=FutureWarning)
@@ -211,6 +212,17 @@ SUBCOMMAND_HELP = {
'Detach a specified SCSI device.'),
'scsi-list' : ('<Domain> [--long]',
'List all SCSI devices currently attached.'),
'usb-attach' : ('<Domain> <DevId> <PortNumber> <BusId>',
'Attach a new USB physical bus to domain\'s virtual port.'),
'usb-detach' : ('<Domain> <DevId> <PortNumber>',
'Detach a USB physical bus from domain\'s virtual port.'),
'usb-list' : ('<Domain>',
'List domain\'s attachment state of all virtual port .'),
'usb-list-assignable-devices' : ('', 'List all the assignable usb devices'),
'usb-hc-create' : ('<Domain> <USBSpecVer> <NumberOfPorts>',
'Create a domain\'s new virtual USB host controller.'),
'usb-hc-destroy' : ('<Domain> <DevId>',
'Destroy a domain\'s virtual USB host controller.'),
# tmem
'tmem-list' : ('[-l|--long] [<Domain>|-a|--all]', 'List tmem pools.'),
@@ -429,6 +441,12 @@ device_commands = [
"scsi-attach",
"scsi-detach",
"scsi-list",
"usb-attach",
"usb-detach",
"usb-list",
"usb-list-assignable-devices",
"usb-hc-create",
"usb-hc-destroy",
]
vnet_commands = [
@@ -2409,6 +2427,58 @@ def xm_scsi_list(args):
print "%(idx)-3d %(backend-id)-3d %(state)-5d %(feature-host)-4d " % ni,
print "%(p-dev)-10s %(p-devname)-5s %(v-dev)-10s %(frontstate)-4s" % mi
def xm_usb_list(args):
xenapi_unsupported()
arg_check(args, 'usb-list', 1)
dom = args[0]
devs = server.xend.domain.getDeviceSxprs(dom, 'vusb')
for x in devs:
print "%-3s %-3s %-5s %-7s %-30s" \
% ('Idx', 'BE', 'state', 'usb-ver', 'BE-path')
ni = parse_dev_info(x[1])
ni['idx'] = int(x[0])
usbver = sxp.child_value(x[1], 'usb-ver')
if int(usbver) == 1:
ni['usb-ver'] = 'USB1.1'
else:
ni['usb-ver'] = 'USB2.0'
print "%(idx)-3d %(backend-id)-3d %(state)-5d %(usb-ver)-7s %(be-path)-30s " % ni
ports = sxp.child(x[1], 'port')
for port in ports[1:]:
try:
num, bus = port
if bus != "" and vusb_util.usb_device_is_connected(bus):
idvendor = vusb_util.get_usb_idvendor(bus)
idproduct = vusb_util.get_usb_idproduct(bus)
prodinfo = vusb_util.get_usbdevice_info(bus)
print "port %i: %s [ID %-4s:%-4s %s]" \
% (int(num), str(bus), idvendor, idproduct, prodinfo)
else:
print "port %i: " % int(num) + str(bus)
except TypeError:
pass
def xm_usb_list_assignable_devices(args):
xenapi_unsupported()
arg_check(args, 'usb-list-assignable-devices', 0)
usb_devs = vusb_util.get_usb_devices()
buses = vusb_util.get_assigned_buses()
for x in buses:
try:
usb_devs.remove(x)
except ValueError:
pass
for dev in usb_devs:
idvendor = vusb_util.get_usb_idvendor(dev)
idproduct = vusb_util.get_usb_idproduct(dev)
prodinfo = vusb_util.get_usbdevice_info(dev)
print "%-13s: ID %-4s:%-4s %s" \
% (dev, idvendor, idproduct, prodinfo)
def parse_block_configuration(args):
dom = args[0]
@@ -2757,6 +2827,64 @@ def xm_scsi_attach(args):
scsi.append(['backend', args[3]])
server.xend.domain.device_configure(dom, scsi)
def xm_usb_attach(args):
xenapi_unsupported()
arg_check(args, 'usb-attach', 4)
dom = args[0]
dev = args[1]
port = args[2]
bus = args[3]
dev_exist = 0
num_ports = 0
devs = server.xend.domain.getDeviceSxprs(dom, 'vusb')
for x in devs:
if int(x[0]) == int(dev):
dev_exist = 1
num_ports = sxp.child_value(x[1], 'num-ports')
if dev_exist == 0:
print "Cannot find device '%s' in domain '%s'" % (dev,dom)
return False
if int(port) < 1 or int(port) > int(num_ports):
print "Invalid Port Number '%s'" % port
return False
bus_match = re.match(r"(^(?P<bus>[0-9]{1,2})[-,])" + \
r"(?P<root_port>[0-9]{1,2})" + \
r"(?P<port>([\.,]{1}[0-9]{1,2}){0,5})$", bus)
if bus_match is None:
print "Invalid Busid '%s'" % bus
return False
if vusb_util.bus_is_assigned(bus):
print "Cannot assign already attached bus '%s', detach first." % bus
return False
prev_bus = vusb_util.get_assigned_bus(domain_name_to_domid(dom), dev, port)
if not prev_bus == "":
print "Cannot override already attached port '%s', detach first." % port
return False
usb = ['vusb', ['port', [port, str(bus)]]]
server.xend.domain.device_configure(dom, usb, dev)
def xm_usb_hc_create(args):
xenapi_unsupported()
arg_check(args, 'usb-hc-create', 3)
dom = args[0]
ver = args[1]
num = args[2]
vusb_config = ['vusb']
vusb_config.append(['usb-ver', str(ver)])
vusb_config.append(['num-ports', str(num)])
port_config = ['port']
for i in range(1, int(num) + 1):
port_config.append(['%i' % i, ""])
vusb_config.append(port_config)
server.xend.domain.device_create(dom, vusb_config)
def detach(args, deviceClass):
rm_cfg = True
dom = args[0]
@@ -2942,6 +3070,22 @@ def xm_scsi_detach(args):
else:
server.xend.domain.device_configure(dom, scsi)
def xm_usb_detach(args):
xenapi_unsupported()
arg_check(args, 'usb-detach', 3)
dom = args[0]
dev = args[1]
port = args[2]
usb = ['vusb', ['port', [port, '']]]
server.xend.domain.device_configure(dom, usb, dev)
def xm_usb_hc_destroy(args):
xenapi_unsupported()
arg_check(args, 'usb-hc-destroy', 2)
dom = args[0]
dev = args[1]
server.xend.domain.destroyDevice(dom, 'vusb', dev)
def xm_vnet_list(args):
xenapi_unsupported()
try:
@@ -3372,6 +3516,13 @@ commands = {
"scsi-attach": xm_scsi_attach,
"scsi-detach": xm_scsi_detach,
"scsi-list": xm_scsi_list,
# vusb
"usb-attach": xm_usb_attach,
"usb-detach": xm_usb_detach,
"usb-list": xm_usb_list,
"usb-list-assignable-devices": xm_usb_list_assignable_devices,
"usb-hc-create": xm_usb_hc_create,
"usb-hc-destroy": xm_usb_hc_destroy,
# tmem
"tmem-thaw": xm_tmem_thaw,
"tmem-freeze": xm_tmem_freeze,
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.