def get_from_path(items, path): """Returns a list of items matching the specified path. Takes an XPath-like expression e.g. prop1/prop2/prop3, and for each item in items, looks up items[prop1][prop2][prop3]. Like XPath, if any of the intermediate results are lists it will treat each list item individually. A 'None' in items or any child expressions will be ignored, this function will not throw because of None (anywhere) in items. The returned list will contain no None values. """ if path is None: raise exception.Error('Invalid mini_xpath') (first_token, sep, remainder) = path.partition('/') if first_token == '': raise exception.Error('Invalid mini_xpath') results = [] if items is None: return results if not isinstance(items, list): # Wrap single objects in a list items = [items] for item in items: if item is None: continue get_method = getattr(item, 'get', None) if get_method is None: continue child = get_method(first_token) if child is None: continue if isinstance(child, list): # Flatten intermediate lists for x in child: results.append(x) else: results.append(child) if not sep: # No more tokens return results else: return get_from_path(results, remainder)
def register(self, ext): # Do nothing if the extension doesn't check out if not self._check_extension(ext): return alias = ext.alias LOG.info(_LI('Loaded extension: %s'), alias) if alias in self.extensions: raise exception.Error("Found duplicate extension: %s" % alias) self.extensions[alias] = ext
def _await_volume_status(self, context, vol_id, status): # TODO(yamahata): creating volume simultaneously # reduces creation time? # TODO(yamahata): eliminate dumb polling start = time.time() retries = CONF.block_device_allocate_retries if retries < 0: LOG.warn( _LW("Treating negative config value (%(retries)s) for " "'block_device_retries' as 0."), {'retries': retries}) # (1) treat negative config value as 0 # (2) the configured value is 0, one attempt should be made # (3) the configured value is > 0, then the total number attempts # is (retries + 1) attempts = 1 if retries >= 1: attempts = retries + 1 for attempt in range(1, attempts + 1): volume = self.volume_api.get(context, vol_id) volume_status = volume['status'] if volume_status == status: LOG.debug(_("Volume id: %s finished being detached"), vol_id) return attempt greenthread.sleep(CONF.block_device_allocate_retries_interval) # NOTE(harlowja): Should only happen if we ran out of attempts if 'available' == status: LOG.error(_("Volume id: %s detach failed"), vol_id) raise exception.VolumeNotdetach(volume_id=vol_id, seconds=int(time.time() - start), attempts=attempts) elif 'in-use' == status: LOG.error(_("Volume id: %s attach failed"), vol_id) raise exception.VolumeNotAttach(volume_id=vol_id, seconds=int(time.time() - start), attempts=attempts) else: raise exception.Error(message="Volume option error.")
def _await_instance_status(self, context, instance_id, status): start = time.time() retries = CONF.block_device_allocate_retries if retries < 0: LOG.warn( _LW("Treating negative config value (%(retries)s) for " "'block_device_retries' as 0."), {'retries': retries}) # (1) treat negative config value as 0 # (2) the configured value is 0, one attempt should be made # (3) the configured value is > 0, then the total number attempts # is (retries + 1) attempts = 1 if retries >= 1: attempts = retries + 1 for attempt in range(1, attempts + 1): instance = self.nova_api.get_server(context, instance_id) instance_status = instance.get('status', None) if instance_status == status: LOG.error(_("Instance id: %(id)s finished being %(st)s"), { 'id': instance_id, 'st': status }) return attempt greenthread.sleep(CONF.block_device_allocate_retries_interval) if 'SHUTOFF' == status: LOG.error(_("Instance id: %s stop failed"), instance_id) raise exception.InstanceNotStop(instance_id=instance_id, seconds=int(time.time() - start), attempts=attempts) elif 'ACTIVE' == status: LOG.error(_("Instance id: %s start failed"), instance_id) raise exception.InstanceNotStart(instance_id=instance_id, seconds=int(time.time() - start), attempts=attempts) else: raise exception.Error(message="Instance option error.")
def get_blkdev_major_minor(path, lookup_for_file=True): """Get the device's "major:minor" number of a block device to control I/O ratelimit of the specified path. If lookup_for_file is True and the path is a regular file, lookup a disk device which the file lies on and returns the result for the device. """ st = os.stat(path) if stat.S_ISBLK(st.st_mode): path, st = _get_disk_of_partition(path, st) return '%d:%d' % (os.major(st.st_rdev), os.minor(st.st_rdev)) elif stat.S_ISCHR(st.st_mode): # No I/O ratelimit control is provided for character devices return None elif lookup_for_file: # lookup the mounted disk which the file lies on out, _err = execute('df', path) devpath = out.split("\n")[1].split()[0] if devpath[0] is not '/': # the file is on a network file system return None return get_blkdev_major_minor(devpath, False) else: msg = _("Unable to get a block device for file \'%s\'") % path raise exception.Error(msg)