def gatherBlockDevices(self): # Get all the current devices from hal and save in a dictionary try: device_names = self.hal_manager.GetAllDevices() i = 0; for name in device_names: #log.debug("device name, device=%s",name) dev_obj = self.bus.get_object ('org.freedesktop.Hal', name) dev = dbus.Interface (dev_obj, 'org.freedesktop.Hal.Device') dev_properties = dev_obj.GetAllProperties(dbus_interface="org.freedesktop.Hal.Device") if dev_properties.has_key('block.device'): dev_str = dev_properties['block.device'] dev_major = dev_properties['block.major'] dev_minor = dev_properties['block.minor'] udi_info = {} udi_info['device'] = dev_str udi_info['major'] = dev_major udi_info['minor'] = dev_minor udi_info['udi'] = name self.udi_dict[i] = udi_info i = i + 1 except Exception, ex: print >>sys.stderr, 'Exception gathering block devices:', ex log.warn("Exception gathering block devices (%s)",ex)
def gatherBlockDevices(self): # Get all the current devices from hal and save in a dictionary try: device_names = self.hal_manager.GetAllDevices() i = 0 for name in device_names: #log.debug("device name, device=%s",name) dev_obj = self.bus.get_object('org.freedesktop.Hal', name) dev = dbus.Interface(dev_obj, 'org.freedesktop.Hal.Device') dev_properties = dev_obj.GetAllProperties( dbus_interface="org.freedesktop.Hal.Device") if dev_properties.has_key('block.device'): dev_str = dev_properties['block.device'] dev_major = dev_properties['block.major'] dev_minor = dev_properties['block.minor'] udi_info = {} udi_info['device'] = dev_str udi_info['major'] = dev_major udi_info['minor'] = dev_minor udi_info['udi'] = name self.udi_dict[i] = udi_info i = i + 1 except Exception, ex: print >> sys.stderr, 'Exception gathering block devices:', ex log.warn("Exception gathering block devices (%s)", ex)
def prepareEnvironment(self): """Prepare the environment for the execution of the domain. This method is called before any devices are set up.""" domid = self.vm.getDomid() # Delete left-over pipes try: os.unlink("/var/run/tap/qemu-read-%d" % domid) os.unlink("/var/run/tap/qemu-write-%d" % domid) except: pass # No device model, don't create pipes if self.device_model is None: return if platform.system() != "SunOS": # If we use a device model, the pipes for communication between # blktapctrl and ioemu must be present before the devices are # created (blktapctrl must access them for new block devices) try: os.makedirs("/var/run/tap", 0755) except: pass try: os.mkfifo("/var/run/tap/qemu-read-%d" % domid, 0600) os.mkfifo("/var/run/tap/qemu-write-%d" % domid, 0600) except OSError, e: log.warn("Could not create blktap pipes for domain %d" % domid) log.exception(e) pass
def prepareEnvironment(self): """Prepare the environment for the execution of the domain. This method is called before any devices are set up.""" domid = self.vm.getDomid() # Delete left-over pipes try: os.unlink('/var/run/tap/qemu-read-%d' % domid) os.unlink('/var/run/tap/qemu-write-%d' % domid) except: pass # No device model, don't create pipes if self.device_model is None: return if platform.system() != 'SunOS': # If we use a device model, the pipes for communication between # blktapctrl and ioemu must be present before the devices are # created (blktapctrl must access them for new block devices) try: os.makedirs('/var/run/tap', 0755) except: pass try: os.mkfifo('/var/run/tap/qemu-read-%d' % domid, 0600) os.mkfifo('/var/run/tap/qemu-write-%d' % domid, 0600) except OSError, e: log.warn('Could not create blktap pipes for domain %d' % domid) log.exception(e) pass
def createDevice(self, config): uname = config.get('uname', '') try: (typ, subtyp, params, file) = string.split(uname, ':', 3) if subtyp not in ('tapdisk', 'ioemu'): raise ValueError('invalid subtype') except: (typ, params, file) = string.split(uname, ':', 2) subtyp = 'tapdisk' if typ in ('tap'): if subtyp in ('tapdisk', 'ioemu'): if params not in blktap2_disk_types or \ TapdiskController.check(): # pass this device off to BlktapController log.warn('WARNING: using deprecated blktap module') self.deviceClass = 'tap' devid = BlktapController.createDevice(self, config) self.deviceClass = 'tap2' return devid device = TapdiskController.create(params, file) # modify the configutration to create a blkback for the underlying # blktap2 device. Note: we need to preserve the original tapdisk uname # (it is used during save/restore and for managed domains). config.update({'tapdisk_uname' : uname}) config.update({'uname' : 'phy:' + device.rstrip()}) devid = BlkifController.createDevice(self, config) config.update({'uname' : uname}) config.pop('tapdisk_uname') return devid
def check(): try: TapdiskController.exc('check') return 0 except Exception, e: log.warn("tapdisk2 check failed: %s" % e) return -1
def createDevice(self, config): uname = config.get('uname', '') try: (typ, subtyp, params, file) = string.split(uname, ':', 3) if subtyp not in ('tapdisk', 'ioemu'): raise ValueError('invalid subtype') except: (typ, params, file) = string.split(uname, ':', 2) subtyp = 'tapdisk' #check for blktap2 installation. blktap2_installed=0; (rc,stdout, stderr) = doexec("cat /proc/devices"); out = stdout.read(); stdout.close(); stderr.close(); if( out.find("blktap2") >= 0 ): blktap2_installed=1; if typ in ('tap'): if subtyp in ('tapdisk', 'ioemu'): if params not in blktap2_disk_types or not blktap2_installed: # pass this device off to BlktapController log.warn('WARNING: using deprecated blktap module') self.deviceClass = 'tap' devid = BlktapController.createDevice(self, config) self.deviceClass = 'tap2' return devid if self.vm.image and self.vm.image.memory_sharing: cmd = [ TAPDISK_BINARY, '-n', '%s:%s' % (params, file), '-s', '%d' % self.vm.getDomid() ] else: cmd = [ TAPDISK_BINARY, '-n', '%s:%s' % (params, file) ] (rc,stdout,stderr) = doexec(cmd) if rc != 0: err = stderr.read(); out = stdout.read(); stdout.close(); stderr.close(); raise Exception, 'Failed to create device.\n stdout: %s\n stderr: %s\nCheck that target \"%s\" exists and that blktap2 driver installed in dom0.' % (out.rstrip(), err.rstrip(), file); minor, device, control = parseDeviceString(stdout.readline()) stdout.close(); stderr.close(); # modify the configutration to create a blkback for the underlying # blktap2 device. Note: we need to preserve the original tapdisk uname # (it is used during save/restore and for managed domains). config.update({'tapdisk_uname' : uname}) config.update({'uname' : 'phy:' + device.rstrip()}) devid = BlkifController.createDevice(self, config) config.update({'uname' : uname}) config.pop('tapdisk_uname') return devid
def hostAllowed(addrport, hosts_allowed): if hosts_allowed is None: return True else: fqdn = socket.getfqdn(addrport[0]) for h in hosts_allowed: if h.match(fqdn) or h.match(addrport[0]): return True log.warn("Rejected connection from %s (%s).", addrport[0], fqdn) return False
def _process_event(self, udev_event): try: if (udev_event.get('SUBSYSTEM', None) == 'pci'): pci_name = udev_event.get('PCI_SLOT_NAME', None) if (udev_event['ACTION'] == 'add'): log.info("Adding pci device %s", pci_name) XendNode.instance().add_PPCI(pci_name) elif (udev_event['ACTION'] == 'remove'): log.info("Removing pci device %s", pci_name) XendNode.instance().remove_PPCI(pci_name) elif (udev_event.get('SUBSYSTEM', None) == 'scsi'): hctl = None devpath = udev_event.get('DEVPATH', None) if devpath: hctl = devpath.split('/')[-1] if len(hctl.split(':')) != 4: hctl = None if hctl is None: # By any possibility, if an HCTL isn't gotten from # the udev event, the udev event is ignored. log.warn("Invalid udev event about scsi received") return if (udev_event['ACTION'] == 'add'): log.info("Adding scsi device %s", hctl) XendNode.instance().add_PSCSI(hctl) elif (udev_event['ACTION'] == 'remove'): 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'): log.info("Adding net device %s", interface) XendNode.instance().add_network(interface) elif (udev_event['ACTION'] == 'remove'): log.info("Removing net device %s", interface) XendNode.instance().remove_network(interface) except Exception, e: log.warn("error while processing udev event(): %s" % str(e))
def createDevice(self, config): uname = config.get('uname', '') try: (typ, subtyp, params, file) = string.split(uname, ':', 3) except: (typ, params, file) = string.split(uname, ':', 2) subtyp = 'tapdisk' #check for blktap2 installation. blktap2_installed=0; (rc,stdout, stderr) = doexec("cat /proc/devices"); out = stdout.read(); stdout.close(); stderr.close(); if( out.find("blktap2") >= 0 ): blktap2_installed=1; if typ in ('tap'): if subtyp in ('tapdisk'): if params not in blktap2_disk_types or not blktap2_installed: # pass this device off to BlktapController log.warn('WARNING: using deprecated blktap module') self.deviceClass = 'tap' devid = BlktapController.createDevice(self, config) self.deviceClass = 'tap2' return devid cmd = [ TAPDISK_BINARY, '-n', '%s:%s' % (params, file) ] (rc,stdout,stderr) = doexec(cmd) if rc != 0: err = stderr.read(); out = stdout.read(); stdout.close(); stderr.close(); raise Exception, 'Failed to create device.\n stdout: %s\n stderr: %s\nCheck that target \"%s\" exists and that blktap2 driver installed in dom0.' % (out.rstrip(), err.rstrip(), file); minor, device, control = parseDeviceString(stdout.readline()) stdout.close(); stderr.close(); # modify the configutration to create a blkback for the underlying # blktap2 device. Note: we need to preserve the original tapdisk uname # (it is used during save/restore and for managed domains). config.update({'tapdisk_uname' : uname}) config.update({'uname' : 'phy:' + device.rstrip()}) devid = BlkifController.createDevice(self, config) config.update({'uname' : uname}) config.pop('tapdisk_uname') return devid
def domains_with_state(detail, state, full): if detail: domains = XendDomain.instance().list_sorted(state) ret = [] for dom in domains: try: ret.append(fixup_sxpr(dom.sxpr(not full))) except: log.warn("Failed to query SXPR for domain %s" % str(dom)) pass return ret else: return XendDomain.instance().list_names(state)
def dataReceived(self, data): udev_event = {} for entry in data.split('\0'): try: opt, val = entry.split("=") udev_event[opt] = val except (TypeError, ValueError): pass if udev_event.get('ACTION', None) is None: log.warn("Invalid udev event received") return log.debug("udev event received: %s", udev_event) self._process_event(udev_event)
def createXenPaging(self): if not self.vm.info.is_hvm(): return if self.actmem == "0": return if self.xenpaging_pid: return xenpaging_bin = auxbin.pathTo("xenpaging") args = [xenpaging_bin] args = args + ([ "-f", "/var/lib/xen/xenpaging/%s.%d.paging" % (str(self.vm.info['name_label']), self.vm.getDomid())]) if self.xenpaging_extra: args = args + (self.xenpaging_extra) args = args + ([ "-d", "%d" % self.vm.getDomid()]) self.xenpaging_logfile = "/var/log/xen/xenpaging-%s.log" % str(self.vm.info['name_label']) logfile_mode = os.O_WRONLY|os.O_CREAT|os.O_APPEND|os.O_TRUNC null = os.open("/dev/null", os.O_RDONLY) try: os.unlink(self.xenpaging_logfile) except: pass logfd = os.open(self.xenpaging_logfile, logfile_mode, 0644) sys.stderr.flush() contract = osdep.prefork("%s:%d" % (self.vm.getName(), self.vm.getDomid())) xenpaging_pid = os.fork() if xenpaging_pid == 0: #child try: osdep.postfork(contract) os.dup2(null, 0) os.dup2(logfd, 1) os.dup2(logfd, 2) try: env = dict(os.environ) log.info("starting %s" % args) os.execve(xenpaging_bin, args, env) except Exception, e: log.warn('failed to execute xenpaging: %s' % utils.exception_string(e)) os._exit(126) except: log.warn("starting xenpaging failed") os._exit(127) else: osdep.postfork(contract, abandon=True) self.xenpaging_pid = xenpaging_pid os.close(null) os.close(logfd) self.vm.storeDom("xenpaging/xenpaging-pid", self.xenpaging_pid) self.vm.storeDom("memory/target-tot_pages", int(self.actmem) * 1024)
def acceptConnection(self, sock, addrport): addr = addrport[0] if self.hosts_allow is None: connection.SocketServerConnection(sock, self.protocol_class) else: fqdn = socket.getfqdn(addr) for h in self.hosts_allow: if h.match(fqdn) or h.match(addr): log.debug("Match %s %s", fqdn, h.pattern) connection.SocketServerConnection(sock, self.protocol_class) return try: log.warn("Rejected connection from %s:%d (%s) for port %d.", addr, addrport[1], fqdn, self.port) sock.close() except: pass
def is_authorized(self, username, password): """Returns true is a user is authorised via PAM. Note: We use the 'login' PAM stack rather than inventing our own. @rtype: boolean """ pam_auth = None try: import PAM pam_auth = PAM.pam() except ImportError: log.warn("python-pam is required for XenAPI support.") return False except NameError: # if PAM doesn't exist, let's ignore it return False pam_auth.start("login") pam_auth.set_item(PAM.PAM_USER, username) def _pam_conv(auth, query_list, user_data = None): resp = [] for i in range(len(query_list)): query, qtype = query_list[i] if qtype == PAM.PAM_PROMPT_ECHO_ON: resp.append((username, 0)) elif qtype == PAM.PAM_PROMPT_ECHO_OFF: resp.append((password, 0)) else: return None return resp pam_auth.set_item(PAM.PAM_CONV, _pam_conv) try: pam_auth.authenticate() pam_auth.acct_mgmt() except PAM.error, resp: return False
def setupDevice(self, config): """Setup devices from config """ pci_str_list = [] pci_dev_list = [] for pci_config in config.get('devs', []): domain = parse_hex(pci_config.get('domain', 0)) bus = parse_hex(pci_config.get('bus', 0)) slot = parse_hex(pci_config.get('slot', 0)) func = parse_hex(pci_config.get('func', 0)) pci_str = '%04x:%02x:%02x.%01x' % (domain, bus, slot, func) pci_str_list = pci_str_list + [pci_str] pci_dev_list = pci_dev_list + [(domain, bus, slot, func)] for (domain, bus, slot, func) in pci_dev_list: try: dev = PciDevice(domain, bus, slot, func) except Exception, e: raise VmError("pci: failed to locate device and " + "parse it's resources - " + str(e)) if (dev.dev_type == DEV_TYPE_PCIe_ENDPOINT) and not dev.pcie_flr: if dev.bus == 0: # We cope with this case by using the Dstate transition # method or some vendor specific methods for now. err_msg = 'pci: %s: it is on bus 0, but has no PCIe' +\ ' FLR Capability. Will try the Dstate transition'+\ ' method or some vendor specific methods if available.' log.warn(err_msg % dev.name) else: funcs = dev.find_all_the_multi_functions() for f in funcs: if not f in pci_str_list: (f_dom, f_bus, f_slot, f_func) = parse_pci_name(f) f_pci_str = '0x%x,0x%x,0x%x,0x%x' % \ (f_dom, f_bus, f_slot, f_func) # f has been assigned to other guest? if xc.test_assign_device(0, f_pci_str) != 0: err_msg = 'pci: %s must be co-assigned to' + \ ' the same guest with %s' raise VmError(err_msg % (f, dev.name)) elif dev.dev_type == DEV_TYPE_PCI: if dev.bus == 0 or arch.type == "ia64": if not dev.pci_af_flr: # We cope with this case by using the Dstate transition # method or some vendor specific methods for now. err_msg = 'pci: %s: it is on bus 0, but has no PCI' +\ ' Advanced Capabilities for FLR. Will try the'+\ ' Dstate transition method or some vendor' +\ ' specific methods if available.' log.warn(err_msg % dev.name) else: # All devices behind the uppermost PCI/PCI-X bridge must be\ # co-assigned to the same guest. devs_str = dev.find_coassigned_devices(True) # Remove the element 0 which is a bridge del devs_str[0] for s in devs_str: if not s in pci_str_list: (s_dom, s_bus, s_slot, s_func) = parse_pci_name(s) s_pci_str = '0x%x,0x%x,0x%x,0x%x' % \ (s_dom, s_bus, s_slot, s_func) # s has been assigned to other guest? if xc.test_assign_device(0, s_pci_str) != 0: err_msg = 'pci: %s must be co-assigned to the'+\ ' same guest with %s' raise VmError(err_msg % (s, dev.name))
def dev_check_assignability_and_do_FLR(self, config): pci_dev_list = config.get('devs', []) pci_str_list = map(pci_dict_to_bdf_str, pci_dev_list) if len(pci_str_list) != len(set(pci_str_list)): raise VmError('pci: duplicate devices specified in guest config?') strict_check = xoptions.get_pci_dev_assign_strict_check() devs = [] for pci_dev in pci_dev_list: try: dev = PciDevice(pci_dev) except Exception, e: raise VmError("pci: failed to locate device and "+ "parse its resources - "+str(e)) if dev.driver!='pciback' and dev.driver!='pci-stub': raise VmError(("pci: PCI Backend and pci-stub don't own device"\ " %s") %(dev.name)) devs.append(dev) if dev.has_non_page_aligned_bar and strict_check: raise VmError("pci: %s: non-page-aligned MMIO BAR found." % dev.name) # Check if there is intermediate PCIe switch bewteen the device and # Root Complex. if self.vm.info.is_hvm() and dev.is_behind_switch_lacking_acs() \ and strict_check: err_msg = 'pci: to avoid potential security issue, %s is not'+\ ' allowed to be assigned to guest since it is behind'+\ ' PCIe switch that does not support or enable ACS.' raise VmError(err_msg % dev.name) if (dev.dev_type == DEV_TYPE_PCIe_ENDPOINT) and not dev.pcie_flr: if dev.bus == 0: # We cope with this case by using the Dstate transition # method or some vendor specific methods for now. err_msg = 'pci: %s: it is on bus 0, but has no PCIe' +\ ' FLR Capability. Will try the Dstate transition'+\ ' method or some vendor specific methods if available.' log.warn(err_msg % dev.name) else: if not self.vm.info.is_hvm(): continue if not strict_check: continue funcs = dev.find_all_the_multi_functions() dev.devs_check_driver(funcs) for f in funcs: if not f in pci_str_list: # f has been assigned to other guest? if f in get_all_assigned_pci_devices(): err_msg = 'pci: %s must be co-assigned to' + \ ' the same guest with %s' raise VmError(err_msg % (f, dev.name)) elif dev.dev_type == DEV_TYPE_PCI: if dev.bus == 0 or arch.type == "ia64": if not dev.pci_af_flr: # We cope with this case by using the Dstate transition # method or some vendor specific methods for now. err_msg = 'pci: %s: it is on bus 0, but has no PCI' +\ ' Advanced Capabilities for FLR. Will try the'+\ ' Dstate transition method or some vendor' +\ ' specific methods if available.' log.warn(err_msg % dev.name) else: if not self.vm.info.is_hvm(): continue if not strict_check: continue # All devices behind the uppermost PCI/PCI-X bridge must be\ # co-assigned to the same guest. devs_str = dev.find_coassigned_pci_devices(True) # Remove the element 0 which is a bridge del devs_str[0] dev.devs_check_driver(devs_str) for s in devs_str: if not s in pci_str_list: # s has been assigned to other guest? if s in get_all_assigned_pci_devices(): err_msg = 'pci: %s must be co-assigned to the'+\ ' same guest with %s' raise VmError(err_msg % (s, dev.name))
def setupDevice(self, config): """Setup devices from config """ pci_dev_list = config.get('devs', []) pci_str_list = map(pci_dict_to_bdf_str, pci_dev_list) if len(pci_str_list) != len(set(pci_str_list)): raise VmError('pci: duplicate devices specified in guest config?') for pci_dev in pci_dev_list: try: dev = PciDevice(pci_dev) except Exception, e: raise VmError("pci: failed to locate device and "+ "parse it's resources - "+str(e)) if (dev.dev_type == DEV_TYPE_PCIe_ENDPOINT) and not dev.pcie_flr: if dev.bus == 0: # We cope with this case by using the Dstate transition # method or some vendor specific methods for now. err_msg = 'pci: %s: it is on bus 0, but has no PCIe' +\ ' FLR Capability. Will try the Dstate transition'+\ ' method or some vendor specific methods if available.' log.warn(err_msg % dev.name) else: funcs = dev.find_all_the_multi_functions() dev.devs_check_driver(funcs) for f in funcs: if not f in pci_str_list: (f_dom, f_bus, f_slot, f_func) = parse_pci_name(f) f_pci_str = '0x%x,0x%x,0x%x,0x%x' % \ (f_dom, f_bus, f_slot, f_func) # f has been assigned to other guest? if xc.test_assign_device(0, f_pci_str) != 0: err_msg = 'pci: %s must be co-assigned to' + \ ' the same guest with %s' raise VmError(err_msg % (f, dev.name)) elif dev.dev_type == DEV_TYPE_PCI: if dev.bus == 0 or arch.type == "ia64": if not dev.pci_af_flr: # We cope with this case by using the Dstate transition # method or some vendor specific methods for now. err_msg = 'pci: %s: it is on bus 0, but has no PCI' +\ ' Advanced Capabilities for FLR. Will try the'+\ ' Dstate transition method or some vendor' +\ ' specific methods if available.' log.warn(err_msg % dev.name) else: # All devices behind the uppermost PCI/PCI-X bridge must be\ # co-assigned to the same guest. devs_str = dev.find_coassigned_pci_devices(True) # Remove the element 0 which is a bridge del devs_str[0] dev.devs_check_driver(devs_str) for s in devs_str: if not s in pci_str_list: s_pci_str = pci_dict_to_bdf_str(parse_pci_name(s)) # s has been assigned to other guest? if xc.test_assign_device(0, s_pci_str) != 0: err_msg = 'pci: %s must be co-assigned to the'+\ ' same guest with %s' raise VmError(err_msg % (s, dev.name))
class XendAuthSessions: """Keeps track of Xen API Login Sessions using PAM. Note: Login sessions are not valid across instances of Xend. """ def __init__(self): self.sessions = {} def init(self): pass def login_unconditionally(self, username): """Returns a session UUID if valid. @rtype: string @return: Session UUID """ new_session = uuid.createString() self.sessions[new_session] = (username, time.time()) return new_session def login_with_password(self, username, password): """Returns a session UUID if valid, otherwise raises an error. @raises XendError: If login fails. @rtype: string @return: Session UUID """ if self.is_authorized(username, password): return self.login_unconditionally(username) raise XendError("Login failed") def logout(self, session): """Delete session of it exists.""" if self.is_session_valid(session): del self.sessions[session] def is_session_valid(self, session): """Returns true is session is valid.""" if type(session) == type(str()): return (session in self.sessions) return False def is_authorized(self, username, password): """Returns true is a user is authorised via PAM. Note: We use the 'login' PAM stack rather than inventing our own. @rtype: boolean """ pam_auth = None try: import PAM pam_auth = PAM.pam() except ImportError: log.warn("python-pam is required for XenAPI support.") return False except NameError: # if PAM doesn't exist, let's ignore it return False pam_auth.start("login") pam_auth.set_item(PAM.PAM_USER, username) def _pam_conv(auth, query_list, user_data = None): resp = [] for i in range(len(query_list)): query, qtype = query_list[i] if qtype == PAM.PAM_PROMPT_ECHO_ON: resp.append((username, 0)) elif qtype == PAM.PAM_PROMPT_ECHO_OFF: resp.append((password, 0)) else: return None return resp pam_auth.set_item(PAM.PAM_CONV, _pam_conv) try: pam_auth.authenticate() pam_auth.acct_mgmt() except PAM.error, resp: return False except Exception, e: log.warn("Error with PAM: %s" % str(e)) return False
def setupDevice(self, config): """Setup devices from config """ pci_str_list = [] pci_dev_list = [] for pci_config in config.get('devs', []): domain = parse_hex(pci_config.get('domain', 0)) bus = parse_hex(pci_config.get('bus', 0)) slot = parse_hex(pci_config.get('slot', 0)) func = parse_hex(pci_config.get('func', 0)) pci_str = '%04x:%02x:%02x.%01x' % (domain, bus, slot, func) pci_str_list = pci_str_list + [pci_str] pci_dev_list = pci_dev_list + [(domain, bus, slot, func)] for (domain, bus, slot, func) in pci_dev_list: try: dev = PciDevice(domain, bus, slot, func) except Exception, e: raise VmError("pci: failed to locate device and "+ "parse it's resources - "+str(e)) if (dev.dev_type == DEV_TYPE_PCIe_ENDPOINT) and not dev.pcie_flr: if dev.bus == 0: # We cope with this case by using the Dstate transition # method or some vendor specific methods for now. err_msg = 'pci: %s: it is on bus 0, but has no PCIe' +\ ' FLR Capability. Will try the Dstate transition'+\ ' method or some vendor specific methods if available.' log.warn(err_msg % dev.name) else: funcs = dev.find_all_the_multi_functions() for f in funcs: if not f in pci_str_list: (f_dom, f_bus, f_slot, f_func) = parse_pci_name(f) f_pci_str = '0x%x,0x%x,0x%x,0x%x' % \ (f_dom, f_bus, f_slot, f_func) # f has been assigned to other guest? if xc.test_assign_device(0, f_pci_str) != 0: err_msg = 'pci: %s must be co-assigned to' + \ ' the same guest with %s' raise VmError(err_msg % (f, dev.name)) elif dev.dev_type == DEV_TYPE_PCI: if dev.bus == 0 or arch.type == "ia64": if not dev.pci_af_flr: # We cope with this case by using the Dstate transition # method or some vendor specific methods for now. err_msg = 'pci: %s: it is on bus 0, but has no PCI' +\ ' Advanced Capabilities for FLR. Will try the'+\ ' Dstate transition method or some vendor' +\ ' specific methods if available.' log.warn(err_msg % dev.name) else: # All devices behind the uppermost PCI/PCI-X bridge must be\ # co-assigned to the same guest. devs_str = dev.find_coassigned_devices(True) # Remove the element 0 which is a bridge del devs_str[0] for s in devs_str: if not s in pci_str_list: (s_dom, s_bus, s_slot, s_func) = parse_pci_name(s) s_pci_str = '0x%x,0x%x,0x%x,0x%x' % \ (s_dom, s_bus, s_slot, s_func) # s has been assigned to other guest? if xc.test_assign_device(0, s_pci_str) != 0: err_msg = 'pci: %s must be co-assigned to the'+\ ' same guest with %s' raise VmError(err_msg % (s, dev.name))
def dev_check_assignability_and_do_FLR(self, config): pci_dev_list = config.get('devs', []) pci_str_list = map(pci_dict_to_bdf_str, pci_dev_list) if len(pci_str_list) != len(set(pci_str_list)): raise VmError('pci: duplicate devices specified in guest config?') strict_check = xoptions.get_pci_dev_assign_strict_check() devs = [] for pci_dev in pci_dev_list: try: dev = PciDevice(pci_dev) except Exception, e: raise VmError("pci: failed to locate device and " + "parse its resources - " + str(e)) if dev.driver != 'pciback' and dev.driver != 'pci-stub': raise VmError(("pci: PCI Backend and pci-stub don't own device"\ " %s") %(dev.name)) devs.append(dev) if dev.has_non_page_aligned_bar and strict_check: raise VmError("pci: %s: non-page-aligned MMIO BAR found." % dev.name) # Check if there is intermediate PCIe switch bewteen the device and # Root Complex. if self.vm.info.is_hvm() and dev.is_behind_switch_lacking_acs() \ and strict_check: err_msg = 'pci: to avoid potential security issue, %s is not'+\ ' allowed to be assigned to guest since it is behind'+\ ' PCIe switch that does not support or enable ACS.' raise VmError(err_msg % dev.name) if (dev.dev_type == DEV_TYPE_PCIe_ENDPOINT) and not dev.pcie_flr: if dev.bus == 0: # We cope with this case by using the Dstate transition # method or some vendor specific methods for now. err_msg = 'pci: %s: it is on bus 0, but has no PCIe' +\ ' FLR Capability. Will try the Dstate transition'+\ ' method or some vendor specific methods if available.' log.warn(err_msg % dev.name) else: if not self.vm.info.is_hvm(): continue if not strict_check: continue funcs = dev.find_all_the_multi_functions() dev.devs_check_driver(funcs) for f in funcs: if not f in pci_str_list: # f has been assigned to other guest? if f in get_all_assigned_pci_devices(): err_msg = 'pci: %s must be co-assigned to' + \ ' the same guest with %s' raise VmError(err_msg % (f, dev.name)) elif dev.dev_type == DEV_TYPE_PCI: if dev.bus == 0 or arch.type == "ia64": if not dev.pci_af_flr: # We cope with this case by using the Dstate transition # method or some vendor specific methods for now. err_msg = 'pci: %s: it is on bus 0, but has no PCI' +\ ' Advanced Capabilities for FLR. Will try the'+\ ' Dstate transition method or some vendor' +\ ' specific methods if available.' log.warn(err_msg % dev.name) else: if not self.vm.info.is_hvm(): continue if not strict_check: continue # All devices behind the uppermost PCI/PCI-X bridge must be\ # co-assigned to the same guest. devs_str = dev.find_coassigned_pci_devices(True) # Remove the element 0 which is a bridge del devs_str[0] dev.devs_check_driver(devs_str) for s in devs_str: if not s in pci_str_list: # s has been assigned to other guest? if s in get_all_assigned_pci_devices(): err_msg = 'pci: %s must be co-assigned to the'+\ ' same guest with %s' raise VmError(err_msg % (s, dev.name))