예제 #1
0
    def waitForDevice(self, devid):
        log.debug("Waiting for %s.", devid)
        
        status = self.waitForBackend(devid)

        if status == Timeout:
            self.destroyDevice(devid)
            raise VmError("Device %s (%s) could not be connected. "
                          "Hotplug scripts not working." %
                          (devid, self.deviceClass))

        elif status == Error:
            self.destroyDevice(devid)
            raise VmError("Device %s (%s) could not be connected. "
                          "Backend device not found." %
                          (devid, self.deviceClass))

        elif status == Missing:
            # Don't try to destroy the device; it's already gone away.
            raise VmError("Device %s (%s) could not be connected. "
                          "Device not found." % (devid, self.deviceClass))

        elif status == Busy:
            err = None
            frontpath = self.frontendPath(devid)
            backpath = xstransact.Read(frontpath, "backend")
            if backpath:
                err = xstransact.Read(backpath, HOTPLUG_ERROR_NODE)
            if not err:
                err = "Busy."
                
            self.destroyDevice(devid)
            raise VmError("Device %s (%s) could not be connected.\n%s" %
                          (devid, self.deviceClass, err))
예제 #2
0
    def waitForBackend(self, devid):
        frontpath = self.frontendPath(devid)
        # lookup a phantom
        phantomPath = xstransact.Read(frontpath, 'phantom_vbd')
        if phantomPath is not None:
            log.debug("Waiting for %s's phantom %s.", devid, phantomPath)
            statusPath = phantomPath + '/' + HOTPLUG_STATUS_NODE
            ev = Event()
            result = {'status': Timeout}
            xswatch(statusPath, hotplugStatusCallback, ev, result)
            ev.wait(DEVICE_CREATE_TIMEOUT)
            err = xstransact.Read(statusPath, HOTPLUG_ERROR_NODE)
            if result['status'] != Connected:
                return (result['status'], err)

        backpath = self.readVm(devid, "backend")

        if backpath:
            statusPath = backpath + '/' + HOTPLUG_STATUS_NODE
            ev = Event()
            result = {'status': Timeout}

            xswatch(statusPath, hotplugStatusCallback, ev, result)

            ev.wait(DEVICE_CREATE_TIMEOUT)

            err = xstransact.Read(backpath, HOTPLUG_ERROR_NODE)

            return (result['status'], err)
        else:
            return (Missing, None)
예제 #3
0
 def readBackend(self, devid, *args):
     frontpath = self.frontendPath(devid)
     backpath = xstransact.Read(frontpath, "backend")
     if backpath:
         return xstransact.Read(backpath, *args)
     else:
         raise VmError("Device %s not connected" % devid)
예제 #4
0
    def recreate_active_pools(cls):
        """ Read active pool config from hypervisor and create pool instances.
            - Query pool ids and assigned CPUs from hypervisor.
            - Query additional information for any pool from xenstore.
              If an entry for a pool id is missing in xenstore, it will be
              recreated with a new uuid and generic name (this is an error case)
            - Create an XendCPUPool instance for any pool id
            Function have to be called after recreation of managed pools.
        """
        log.debug('recreate_active_pools')

        for pool_rec in xc.cpupool_getinfo():
            pool = pool_rec['cpupool']

            # read pool data from xenstore
            path = XS_POOLROOT + "%s/" % pool
            uuid = xstransact.Read(path, 'uuid')
            if not uuid:
                # xenstore entry missing / invaild; create entry with new uuid
                uuid = genuuid.createString()
                name = "Pool-%s" % pool
                try:
                    inst = XendCPUPool({'name_label': name}, uuid, False)
                    inst.update_XS(pool)
                except PoolError, ex:
                    # log error and skip domain
                    log.error('cannot recreate pool %s; skipping (reason: %s)' \
                        % (name, ex))
            else:
                (name, descr) = xstransact.Read(path, 'name', 'description')
                other_config = {}
                for key in xstransact.List(path + 'other_config'):
                    other_config[key] = xstransact.Read(path +
                                                        'other_config/%s' %
                                                        key)

                # check existance of pool instance
                inst = XendAPIStore.get(uuid, cls.getClass())
                if inst:
                    # update attributes of existing instance
                    inst.name_label = name
                    inst.name_description = descr
                    inst.other_config = other_config
                else:
                    # recreate instance
                    try:
                        inst = XendCPUPool(
                            {
                                'name_label': name,
                                'name_description': descr,
                                'other_config': other_config,
                                'proposed_CPUs': pool_rec['cpulist'],
                                'ncpu': len(pool_rec['cpulist']),
                            }, uuid, False)
                    except PoolError, ex:
                        # log error and skip domain
                        log.error(
                            'cannot recreate pool %s; skipping (reason: %s)' \
                            % (name, ex))
예제 #5
0
def diagnose_console():
    port = xstransact.Read(dompath + '/console/port')
    ringref = xstransact.Read(dompath + '/console/ring-ref')
    tty = xstransact.Read(dompath + '/console/tty')

    if not port:
        print "Console port is missing; Xend has failed."
    if not ringref:
        print "Console ring-ref is missing; Xend has failed."
    if not tty:
        print "Console tty is missing; Xenconsoled has failed."
예제 #6
0
def get_assigned_pci_devices(domid):
    dev_str_list = []
    path = '/local/domain/0/backend/pci/%u/0/' % domid
    num_devs = xstransact.Read(path + 'num_devs')
    if num_devs is None or num_devs == "":
        return dev_str_list
    num_devs = int(num_devs)
    for i in range(num_devs):
        dev_str = xstransact.Read(path + 'dev-%i' % i)
        dev_str_list = dev_str_list + [dev_str]
    return dev_str_list
예제 #7
0
def get_all_assigned_pci_devices(domid=0):
    dom_list = xstransact.List('/local/domain')
    pci_str_list = []
    ti = 0
    ts = xstransact.Read('/local/domain/' + str(domid) + '/target')
    if ts is not None:
        ti = int(ts)
    for d in dom_list:
        target = xstransact.Read('/local/domain/' + d + '/target')
        if int(d) is not ti and target is None:
            pci_str_list = pci_str_list + get_assigned_pci_devices(int(d))
    return pci_str_list
예제 #8
0
    def signalDeviceModel(self, cmd, ret, par=None):
        if self.device_model is None:
            return
        # Signal the device model to for action
        if cmd is '' or ret is '':
            raise VmError(
                'need valid command and result when signal device model')

        count = 0
        while True:
            orig_state = xstransact.Read(
                "/local/domain/0/device-model/%i/state" % self.vm.getDomid())
            # This can occur right after start-up
            if orig_state != None:
                break

            log.debug('signalDeviceModel: orig_state is None, retrying')

            time.sleep(0.1)
            count += 1
            if count < 100:
                continue

            raise VmError('Device model isn\'t ready for commands')

        if par is not None:
            xstransact.Store(
                "/local/domain/0/device-model/%i" % self.vm.getDomid(),
                ('parameter', par))

        xstransact.Store(
            "/local/domain/0/device-model/%i" % self.vm.getDomid(),
            ('command', cmd))
        # Wait for confirmation.  Could do this with a watch but we'd
        # still end up spinning here waiting for the watch to fire.
        state = ''
        count = 0
        while state != ret:
            state = xstransact.Read("/local/domain/0/device-model/%i/state" %
                                    self.vm.getDomid())
            time.sleep(0.1)
            count += 1
            if count > 100:
                raise VmError('Timed out waiting for device model action')

        #resotre orig state
        xstransact.Store(
            "/local/domain/0/device-model/%i" % self.vm.getDomid(),
            ('state', orig_state))
        log.info("signalDeviceModel:restore dm state to %s", orig_state)
예제 #9
0
    def destroyDevice(self, devid, force):
        """Destroy the specified device.

        @param devid The device ID, or something device-specific from which
        the device ID can be determined (such as a guest-side device name).

        The implementation here simply deletes the appropriate paths from the
        store.  This may be overridden by subclasses who need to perform other
        tasks on destruction. The implementation here accepts integer device
        IDs or paths containg integer deviceIDs, e.g. vfb/0.  Subclasses may
        accept other values and convert them to integers before passing them
        here.
        """

        dev = self.convertToDeviceNumber(devid)

        # Modify online status /before/ updating state (latter is watched by
        # drivers, so this ordering avoids a race).
        self.writeBackend(dev, 'online', "0")
        self.writeBackend(dev, 'state', str(xenbusState['Closing']))

        if force:
            frontpath = self.frontendPath(dev)
            backpath = xstransact.Read(frontpath, "backend")
            if backpath:
                xstransact.Remove(backpath)
            xstransact.Remove(frontpath)

        self.vm._removeVm("device/%s/%d" % (self.deviceClass, dev))
예제 #10
0
    def cleanupDevice(self, devid):
        devs = self.readBackendList(devid, "vscsi-devs")
        vscsipath = "vscsi-devs/"
        new_num_devs = 0
        
        for dev in devs:
            new_num_devs = new_num_devs + 1
            devpath = vscsipath + dev
            devstate = self.readBackend(devid, devpath + '/state')

            if str(xenbusState['Closed']) == devstate:
                self.removeBackend(devid, devpath)
                frontpath = self.frontendPath(devid)
                xstransact.Remove(frontpath + '/' + devpath)
                new_num_devs = new_num_devs - 1

            frontpath = self.frontendPath(devid)
            front_devstate = xstransact.Read(frontpath + '/' + devpath)
            if front_devstate is not None:
                if str(xenbusState['Closed']) == front_devstate:
                    self.removeBackend(devid, devpath)
                    xstransact.Remove(frontpath + '/' + devpath)
                    new_num_devs = new_num_devs - 1

        return new_num_devs
예제 #11
0
 def _handleAerStateWatch(self, _):
     log.debug('XendDomainInfo.handleAerStateWatch')
     if self.getDomid() == 0:
         raise XendError('Domain 0 cannot be shutdown')
     readPath = '/local/domain/0/backend/pci/%u/0/aerState' % (self.getDomid())
     action = xstransact.Read(readPath)
     if action and action=='aerfail':
         log.debug('shutdown domain because of aer handle error')
         self.vm.shutdown('poweroff')
     return True
예제 #12
0
    def configuration(self, devid):
        """@return an s-expression giving the current configuration of the
        specified device.  This would be suitable for giving to {@link
        #createDevice} in order to recreate that device."""

        backdomid = xstransact.Read(self.frontendPath(devid), "backend-id")
        if backdomid is None:
            raise VmError("Device %s not connected" % devid)
        
        return [self.deviceClass, ['backend', int(backdomid)]]
예제 #13
0
def diagnose_devices():
    global deviceClass
    global device
    global frontendPath
    global backendPath

    device_path = dompath + '/device'

    device_classes = xstransact.List(device_path)

    print "Found %d device classes in use." % len(device_classes)

    for dc in device_classes:
        deviceClass = dc
        device_class_path = device_path + '/' + deviceClass

        devices = xstransact.List(device_class_path)

        print "Found %d %s devices." % (len(devices), deviceClass)

        for d in devices:
            device = d

            print "Found device %s, %s." % (deviceClass, device)

            frontendPath = device_class_path + '/' + device
            backendPath = xstransact.Read(frontendPath, 'backend')

            if not backendPath:
                print("Cannot find backend path for device %s, %s." %
                      (deviceClass, device))
            else:
                frontend_state = xstransact.Read(frontendPath, 'state')
                backend_state = xstransact.Read(backendPath, 'state')

                print "Backend is in state %s." % stateString(backend_state)
                print "Frontend is in state %s." % stateString(frontend_state)

                check_for_error(True)
                check_for_error(False)

                diagnose_hotplugging()
예제 #14
0
def diagnose_hotplugging():
    if deviceClass == 'vbd':
        phy = xstransact.Read(backendPath, 'physical-device')

        if phy:
            print(
                'Device %s, %s hotplugging has completed successfully, '
                'and is connected to physical device %s.' %
                (deviceClass, device, phy))
        else:
            print('Device %s, %s hotplugging failed.' % (deviceClass, device))
    elif deviceClass == 'vif':
        handle = xstransact.Read(backendPath, 'handle')

        if handle:
            print(
                'Device %s, %s hotplugging has completed successfully, '
                'and is using handle %s.' % (deviceClass, device, handle))
        else:
            print('Device %s, %s hotplugging failed.' % (deviceClass, device))
예제 #15
0
def check_for_error(backend):
    if backend:
        path = backendPath.replace('backend/', 'error/backend/')
    else:
        path = frontendPath.replace('device/', 'error/device/')

    err = xstransact.Read(path, 'error')

    if err:
        print("%s for device %s, %s shows error %s." %
              (backend and 'Backend' or 'Frontend', deviceClass, device, err))
예제 #16
0
 def query_pool_ref(cls, pool_id):
     """ Get pool ref by pool id.
         Take the ref from xenstore.
         @param pool_id:
         @type  pool_id: int
         @return: ref
         @rtype:  str
     """
     uuid = xstransact.Read(XS_POOLROOT + "%s/" % pool_id, 'uuid')
     if uuid:
         return [uuid]
     else:
         return []
예제 #17
0
def xenbusStatusCallback(statusPath, ev, result):
    log.debug("xenbusStatusCallback %s.", statusPath)

    status = xstransact.Read(statusPath)

    if status == str(xenbusState['Connected']):
        result['status'] = Connected
    else:
        return 1

    log.debug("xenbusStatusCallback %d.", result['status'])

    ev.set()
    return 0
예제 #18
0
def deviceDestroyCallback(statusPath, ev, result):
    log.debug("deviceDestroyCallback %s.", statusPath)

    status = xstransact.Read(statusPath)

    if status is None:
        result['status'] = Disconnected
    else:
        return 1

    log.debug("deviceDestroyCallback %d.", result['status'])

    ev.set()
    return 0
예제 #19
0
 def frontendStatusCallback(statusPath, ev, result):
     status = xstransact.Read(statusPath)
     log.debug("frontendStatusCallback %s = %s" % (statusPath, status))
     try:
         status = int(status)
         if status == xenbusState['Connected']:
             result['status'] = Connected
         elif status == xenbusState['Closed']:
             result['status'] = Error
         else:
             raise
     except:
         return 1
     ev.set()
     return 0
예제 #20
0
    def getDeviceConfiguration(self, devid, transaction=None):
        """Returns the configuration of a device.

        @note: Similar to L{configuration} except it returns a dict.
        @return: dict
        """
        if transaction is None:
            backdomid = xstransact.Read(self.frontendPath(devid), "backend-id")
        else:
            backdomid = transaction.read(
                self.frontendPath(devid) + "/backend-id")
        if backdomid is None:
            raise VmError("Device %s not connected" % devid)

        return {'backend': int(backdomid)}
예제 #21
0
    def waitForBackend_reconfigure(self, devid):
        frontpath = self.frontendPath(devid)
        backpath = xstransact.Read(frontpath, "backend")
        if backpath:
            statusPath = backpath + '/' + "state"
            ev = Event()
            result = {'status': Timeout}

            xswatch(statusPath, xenbusStatusCallback, ev, result)

            ev.wait(DEVICE_CREATE_TIMEOUT)

            return (result['status'], None)
        else:
            return (Missing, None)
예제 #22
0
    def query_pool_id(self):
        """ Get corresponding pool-id of pool instance from XenStore.
            @return: pool id or None
            @rytpe:  int
        """
        self.pool_lock.acquire()
        try:
            for pool_id in xstransact.List(XS_POOLROOT):
                uuid = xstransact.Read(XS_POOLROOT + "%s/" % pool_id, 'uuid')
                if uuid == self.get_uuid():
                    return int(pool_id)
        finally:
            self.pool_lock.release()

        return None
예제 #23
0
    def waitForBackend_destroy(self, backpath):

        statusPath = backpath + '/' + HOTPLUG_STATUS_NODE
        ev = Event()
        result = {'status': Timeout}

        xswatch(statusPath, deviceDestroyCallback, ev, result)

        for i in range(1, 50):
            ev.wait(DEVICE_DESTROY_TIMEOUT / 50)
            status = xstransact.Read(statusPath)
            if status is None:
                result['status'] = Disconnected
                break

        return result['status']
예제 #24
0
 def change_xenstore(self, action, device, major, minor):
     for type in DEVICE_TYPES:
         path = self.dbpath + '/' + type
         domains = xstransact.List(path)
         log.debug('domains: %s', domains)
         for domain in domains:  # for each domain
             devices = xstransact.List(path + '/' + domain)
             log.debug('devices: %s', devices)
             for device in devices:  # for each vbd device
                 str = device.split('/')
                 vbd_type = None
                 vbd_physical_device = None
                 vbd_media = None
                 vbd_device_path = path + '/' + domain + '/' + device
                 listing = xstransact.List(vbd_device_path)
                 for entry in listing:  # for each entry
                     item = path + '/' + entry
                     value = xstransact.Read(vbd_device_path + '/' + entry)
                     log.debug('%s=%s', item, value)
                     if item.find('media-present') != -1:
                         vbd_media = item
                         vbd_media_path = item
                     if item.find('physical-device') != -1:
                         vbd_physical_device = value
                     if item.find('type') != -1:
                         vbd_type = value
                 if vbd_type is not None and vbd_physical_device is not None and vbd_media is not None:
                     inode = vbd_physical_device.split(':')
                     imajor = parse_hex(inode[0])
                     iminor = parse_hex(inode[1])
                     log.debug(
                         "action:%s major:%s- minor:%s- imajor:%s- iminor:%s- inode: %s",
                         action, major, minor, imajor, iminor, inode)
                     if int(imajor) == int(major) and int(iminor) == int(
                             minor):
                         if action == "add":
                             xs_dict = {'media': "1"}
                             xstransact.Write(vbd_device_path,
                                              'media-present', "1")
                             log.debug(
                                 "wrote xenstore media-present 1 path:%s",
                                 vbd_media_path)
                         else:
                             xstransact.Write(vbd_device_path,
                                              'media-present', "0")
                             log.debug("wrote xenstore media 0 path:%s",
                                       vbd_media_path)
예제 #25
0
 def saveDeviceModel(self):
     if self.device_model is None:
         return
     # Signal the device model to pause itself and save its state
     xstransact.Store(
         "/local/domain/0/device-model/%i" % self.vm.getDomid(),
         ('command', 'save'))
     # Wait for confirmation.  Could do this with a watch but we'd
     # still end up spinning here waiting for the watch to fire.
     state = ''
     count = 0
     while state != 'paused':
         state = xstransact.Read("/local/domain/0/device-model/%i/state" %
                                 self.vm.getDomid())
         time.sleep(0.1)
         count += 1
         if count > 100:
             raise VmError('Timed out waiting for device model to save')
예제 #26
0
def hotplugStatusCallback(statusPath, ev, result):
    log.debug("hotplugStatusCallback %s.", statusPath)

    status = xstransact.Read(statusPath)

    if status is not None:
        if status == HOTPLUG_STATUS_ERROR:
            result['status'] = Error
        elif status == HOTPLUG_STATUS_BUSY:
            result['status'] = Busy
        else:
            result['status'] = Connected
    else:
        return 1

    log.debug("hotplugStatusCallback %d.", result['status'])

    ev.set()
    return 0
예제 #27
0
    def waitForBackend(self, devid):
        
        # FIXME!!! We haven't udev daemon...
        #result = { 'status': Connected }
        #return result['status']

        frontpath = self.frontendPath(devid)
        backpath = xstransact.Read(frontpath, "backend")

        if backpath:
            statusPath = backpath + '/' + HOTPLUG_STATUS_NODE
            ev = Event()
            result = { 'status': Timeout }
            
            xswatch(statusPath, hotplugStatusCallback, ev, result)

            ev.wait(DEVICE_CREATE_TIMEOUT)
            return result['status']
        else:
            return Missing
예제 #28
0
    def destroyDevice(self, devid):
        """Destroy the specified device.

        @param devid The device ID, or something device-specific from which
        the device ID can be determined (such as a guest-side device name).

        The implementation here simply deletes the appropriate paths from the
        store.  This may be overridden by subclasses who need to perform other
        tasks on destruction.  Further, the implementation here can only
        accept integer device IDs, or values that can be converted to
        integers.  Subclasses may accept other values and convert them to
        integers before passing them here.
        """

        devid = int(devid)
        
        frontpath = self.frontendPath(devid)
        backpath = xstransact.Read(frontpath, "backend")

        if backpath:
            xstransact.Write(backpath, 'state', str(xenbusState['Closing']))
        else:
            raise VmError("Device %s not connected" % devid)
예제 #29
0
 def readFrontend(self, devid, *args):
     return xstransact.Read(self.frontendPath(devid), *args)
예제 #30
0
 def readBackend(self, devid, *args):
     backpath = self.readVm(devid, "backend")
     if backpath:
         return xstransact.Read(backpath, *args)
     else:
         raise VmError("Device %s not connected" % devid)