def _get_vmedia_params(): """This method returns the parameters passed through virtual media floppy. :returns: a partial dict of potential agent configuration parameters :raises: VirtualMediaBootError when it cannot find the virtual media device """ parameters_file = "parameters.txt" vmedia_device_file = _find_vmedia_device_by_labels(['ir-vfd-dev']) if not vmedia_device_file: # This falls back to trying to find a matching device by name/type. # if not found, it is likely okay to just fail out and treat it as # No device found as there are multiple ways to launch IPA, and all # vmedia styles should be treated consistently. vmedia_device = _get_vmedia_device() if not vmedia_device: return {} vmedia_device_file = os.path.join("/dev", vmedia_device) if not _check_vmedia_device(vmedia_device_file): # If the device is not valid, return an empty dictionary. return {} with ironic_utils.mounted(vmedia_device_file) as vmedia_mount_point: parameters_file_path = os.path.join(vmedia_mount_point, parameters_file) params = _read_params_from_file(parameters_file_path) return params
def partition_with_path(path): root_dev = hardware.dispatch_to_managers('get_os_install_device') partitions = disk_utils.list_partitions(root_dev) local_path = tempfile.mkdtemp() for part in partitions: if 'esp' in part['flags'] or 'lvm' in part['flags']: LOG.debug('Skipping partition %s', part) continue part_path = partition_index_to_name(root_dev, part['number']) try: with utils.mounted(part_path) as local_path: conf_path = os.path.join(local_path, path) LOG.debug('Checking for path %s on %s', conf_path, part_path) if not os.path.isdir(conf_path): continue LOG.info('Path found: %s on %s', conf_path, part_path) yield conf_path return except processutils.ProcessExecutionError as exc: LOG.warning('Failure when inspecting partition %s: %s', part, exc) raise RuntimeError("No partition found with path %s, scanned: %s" % (path, partitions))
def _find_and_mount_path(path, partition, root_dev): """Find the specified path on a device. Tries to find the suitable device for the file based on the ``path`` and ``partition``, mount the device and provides the actual full path. :param path: Path to the file to find. :param partition: Device to find the file on or None. :param root_dev: Root device from the hardware manager. :return: Context manager that yields the full path to the file. """ path = os.path.normpath(path.strip('/')) # to make path joining work if partition: try: part_num = int(partition) except ValueError: with ironic_utils.mounted(partition) as part_path: yield os.path.join(part_path, path) else: # TODO(dtantsur): switch to ironic-lib instead: # https://review.opendev.org/c/openstack/ironic-lib/+/774502 part_template = '%s%s' if 'nvme' in root_dev: part_template = '%sp%s' part_dev = part_template % (root_dev, part_num) with ironic_utils.mounted(part_dev) as part_path: yield os.path.join(part_path, path) else: try: # This turns e.g. etc/sysctl.d/my.conf into etc + sysctl.d/my.conf detect_dir, rest_dir = path.split('/', 1) except ValueError: # Validation ensures that files in / have "partition" present, # checking here just in case. raise errors.InvalidCommandParamsError( "Invalid path %s, must be an absolute path to a file" % path) with find_partition_with_path(detect_dir, root_dev) as part_path: yield os.path.join(part_path, rest_dir)
def find_partition_with_path(path, device=None): """Find a partition with the given path. :param path: Expected path. :param device: Target device. If None, the root device is used. :returns: A context manager that will unmount and delete the temporary mount point on exit. """ if device is None: device = hardware.dispatch_to_managers('get_os_install_device') partitions = disk_utils.list_partitions(device) # Make os.path.join work as expected lookup_path = path.lstrip('/') for part in partitions: if 'lvm' in part['flags']: LOG.debug('Skipping LVM partition %s', part) continue # TODO(dtantsur): switch to ironic-lib instead: # https://review.opendev.org/c/openstack/ironic-lib/+/774502 part_template = '%s%s' if 'nvme' in device: part_template = '%sp%s' part_path = part_template % (device, part['number']) LOG.debug('Inspecting partition %s for path %s', part, path) try: with ironic_utils.mounted(part_path) as local_path: found_path = os.path.join(local_path, lookup_path) if not os.path.isdir(found_path): continue LOG.info('Path %s has been found on partition %s', path, part) yield found_path return except processutils.ProcessExecutionError as exc: LOG.warning('Failure when inspecting partition %s: %s', part, exc) raise errors.DeviceNotFound( "No partition found with path %s, scanned: %s" % (path, partitions))
def copy_config_from_vmedia(): """Copies any configuration from a virtual media device. Copies files under /etc/ironic-python-agent and /etc/ironic-python-agent.d. """ vmedia_device_file = _find_vmedia_device_by_labels( ['config-2', 'vmedia_boot_iso']) if not vmedia_device_file: _early_log('No virtual media device detected') return if not _booted_from_vmedia(): _early_log('Cannot use configuration from virtual media as the ' 'agent was not booted from virtual media.') return # Determine the device mounted = _find_mount_point(vmedia_device_file) if mounted: _copy_config_from(mounted) else: with ironic_utils.mounted(vmedia_device_file) as vmedia_mount_point: _copy_config_from(vmedia_mount_point)