Пример #1
0
    def _ata_erase(self, block_device):
        security_lines = self._get_ata_security_lines(block_device)

        # If secure erase isn't supported return False so erase_block_device
        # can try another mechanism. Below here, if secure erase is supported
        # but fails in some way, error out (operators of hardware that supports
        # secure erase presumably expect this to work).
        if 'supported' not in security_lines:
            return False

        if 'enabled' in security_lines:
            raise errors.BlockDeviceEraseError(('Block device {0} already has '
                'a security password set').format(block_device.name))

        if 'not frozen' not in security_lines:
            raise errors.BlockDeviceEraseError(('Block device {0} is frozen '
                'and cannot be erased').format(block_device.name))

        utils.execute('hdparm', '--user-master', 'u', '--security-set-pass',
                      'NULL', block_device.name)
        utils.execute('hdparm', '--user-master', 'u', '--security-erase',
                      'NULL', block_device.name)

        # Verify that security is now 'not enabled'
        security_lines = self._get_ata_security_lines(block_device)
        if 'not enabled' not in security_lines:
            raise errors.BlockDeviceEraseError(('An unknown error occurred '
                'erasing block device {0}').format(block_device.name))

        return True
Пример #2
0
def _add_vlan_interface(interface, vlan, interfaces_list):

    vlan_name = interface + '.' + vlan

    # if any(x for x in interfaces_list if x.name == vlan_name):
    if any(x.name == vlan_name for x in interfaces_list):
        LOG.info("VLAN interface %s has already been added", vlan_name)
        return ''

    try:
        LOG.info('Adding VLAN interface %s', vlan_name)
        # Add the interface
        utils.execute('ip',
                      'link',
                      'add',
                      'link',
                      interface,
                      'name',
                      vlan_name,
                      'type',
                      'vlan',
                      'id',
                      vlan,
                      check_exit_code=[0, 2])

        # Bring up interface
        utils.execute('ip', 'link', 'set', 'dev', vlan_name, 'up')

    except Exception as exc:
        LOG.warning(
            'Exception when running ip commands to add VLAN '
            'interface: %s', exc)
        return ''

    return vlan_name
Пример #3
0
    def _run_shutdown_command(self, command):
        """Run the shutdown or reboot command

        :param command: A string having the command to be run.
        :raises: InvalidCommandParamsError if the passed command is not
            equal to poweroff or reboot.
        :raises: SystemRebootError if the command errors out with an
            unsuccessful exit code.
        """
        if command not in ('reboot', 'poweroff'):
            msg = (('Expected the command "poweroff" or "reboot" '
                    'but received "%s".') % command)
            raise errors.InvalidCommandParamsError(msg)
        try:
            self.sync()
        except errors.CommandExecutionError as e:
            LOG.warning('Failed to sync file system buffers: % s', e)
        try:
            _, stderr = utils.execute(command,
                                      use_standard_locale=True,
                                      check_exit_code=[0])
            if 'ignoring request.' in stderr:
                LOG.debug(
                    '%s command failed with error %s, '
                    'falling back to sysrq-trigger.', command, stderr)
                if command == 'poweroff':
                    utils.execute("echo o > /proc/sysrq-trigger", shell=True)
                elif command == 'reboot':
                    utils.execute("echo b > /proc/sysrq-trigger", shell=True)
        except processutils.ProcessExecutionError as e:
            raise errors.SystemRebootError(e.exit_code, e.stdout, e.stderr)
Пример #4
0
 def test_no_exception_raised_for_execute(self, mock_exec):
     # Make sure we can call utils.execute() even though we didn't mock it.
     # We do mock ironic_lib.utils.execute() so we don't actually execute
     # anything.
     utils.execute("ls")
     utils.execute("echo")
     self.assertEqual(2, mock_exec.call_count)
Пример #5
0
def _get_vmedia_params():
    """This method returns the parameters passed to the agent through virtual
    media floppy.
    """
    vmedia_mount_point = "/vmedia_mnt"
    parameters_file = "parameters.txt"

    vmedia_device = _get_vmedia_device()
    if not vmedia_device:
        msg = "Unable to find virtual media device"
        raise errors.VirtualMediaBootError(msg)

    vmedia_device_file = os.path.join("/dev", vmedia_device)
    os.mkdir(vmedia_mount_point)

    try:
        stdout, stderr = utils.execute("mount", vmedia_device_file,
                                       vmedia_mount_point)
    except processutils.ProcessExecutionError as e:
        msg = ("Unable to mount virtual media device %(device)s: %(error)s" % {
            'device': vmedia_device_file,
            'error': e
        })
        raise errors.VirtualMediaBootError(msg)

    parameters_file_path = os.path.join(vmedia_mount_point, parameters_file)
    params = _read_params_from_file(parameters_file_path)

    try:
        stdout, stderr = utils.execute("umount", vmedia_mount_point)
    except processutils.ProcessExecutionError as e:
        pass

    return params
Пример #6
0
    def get_system_vendor_info(self):
        product_name = None
        serial_number = None
        manufacturer = None
        try:
            out, _e = utils.execute("dmidecode --type system", shell=True)
        except (processutils.ProcessExecutionError, OSError) as e:
            LOG.warning("Cannot get system vendor information: %s", e)
        else:
            for line in out.split('\n'):
                line_arr = line.split(':', 1)
                if len(line_arr) != 2:
                    continue
                if line_arr[0].strip() == 'Product Name':
                    product_name = line_arr[1].strip()
                elif line_arr[0].strip() == 'Serial Number':
                    serial_number = line_arr[1].strip()
                elif line_arr[0].strip() == 'Manufacturer':
                    manufacturer = line_arr[1].strip()

        try:
            out, _e = utils.execute("dmidecode -s chassis-asset-tag",
                                    shell=True)
        except (processutils.ProcessExecutionError, OSError) as e:
            LOG.warning("Cannot get system vendor asset tag: %s", e)
        else:
            out_list = out.strip().split('\n')
            asset_tag = out_list[len(out_list) - 1]

        return SystemVendorInfo(product_name=product_name,
                                serial_number=serial_number,
                                manufacturer=manufacturer,
                                asset_tag=asset_tag)
Пример #7
0
    def _run_shutdown_command(self, command):
        """Run the shutdown or reboot command

        :param command: A string having the command to be run.
        :raises: InvalidCommandParamsError if the passed command is not
            equal to poweroff or reboot.
        :raises: SystemRebootError if the command errors out with an
            unsuccessful exit code.
        """
        if command not in ('reboot', 'poweroff'):
            msg = (('Expected the command "poweroff" or "reboot" '
                    'but received "%s".') % command)
            raise errors.InvalidCommandParamsError(msg)
        try:
            self.sync()
        except errors.CommandExecutionError as e:
            LOG.warning('Failed to sync file system buffers: % s', e)
        try:
            _, stderr = utils.execute(command, use_standard_locale=True,
                                      check_exit_code=[0])
            if 'ignoring request.' in stderr:
                LOG.debug('%s command failed with error %s, '
                          'falling back to sysrq-trigger.', command, stderr)
                if command == 'poweroff':
                    utils.execute("echo o > /proc/sysrq-trigger", shell=True)
                elif command == 'reboot':
                    utils.execute("echo b > /proc/sysrq-trigger", shell=True)
        except processutils.ProcessExecutionError as e:
            raise errors.SystemRebootError(e.exit_code, e.stdout, e.stderr)
Пример #8
0
def _get_vmedia_params():
    """This method returns the parameters passed to the agent through virtual
    media floppy.

    :returns: a partial dict of potential agent configuration parameters
    :raises: VirtualMediaBootError when it cannot find the virtual media device
    """
    vmedia_mount_point = "/vmedia_mnt"
    parameters_file = "parameters.txt"

    vmedia_device = _get_vmedia_device()
    if not vmedia_device:
        msg = "Unable to find virtual media device"
        raise errors.VirtualMediaBootError(msg)

    vmedia_device_file = os.path.join("/dev", vmedia_device)
    os.mkdir(vmedia_mount_point)

    try:
        stdout, stderr = utils.execute("mount", vmedia_device_file,
                                       vmedia_mount_point)
    except processutils.ProcessExecutionError as e:
        msg = ("Unable to mount virtual media device %(device)s: %(error)s" %
              {'device': vmedia_device_file, 'error': e})
        raise errors.VirtualMediaBootError(msg)

    parameters_file_path = os.path.join(vmedia_mount_point, parameters_file)
    params = _read_params_from_file(parameters_file_path)

    try:
        stdout, stderr = utils.execute("umount", vmedia_mount_point)
    except processutils.ProcessExecutionError as e:
        pass

    return params
Пример #9
0
def _run_efibootmgr(valid_efi_bootloaders, device, efi_partition):
    """Executes efibootmgr and removes duplicate entries.

    :param valid_efi_bootloaders: the list of valid efi bootloaders
    :param device: the device to be used
    :param efi_partition: the efi partition on the device
    """

    # Before updating let's get information about the bootorder
    LOG.debug("Getting information about boot order")
    utils.execute('efibootmgr')
    # NOTE(iurygregory): regex used to identify the Warning in the stderr after
    # we add the new entry. Example:
    # "efibootmgr: ** Warning ** : Boot0004 has same label ironic"
    duplicated_label = re.compile(r'^.*:\s\*\*.*\*\*\s:\s.*'
                                  r'Boot([0-9a-f-A-F]+)\s.*$')
    label_id = 1
    for v_efi_bl_path in valid_efi_bootloaders:
        # Update the nvram using efibootmgr
        # https://linux.die.net/man/8/efibootmgr
        label = 'ironic' + str(label_id)
        LOG.debug("Adding loader %(path)s on partition %(part)s of device "
                  " %(dev)s", {'path': v_efi_bl_path, 'part': efi_partition,
                               'dev': device})
        cmd = utils.execute('efibootmgr', '-c', '-d', device,
                            '-p', efi_partition, '-w', '-L', label,
                            '-l', v_efi_bl_path)
        for line in cmd[1].split('\n'):
            match = duplicated_label.match(line)
            if match:
                boot_num = match.group(1)
                LOG.debug("Found bootnum %s matching label", boot_num)
                utils.execute('efibootmgr', '-b', boot_num, '-B')
        label_id += 1
Пример #10
0
def _validate_partitioning(device):
    """Validate the final partition table.

    Check if after writing the image to disk we have a valid partition
    table by trying to read it. This will fail if the disk is junk.
    """
    try:
        # Ensure we re-read the partition table before we try to list
        # partitions
        utils.execute('partprobe', device, run_as_root=True,
                      attempts=CONF.disk_utils.partprobe_attempts)
    except (processutils.UnknownArgumentError,
            processutils.ProcessExecutionError, OSError) as e:
        LOG.warning("Unable to probe for partitions on device %(device)s "
                    "after writing the image, the partitioning table may "
                    "be broken. Error: %(error)s",
                    {'device': device, 'error': e})

    try:
        nparts = len(disk_utils.list_partitions(device))
    except (processutils.UnknownArgumentError,
            processutils.ProcessExecutionError, OSError) as e:
        msg = ("Unable to find a valid partition table on the disk after "
               "writing the image. Error {}".format(e))
        raise exception.InstanceDeployFailure(msg)

    # Check if there is at least one partition in the partition table after
    # deploy
    if not nparts:
        msg = ("No partitions found on the device {} after writing "
               "the image.".format(device))
        raise exception.InstanceDeployFailure(msg)
Пример #11
0
    def _shred_block_device(self, node, block_device):
        """Erase a block device using shred.

        :param node: Ironic node info.
        :param block_device: a BlockDevice object to be erased
        :returns: True if the erase succeeds, False if it fails for any reason
        """
        info = node.get('driver_internal_info', {})
        npasses = info.get('agent_erase_devices_iterations', 1)
        args = ('shred', '--force')

        if info.get('agent_erase_devices_zeroize', True):
            args += ('--zero', )

        args += ('--verbose', '--iterations', str(npasses), block_device.name)

        try:
            utils.execute(*args)
        except (processutils.ProcessExecutionError, OSError) as e:
            msg = ("Erasing block device %(dev)s failed with error %(err)s ",
                   {'dev': block_device.name, 'err': e})
            LOG.error(msg)
            return False

        return True
Пример #12
0
    def _ata_erase(self, block_device):
        security_lines = self._get_ata_security_lines(block_device)

        # If secure erase isn't supported return False so erase_block_device
        # can try another mechanism. Below here, if secure erase is supported
        # but fails in some way, error out (operators of hardware that supports
        # secure erase presumably expect this to work).
        if 'supported' not in security_lines:
            return False

        if 'enabled' in security_lines:
            raise errors.BlockDeviceEraseError(
                ('Block device {0} already has '
                 'a security password set').format(block_device.name))

        if 'not frozen' not in security_lines:
            raise errors.BlockDeviceEraseError(
                ('Block device {0} is frozen '
                 'and cannot be erased').format(block_device.name))

        utils.execute('hdparm', '--user-master', 'u', '--security-set-pass',
                      'NULL', block_device.name)
        utils.execute('hdparm', '--user-master', 'u', '--security-erase',
                      'NULL', block_device.name)

        # Verify that security is now 'not enabled'
        security_lines = self._get_ata_security_lines(block_device)
        if 'not enabled' not in security_lines:
            raise errors.BlockDeviceEraseError(
                ('An unknown error occurred '
                 'erasing block device {0}').format(block_device.name))

        return True
 def remove_bootloader(self, node, ports):
     driver_info = node.get('driver_info', {})
     LOG.info('Remove Bootloader called with %s' % driver_info)
     bootdisk = self.get_os_install_device()
     cmd = ['dd', 'if=/dev/zero', 'of=' + bootdisk, 'bs=1M', 'count=1']
     utils.execute(*cmd, check_exit_code=[0])
     return True
Пример #14
0
    def _shred_block_device(self, node, block_device):
        """Erase a block device using shred.

        :param node: Ironic node info.
        :param block_device: a BlockDevice object to be erased
        :returns: True if the erase succeeds, False if it fails for any reason
        """
        info = node.get('driver_internal_info', {})
        npasses = info.get('agent_erase_devices_iterations', 1)
        args = ('shred', '--force')

        if info.get('agent_erase_devices_zeroize', True):
            args += ('--zero', )

        args += ('--verbose', '--iterations', str(npasses), block_device.name)

        try:
            utils.execute(*args)
        except (processutils.ProcessExecutionError, OSError) as e:
            msg = ("Erasing block device %(dev)s failed with error %(err)s ",
                   {'dev': block_device.name, 'err': e})
            LOG.error(msg)
            return False

        return True
Пример #15
0
def setup_ipmi_credentials(resp):
    """Setup IPMI credentials, if requested.

    :param resp: JSON response from inspector.
    """
    if not resp.get("ipmi_setup_credentials"):
        LOG.info("setting IPMI credentials was not requested")
        return

    user, password = resp["ipmi_username"], resp["ipmi_password"]
    LOG.debug("setting IPMI credentials: user %s", user)

    commands = [
        ("user", "set", "name", "2", user),
        ("user", "set", "password", "2", password),
        ("user", "enable", "2"),
        ("channel", "setaccess", "1", "2", "link=on", "ipmi=on", "callin=on", "privilege=4"),
    ]

    for cmd in commands:
        try:
            utils.execute("ipmitool", *cmd)
        except processutils.ProcessExecutionError:
            LOG.exception("failed to update IPMI credentials")
            raise errors.InspectionError("failed to update IPMI credentials")

    LOG.info("successfully set IPMI credentials: user %s", user)
Пример #16
0
def _validate_partitioning(device):
    """Validate the final partition table.

    Check if after writing the image to disk we have a valid partition
    table by trying to read it. This will fail if the disk is junk.
    """
    try:
        # Ensure we re-read the partition table before we try to list
        # partitions
        utils.execute('partprobe', device, run_as_root=True,
                      attempts=CONF.disk_utils.partprobe_attempts)
    except (processutils.UnknownArgumentError,
            processutils.ProcessExecutionError, OSError) as e:
        LOG.warning("Unable to probe for partitions on device %(device)s "
                    "after writing the image, the partitioning table may "
                    "be broken. Error: %(error)s",
                    {'device': device, 'error': e})

    try:
        nparts = len(disk_utils.list_partitions(device))
    except (processutils.UnknownArgumentError,
            processutils.ProcessExecutionError, OSError) as e:
        msg = ("Unable to find a valid partition table on the disk after "
               "writing the image. Error {}".format(e))
        raise exception.InstanceDeployFailure(msg)

    # Check if there is at least one partition in the partition table after
    # deploy
    if not nparts:
        msg = ("No partitions found on the device {} after writing "
               "the image.".format(device))
        raise exception.InstanceDeployFailure(msg)
Пример #17
0
    def get_bmc_address(self):
        # These modules are rarely loaded automatically
        utils.try_execute('modprobe', 'ipmi_msghandler')
        utils.try_execute('modprobe', 'ipmi_devintf')
        utils.try_execute('modprobe', 'ipmi_si')

        try:
            out, _e = utils.execute(
                "ipmitool lan print | grep -e 'IP Address [^S]' "
                "| awk '{ print $4 }'",
                shell=True)
            if out.strip() and out.strip() != '0.0.0.0':
                return out.strip()

        except (processutils.ProcessExecutionError, OSError) as e:
            # Not error, because it's normal in virtual environment
            LOG.warning("Cannot get BMC address: %s", e)

        for channel_id in range(1, 10):
            try:
                out, _e = utils.execute("ipmitool lan print " +
                                        str(channel_id) +
                                        "| grep -e 'IP Address [^S]' "
                                        "| awk '{ print $4 }'",
                                        shell=True)
                if out.strip() and out.strip() != '0.0.0.0':
                    return out.strip()

            except (processutils.ProcessExecutionError, OSError) as e:
                # Not error, because it's normal in virtual environment
                LOG.warning("Cannot get BMC address: %s, channel_id: %d" %
                            (e, channel_id))

        return None
Пример #18
0
def setup_ipmi_credentials(resp):
    """Setup IPMI credentials, if requested.

    :param resp: JSON response from inspector.
    """
    if not resp.get('ipmi_setup_credentials'):
        LOG.info('setting IPMI credentials was not requested')
        return

    user, password = resp['ipmi_username'], resp['ipmi_password']
    LOG.debug('setting IPMI credentials: user %s', user)

    commands = [
        ('user', 'set', 'name', '2', user),
        ('user', 'set', 'password', '2', password),
        ('user', 'enable', '2'),
        ('channel', 'setaccess', '1', '2', 'link=on', 'ipmi=on', 'callin=on',
         'privilege=4'),
    ]

    for cmd in commands:
        try:
            utils.execute('ipmitool', *cmd)
        except processutils.ProcessExecutionError:
            LOG.exception('failed to update IPMI credentials')
            raise errors.InspectionError('failed to update IPMI credentials')

    LOG.info('successfully set IPMI credentials: user %s', user)
Пример #19
0
def main():
    log.register_options(CONF)
    CONF(args=sys.argv[1:])
    log.setup(CONF, 'virtmedia-netconfig')
    LOG.info("Starting virtmedia-netconfig!!")

    params = _read_params_from_file('/proc/cmdline')
    # If the node booted over virtual media, the parameters are passed
    # in a text file within the virtual media floppy.

    if params.get('boot_method') == 'vmedia':
        LOG.debug("Erasing old filesystems")
        utils.execute('/usr/bin/erase-oldfs.sh')

        LOG.info(
            "This node is booted with vmedia. Checking for available virtual media!!"
        )
        wait_for_cd_device()
        check_cd_config()
        vmedia_params = _get_vmedia_params()
        params.update(vmedia_params)
        LOG.debug("vmedia parameters: %r", vmedia_params)
        os_net_config = params.get('os_net_config')
        LOG.info("virtmedia: os_net_config=%s" % os_net_config)
        if os_net_config:
            _configure_static_net(os_net_config)
Пример #20
0
def _mount_for_chroot(path):
    """Mount items for grub-mkconfig to succeed."""
    LOG.debug('Mounting Linux standard partitions for bootloader '
              'configuration generation')
    for fs in BIND_MOUNTS:
        utils.execute('mount', '-o', 'bind', fs, path + fs)
    utils.execute('mount', '-t', 'sysfs', 'none', path + '/sys')
Пример #21
0
 def test_check_exit_code_boolean(self):
     utils.execute('/usr/bin/env', 'false', check_exit_code=False)
     self.assertRaises(processutils.ProcessExecutionError,
                       utils.execute,
                       '/usr/bin/env',
                       'false',
                       check_exit_code=True)
Пример #22
0
def check_cd_config():
    """ This function checks for any extended 64K block in CD.
    If it is available it will extract the contents for the block.
    Loop mount the image for reading configuration parameters.
    """
    inputiso = '/dev/sr0'
    outputtgz = '/tmp/cdconf.tgz'
    mode = os.stat(inputiso).st_mode
    if stat.S_ISBLK(mode):
        filesize = get_file_size(inputiso)
        skip = filesize / 2048 - 32
        ironic_utils.dd(inputiso, outputtgz, 'bs=2k', 'skip=%d' % skip)

        # Check if tgz file is valid.
        try:
            utils.execute("/usr/bin/gzip", '-t', outputtgz)
        except processutils.ProcessExecutionError as err:
            if 'not in gzip format' in err.stderr:
                LOG.info('File is not gzip format skipping!!')
                sys.exit()

        LOG.info('Configuration file in gzip format proceeding for extraction')
        tar = tarfile.open(outputtgz)
        tar.extractall('/tmp/floppy')
        tar.close()

        dir_list = os.listdir('/tmp/floppy')
        for item in dir_list:
            if item.find('.img') != -1:
                os.mkdir('/tmp/floppy/mnt')
                utils.execute("mount", '-o', 'loop', '/tmp/floppy/%s' % item,
                              '/tmp/floppy/mnt')
                time.sleep(1)
Пример #23
0
def setup_ipmi_credentials(resp):
    """Setup IPMI credentials, if requested.

    :param resp: JSON response from inspector.
    """
    if not resp.get('ipmi_setup_credentials'):
        LOG.info('setting IPMI credentials was not requested')
        return

    user, password = resp['ipmi_username'], resp['ipmi_password']
    LOG.debug('setting IPMI credentials: user %s', user)

    commands = [
        ('user', 'set', 'name', '2', user),
        ('user', 'set', 'password', '2', password),
        ('user', 'enable', '2'),
        ('channel', 'setaccess', '1', '2',
         'link=on', 'ipmi=on', 'callin=on', 'privilege=4'),
    ]

    for cmd in commands:
        try:
            utils.execute('ipmitool', *cmd)
        except processutils.ProcessExecutionError:
            LOG.exception('failed to update IPMI credentials')
            raise errors.InspectionError('failed to update IPMI credentials')

    LOG.info('successfully set IPMI credentials: user %s', user)
Пример #24
0
 def test_no_exception_raised_for_execute(self, mock_exec):
     # Make sure we can call utils.execute() even though we didn't mock it.
     # We do mock ironic_lib.utils.execute() so we don't actually execute
     # anything.
     utils.execute("ls")
     utils.execute("echo")
     self.assertEqual(2, mock_exec.call_count)
Пример #25
0
    def test_no_retry_on_success(self):
        fd, tmpfilename = tempfile.mkstemp()
        _, tmpfilename2 = tempfile.mkstemp()
        try:
            fp = os.fdopen(fd, 'w+')
            fp.write('''#!/bin/sh
# If we've already run, bail out.
grep -q foo "$1" && exit 1
# Mark that we've run before.
echo foo > "$1"
# Check that stdin gets passed correctly.
grep foo
''')
            fp.close()
            os.chmod(tmpfilename, 0o755)
            try:
                utils.execute(tmpfilename,
                              tmpfilename2,
                              process_input=b'foo',
                              attempts=2)
            except OSError as e:
                if e.errno == errno.EACCES:
                    self.skipTest("Permissions error detected. "
                                  "Are you running with a noexec /tmp?")
                else:
                    raise
        finally:
            os.unlink(tmpfilename)
            os.unlink(tmpfilename2)
    def test_no_retry_on_success(self):
        fd, tmpfilename = tempfile.mkstemp()
        _, tmpfilename2 = tempfile.mkstemp()
        try:
            fp = os.fdopen(fd, 'w+')
            fp.write('''#!/bin/sh
# If we've already run, bail out.
grep -q foo "$1" && exit 1
# Mark that we've run before.
echo foo > "$1"
# Check that stdin gets passed correctly.
grep foo
''')
            fp.close()
            os.chmod(tmpfilename, 0o755)
            try:
                utils.execute(tmpfilename,
                              tmpfilename2,
                              process_input=b'foo',
                              attempts=2)
            except OSError as e:
                if e.errno == errno.EACCES:
                    self.skipTest("Permissions error detected. "
                                  "Are you running with a noexec /tmp?")
                else:
                    raise
        finally:
            os.unlink(tmpfilename)
            os.unlink(tmpfilename2)
    def update_warpdrive_firmware(self, node, ports):
        driver_info = node.get('driver_info', {})
        LOG.info('Update Warpdrive called with %s' % driver_info)
        devices = self._list_lsi_devices()
        for device in devices:
            # Don't reflash the same firmware
            if device['version'] != LSI_FIRMWARE_VERSION:
                preflash_path = os.path.join(LSI_WARPDRIVE_DIR,
                                             LSI_FIRMWARE_PREFLASH)
                firmware_path = os.path.join(LSI_WARPDRIVE_DIR,
                                             LSI_FIRMWARE_PACKAGE)

                # note(JayF): New firmware requires us to flash a new firmware
                # flasher before flashing the update package
                precmd = [DDOEMCLI, '-c', device['id'], '-f', preflash_path]
                cmd = [DDOEMCLI, '-c', device['id'],
                       '-updatepkg', firmware_path]
                with metrics.instrument_context(
                        __name__, 'upgrade_warpdrive_firmware_preflash'):
                    utils.execute(*precmd, check_exit_code=[0])
                with metrics.instrument_context(
                        __name__, 'upgrade_warpdrive_firmware_package'):
                    utils.execute(*cmd, check_exit_code=[0])
            else:
                LOG.info('Device %(id)s already version %(version)s, '
                         'not upgrading.' % {
                             'id': device['id'],
                             'version': device['version']
                         })
Пример #28
0
def _detect_raid_card():
    cmd = "%s list" % MEGACLI
    try:
        utils.execute(cmd, shell=True)
        # return true if cmd succeeded
        return True
    except Exception:
        return False
Пример #29
0
def _has_dracut(root):
    try:
        utils.execute('chroot %(path)s /bin/sh -c '
                      '"which dracut"' %
                      {'path': root}, shell=True)
    except processutils.ProcessExecutionError:
        return False
    return True
Пример #30
0
    def delete_configuration(self, node, ports):

        LOG.info('Begin to delete configuration')
        cmd = '%s -CfgLdDel -LAll -aAll' % MEGACLI
        report, _e = utils.execute(cmd, shell=True)

        cmd = '%s -CfgForeign -Clear -aAll' % MEGACLI
        report, _e = utils.execute(cmd, shell=True)
        return
Пример #31
0
    def create_configuration(self, node, ports):

        target_raid_config = node.get('target_raid_config', {}).copy()
        target_raid_config_list = target_raid_config['logical_disks']

        LOG.info('Begin to create configuration')
        ld_num = 0
        for vdriver in target_raid_config_list:
            size = 'MAX'
            raid_level = None
            physical_disks = None
            controller = None

            if 'size_gb' in vdriver and vdriver['size_gb'] != 'MAX':
                size = str(vdriver['size_gb'] * 1024)
            if 'raid_level' in vdriver:
                raid_level = vdriver['raid_level']
            if 'physical_disks' in vdriver:
                physical_disks = vdriver['physical_disks']
            if 'controller' in vdriver:
                controller = vdriver['controller']
            LOG.info(('Raid Configuration:[size:%s, '
                      'raid_level:%s, p_disks:%s, controller:%s]'), size,
                     raid_level, physical_disks, controller)
            disklist = " "
            for i in range(0, len(physical_disks)):
                if i == 0:
                    disklist = physical_disks[i]
                else:
                    disklist = disklist + "," + physical_disks[i]

            LOG.info('Raid disk list:[%s]', disklist)

            cmd = ('%s -CfgLdAdd ' % MEGACLI) + '-r' \
                + raid_level + "[" + disklist + "] " + "-a" + controller
            report, _e = utils.execute(cmd, shell=True)

            ld_num1 = report.split('\n')[1].split()[-1]
            cmd1 = ('%s -LDInfo -L' % MEGACLI) + \
                ld_num1 + ' -aAll | grep -i size'
            report1, _e = utils.execute(cmd1, shell=True)
            if report1.split('\n')[0].split(':')[-1].split()[-1] == 'GB':
                ld_size = float(
                    report1.split('\n')[0].split(':')[-1].split()[-2])
            else:
                ld_size = float(
                    report1.split('\n')[0].split(':')[-1].split()[-2]) * 1024
            target_raid_config['logical_disks'][ld_num]['size_gb'] = int(
                ld_size)
            ld_num += 1
            if raid_level is not None and physical_disks \
                    is not None and controller is not None:
                LOG.info('Raid Configuration Command:%s', cmd)
            else:
                LOG.info(('Param Error,No Raid Configuration'
                          ' Command being Created:%s'), cmd)
        return target_raid_config
Пример #32
0
    def create_configuration(self, node, ports):
        target_raid_config = node.get('target_raid_config', {}).copy()
        target_raid_config_list = target_raid_config['logical_disks']

        LOG.info('Begin to create configuration')
        ld_num = 0
        for vdriver in target_raid_config_list:
            size = 'MAX'
            raid_level = None
            physical_disks = None
            controller = 1

            if 'size_gb' in vdriver and vdriver['size_gb'] != 'MAX':
                size = str(vdriver['size_gb'] * 1024)
            if 'raid_level' in vdriver:
                raid_level = vdriver['raid_level']
            if 'physical_disks' in vdriver:
                physical_disks = vdriver['physical_disks']
            if 'controller' in vdriver:
                controller = vdriver['controller']
            LOG.info('Raid Configuration:[size:%(size)s, '
                     'raid_level:%(raid_level)s, '
                     'physical_disks:%(p_disks)s, '
                     'controller:%(controller)s]',
                     {'size': size, 'raid_level': raid_level,
                      'p_disks': physical_disks,
                      'controller': controller})
            disklist = " "
            for i in range(0, len(physical_disks)):
                if i == 0:
                    disklist = physical_disks[i]
                else:
                    disklist = disklist + " " + physical_disks[i]

            cmd = ('%s create ' % ARCCONF) + controller \
                + ' LOGICALDRIVE ' + size + ' ' + raid_level \
                + ' ' + disklist + ' noprompt'
            report, _e = utils.execute(cmd, shell=True)
            ld_num1 = report.split('\n')[2].split()[-1]
            report1, _e = utils.execute(('%s getconfig ' %
                                         ARCCONF + controller
                                         + ' ld ' + ld_num1
                                         + '|grep -i size'), shell=True)
            ld_size = report1.split('\n')[1].split()[-2]
            target_raid_config['logical_disks'][ld_num]['size_gb'] = int(
                int(ld_size) / 1024)
            ld_num += 1
            if raid_level is not None and physical_disks \
                    is not None and controller is not None:
                LOG.info('Raid Configuration Command:%s', cmd)
                LOG.info('System Reaction:%s', report)
            else:
                LOG.info(
                    ('Param Error,No Raid Configuration'
                     ' Command being Created:%s'), cmd)

        return target_raid_config
Пример #33
0
 def test_can_mock_execute(self, mock_exec):
     # NOTE(jlvillal): We had discovered an issue where mocking wasn't
     # working because we had used a mock to block access to the execute
     # functions. This caused us to "mock a mock" and didn't work correctly.
     # We want to make sure that we can mock our execute functions even with
     # our "block execute" code.
     utils.execute("ls")
     utils.execute("echo")
     self.assertEqual(2, mock_exec.call_count)
Пример #34
0
 def test_can_mock_execute(self, mock_exec):
     # NOTE(jlvillal): We had discovered an issue where mocking wasn't
     # working because we had used a mock to block access to the execute
     # functions. This caused us to "mock a mock" and didn't work correctly.
     # We want to make sure that we can mock our execute functions even with
     # our "block execute" code.
     utils.execute("ls")
     utils.execute("echo")
     self.assertEqual(2, mock_exec.call_count)
Пример #35
0
def config_ipmi_info(sn):

    LOG.info('Config ipmi info...')

    if not CONF.arobot_callback_url:
        LOG.info('Config automation is disabled, skipping')
        return

    interval = 5
    index = 1
    while True:
        ipmi_conf = None
        try:
            ipmi_conf = call_arobot(sn)
        except Exception as e:
            LOG.info('Got exception %s', e)
            LOG.info('%s times', index)
            time.sleep(interval)
            index += 1
            continue
        if ipmi_conf is not None and \
                ipmi_conf.get('return_value') == 'NeedConf':
            LOG.info('Got ipmi conf OK! address %s, netmask %s, gateway %s',
                     ipmi_conf.get('ipmi_address'),
                     ipmi_conf.get('ipmi_netmask'),
                     ipmi_conf.get('ipmi_gateway'))
            break
        elif ipmi_conf is not None and \
                ipmi_conf.get('return_value') == 'Success':
            LOG.info('IPMI info already confed!')
            return
        LOG.info('%s times', index)
        time.sleep(interval)
        index += 1

    commands = [
        ('lan', 'set', '1', 'ipsrc', 'static'),
        ('lan', 'set', '1', 'ipaddr', ipmi_conf.get('ipmi_address')),
        ('lan', 'set', '1', 'netmask', ipmi_conf.get('ipmi_netmask')),
        ('lan', 'set', '1', 'defgw', 'ipaddr', ipmi_conf.get('ipmi_gateway')),
        # ('user', 'set', 'name', '5', 'inspur'),
        # ('user', 'set', 'password', '5', 'Czilpjhstcgx4Ru5'),
        # ('user', 'enable', '5'),
        # ('channel', 'setaccess', '1', '5',
        #  'link=on', 'ipmi=on', 'callin=on', 'privilege=4'),
    ]

    for cmd in commands:
        try:
            utils.execute('ipmitool', *cmd)
        except processutils.ProcessExecutionError:
            LOG.exception('failed to update IPMI ip/netmask/gw')
            raise errors.InspectionError('failed to update IPMI ip/netmask/gw')

    tell_arobot_ipmi(sn=sn)
    LOG.info('successfully set IPMI conf!')
Пример #36
0
def create_raid_device(index, logical_disk):
    """Create a raid device.

    :param index: the index of the resulting md device.
    :param logical_disk: the logical disk containing the devices used to
        crete the raid.
    :raise: errors.SoftwareRAIDError if not able to create the raid device
        or fails to re-add a device to a raid.
    """
    md_device = '/dev/md%d' % index
    component_devices = []
    for device in logical_disk['block_devices']:
        # The partition delimiter for all common harddrives (sd[a-z]+)
        part_delimiter = ''
        if 'nvme' in device:
            part_delimiter = 'p'
        component_devices.append(device + part_delimiter +
                                 str(index + RAID_PARTITION))
    raid_level = logical_disk['raid_level']
    # The schema check allows '1+0', but mdadm knows it as '10'.
    if raid_level == '1+0':
        raid_level = '10'
    try:
        LOG.debug("Creating md device %(dev)s on %(comp)s", {
            'dev': md_device,
            'comp': component_devices
        })
        utils.execute('mdadm', '--create', md_device, '--force', '--run',
                      '--metadata=1', '--level', raid_level, '--raid-devices',
                      len(component_devices), *component_devices)
    except processutils.ProcessExecutionError as e:
        msg = "Failed to create md device {} on {}: {}".format(
            md_device, ' '.join(component_devices), e)
        raise errors.SoftwareRAIDError(msg)

    # check for missing devices and re-add them
    actual_components = _get_actual_component_devices(md_device)
    missing = set(component_devices) - set(actual_components)
    for dev in missing:
        try:
            LOG.warning(
                'Found %(device)s to be missing from %(md)s '
                '... re-adding!', {
                    'device': dev,
                    'md': md_device
                })
            utils.execute('mdadm',
                          '--add',
                          md_device,
                          dev,
                          attempts=3,
                          delay_on_retry=True)
        except processutils.ProcessExecutionError as e:
            msg = "Failed re-add {} to {}: {}".format(dev, md_device, e)
            raise errors.SoftwareRAIDError(msg)
Пример #37
0
def _get_partition(device, uuid):
    """Find the partition of a given device."""
    LOG.debug("Find the partition %(uuid)s on device %(dev)s", {
        'dev': device,
        'uuid': uuid
    })

    try:
        # Try to tell the kernel to re-read the partition table
        try:
            utils.execute('partx',
                          '-u',
                          device,
                          attempts=3,
                          delay_on_retry=True)
            utils.execute('udevadm', 'settle')
        except processutils.ProcessExecutionError:
            LOG.warning("Couldn't re-read the partition table "
                        "on device %s", device)

        report = utils.execute('lsblk', '-PbioKNAME,UUID,TYPE', device)[0]
        for line in report.split('\n'):
            part = {}
            # Split into KEY=VAL pairs
            vals = shlex.split(line)
            for key, val in (v.split('=', 1) for v in vals):
                part[key] = val.strip()
            # Ignore non partition
            if part.get('TYPE') != 'part':
                continue

            if part.get('UUID') == uuid:
                LOG.debug("Partition %(uuid)s found on device "
                          "%(dev)s", {
                              'uuid': uuid,
                              'dev': device
                          })
                return '/dev/' + part.get('KNAME')
        else:
            error_msg = ("No partition with UUID %(uuid)s found on "
                         "device %(dev)s" % {
                             'uuid': uuid,
                             'dev': device
                         })
            LOG.error(error_msg)
            raise errors.DeviceNotFound(error_msg)
    except processutils.ProcessExecutionError as e:
        error_msg = ('Finding the partition with UUID %(uuid)s on '
                     'device %(dev)s failed with %(err)s' % {
                         'uuid': uuid,
                         'dev': device,
                         'err': e
                     })
        LOG.error(error_msg)
        raise errors.CommandExecutionError(error_msg)
Пример #38
0
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_lower_case = "/dev/disk/by-label/ir-vfd-dev"
    vmedia_device_file_upper_case = "/dev/disk/by-label/IR-VFD-DEV"
    if os.path.exists(vmedia_device_file_lower_case):
        vmedia_device_file = vmedia_device_file_lower_case
    elif os.path.exists(vmedia_device_file_upper_case):
        vmedia_device_file = vmedia_device_file_upper_case
    else:

        # TODO(rameshg87): This block of code is there only for compatibility
        # reasons (so that newer agent can work with older Ironic). Remove
        # this after Liberty release.
        vmedia_device = utils._get_vmedia_device()
        if not vmedia_device:
            msg = "Unable to find virtual media device"
            raise errors.VirtualMediaBootError(msg)

        vmedia_device_file = os.path.join("/dev", vmedia_device)

    vmedia_mount_point = tempfile.mkdtemp()
    try:
        try:
            stdout, stderr = utils.execute("mount", vmedia_device_file,
                                           vmedia_mount_point)
        except processutils.ProcessExecutionError as e:
            msg = ("Unable to mount virtual media device %(device)s: "
                   "%(error)s" % {
                       'device': vmedia_device_file,
                       'error': e
                   })
            raise errors.VirtualMediaBootError(msg)

        parameters_file_path = os.path.join(vmedia_mount_point,
                                            parameters_file)
        params = _read_params_from_file(parameters_file_path, '\n')

        try:
            stdout, stderr = utils.execute("umount", vmedia_mount_point)
        except processutils.ProcessExecutionError as e:
            pass
    finally:
        try:
            shutil.rmtree(vmedia_mount_point)
        except Exception as e:
            pass

    return params
Пример #39
0
def _rescan_device(device):
    """Force the device to be rescanned

    :param device: device upon which to rescan and update
                   kernel partition records.
    """
    try:
        utils.execute('partx', '-u', device, attempts=3, delay_on_retry=True)
        utils.execute('udevadm', 'settle')
    except processutils.ProcessExecutionError:
        LOG.warning("Couldn't re-read the partition table "
                    "on device %s", device)
Пример #40
0
    def sync(self):
        """Flush file system buffers forcing changed blocks to disk.

        :raises: CommandExecutionError if flushing file system buffers fails.
        """
        LOG.debug('Flushing file system buffers')
        try:
            utils.execute('sync')
        except processutils.ProcessExecutionError as e:
            error_msg = 'Flushing file system buffers failed. Error: %s' % e
            LOG.error(error_msg)
            raise errors.CommandExecutionError(error_msg)
Пример #41
0
def _udev_settle():
    """Wait for the udev event queue to settle.

    Wait for the udev event queue to settle to make sure all devices
    are detected once the machine boots up.

    """
    try:
        utils.execute('udevadm', 'settle')
    except processutils.ProcessExecutionError as e:
        LOG.warning('Something went wrong when waiting for udev '
                    'to settle. Error: %s', e)
        return
Пример #42
0
    def get_bios_given_nic_name(self, interface_name):
        """Collect the BIOS given NICs name.

        This function uses the biosdevname utility to collect the BIOS given
        name of network interfaces.

        The collected data is added to the network interface inventory with an
        extra field named ``biosdevname``.

        :param interface_name: list of names of node's interfaces.
        :return: the BIOS given NIC name of node's interfaces or default
                 as None.
        """
        global WARN_BIOSDEVNAME_NOT_FOUND
        try:
            stdout, _ = utils.execute('biosdevname', '-i',
                                      interface_name)
            return stdout.rstrip('\n')
        except OSError:
            if not WARN_BIOSDEVNAME_NOT_FOUND:
                LOG.warning("Executable 'biosdevname' not found")
                WARN_BIOSDEVNAME_NOT_FOUND = True
        except processutils.ProcessExecutionError as e:
            # NOTE(alezil) biosdevname returns 4 if running in a
            # virtual machine.
            if e.exit_code == 4:
                LOG.info('The system is a virtual machine, so biosdevname '
                         'utility does not provide names for virtual NICs.')
            else:
                LOG.warning('Biosdevname returned exit code %s', e.exit_code)
Пример #43
0
def _write_configdrive_to_partition(configdrive, device):
    filename = _configdrive_location()
    if _configdrive_is_url(configdrive):
        _download_configdrive_to_file(configdrive, filename)
    else:
        _write_configdrive_to_file(configdrive, filename)

    # check configdrive size before writing it
    filesize = os.stat(filename).st_size
    if filesize > (64 * 1024 * 1024):
        raise errors.ConfigDriveTooLargeError(filename, filesize)

    starttime = time.time()
    script = _path_to_script('shell/copy_configdrive_to_disk.sh')
    command = ['/bin/bash', script, filename, device]
    LOG.info('copying configdrive to disk with command {0}'.format(
             ' '.join(command)))

    try:
        stdout, stderr = utils.execute(*command, check_exit_code=[0])
    except processutils.ProcessExecutionError as e:
        raise errors.ConfigDriveWriteError(device,
                                           e.exit_code,
                                           e.stdout,
                                           e.stderr)

    totaltime = time.time() - starttime
    LOG.info('configdrive copied from {0} to {1} in {2} seconds'.format(
             configdrive,
             device,
             totaltime))
Пример #44
0
    def _shred_block_device(self, block_device):
        """Erase a block device using shred.

        :param block_device: a BlockDevice object to be erased
        :returns: True if the erase succeeds, False if it fails for any reason
        """
        try:
            utils.execute('shred', '--force', '--zero', '--verbose',
                          '--iterations', '1', block_device.name)
        except (processutils.ProcessExecutionError, OSError) as e:
            msg = ("Erasing block device %(dev)s failed with error %(err)s ",
                  {'dev': block_device.name, 'err': e})
            LOG.error(msg)
            return False

        return True
Пример #45
0
    def list_block_devices(self):
        """List all physical block devices

        The switches we use for lsblk: P for KEY="value" output,
        b for size output in bytes, d to exclude dependant devices
        (like md or dm devices), i to ensure ascii characters only,
        and  o to specify the fields we need

        :return: A list of BlockDevices
        """
        report = utils.execute('lsblk', '-PbdioKNAME,MODEL,SIZE,ROTA,TYPE',
                               check_exit_code=[0])[0]
        lines = report.split('\n')

        devices = []
        for line in lines:
            device = {}
            # Split into KEY=VAL pairs
            vals = shlex.split(line)
            for key, val in (v.split('=', 1) for v in vals):
                device[key] = val.strip()
            # Ignore non disk
            if device.get('TYPE') != 'disk':
                continue

            # Ensure all required keys are at least present, even if blank
            diff = set(['KNAME', 'MODEL', 'SIZE', 'ROTA']) - set(device.keys())
            if diff:
                raise errors.BlockDeviceError(
                    '%s must be returned by lsblk.' % diff)
            devices.append(BlockDevice(name='/dev/' + device['KNAME'],
                                       model=device['MODEL'],
                                       size=int(device['SIZE']),
                                       rotational=bool(int(device['ROTA']))))
        return devices
Пример #46
0
    def get_memory(self):
        # psutil returns a long, so we force it to an int
        if psutil.version_info[0] == 1:
            total = int(psutil.TOTAL_PHYMEM)
        elif psutil.version_info[0] == 2:
            total = int(psutil.phymem_usage().total)

        try:
            out, _e = utils.execute("dmidecode --type memory | grep Size",
                                    shell=True)
        except (processutils.ProcessExecutionError, OSError) as e:
            LOG.warning("Cannot get real physical memory size: %s", e)
            physical = None
        else:
            physical = 0
            for line in out.strip().split('\n'):
                line = line.strip()
                if not line:
                    continue

                try:
                    value = line.split(None, 1)[1].strip()
                    physical += int(UNIT_CONVERTER(value).to_base_units())
                except Exception as exc:
                    LOG.error('Cannot parse size expression %s: %s',
                              line, exc)

            if not physical:
                LOG.warning('failed to get real physical RAM, dmidecode '
                            'returned %s', out)

        return Memory(total=total, physical_mb=physical)
Пример #47
0
def _execute(cmd, error_msg, **kwargs):
    try:
        stdout, stderr = utils.execute(*cmd, **kwargs)
    except processutils.ProcessExecutionError as e:
        LOG.error(error_msg)
        raise errors.ISCSICommandError(error_msg, e.exit_code,
                                       e.stdout, e.stderr)
Пример #48
0
def collect_extra_hardware(data, failures):
    """Collect detailed inventory using 'hardware-detect' utility.

    Recognizes ipa-inspection-benchmarks with list of benchmarks (possible
    values are cpu, disk, mem) to run. No benchmarks are run by default, as
    they're pretty time-consuming.

    Puts collected data as JSON under 'data' key.
    Requires 'hardware' python package to be installed on the ramdisk in
    addition to the packages in requirements.txt.

    :param data: mutable data that we'll send to inspector
    :param failures: AccumulatedFailures object
    """
    benchmarks = utils.get_agent_params().get("ipa-inspection-benchmarks", [])
    if benchmarks:
        benchmarks = ["--benchmark"] + benchmarks.split(",")

    try:
        out, err = utils.execute("hardware-detect", *benchmarks)
    except (processutils.ProcessExecutionError, OSError) as exc:
        failures.add("failed to run hardware-detect utility: %s", exc)
        return

    try:
        data["data"] = json.loads(out)
    except ValueError as exc:
        msg = "JSON returned from hardware-detect cannot be decoded: %s"
        failures.add(msg, exc)
Пример #49
0
def collect_logs(data, failures):
    """Collect journald logs from the ramdisk.

    As inspection runs before any nodes details are known, it's handy to have
    logs returned with data. This collector sends logs to inspector in format
    expected by the 'ramdisk_error' plugin: base64 encoded tar.gz.

    This collector should be installed last in the collector chain, otherwise
    it won't collect enough logs.

    This collector does not report failures.

    :param data: mutable data that we'll send to inspector
    :param failures: AccumulatedFailures object
    """
    try:
        out, _e = utils.execute("journalctl", "--full", "--no-pager", "-b", "-n", "10000")
    except (processutils.ProcessExecutionError, OSError):
        LOG.warn("failed to get system journal")
        return

    journal = io.BytesIO(out.encode("utf-8"))
    with io.BytesIO() as fp:
        with tarfile.open(fileobj=fp, mode="w:gz") as tar:
            tarinfo = tarfile.TarInfo("journal")
            tarinfo.size = len(out)
            tar.addfile(tarinfo, journal)

        fp.seek(0)
        data["logs"] = base64.b64encode(fp.getvalue())
Пример #50
0
def collect_logs(data, failures):
    """Collect journald logs from the ramdisk.

    As inspection runs before any nodes details are known, it's handy to have
    logs returned with data. This collector sends logs to inspector in format
    expected by the 'ramdisk_error' plugin: base64 encoded tar.gz.

    This collector should be installed last in the collector chain, otherwise
    it won't collect enough logs.

    This collector does not report failures.

    :param data: mutable data that we'll send to inspector
    :param failures: AccumulatedFailures object
    """
    try:
        out, _e = utils.execute('journalctl', '--full', '--no-pager', '-b',
                                '-n', '10000', binary=True,
                                log_stdout=False)
    except (processutils.ProcessExecutionError, OSError):
        LOG.warning('failed to get system journal')
        return

    journal = io.BytesIO(bytes(out))
    with io.BytesIO() as fp:
        with tarfile.open(fileobj=fp, mode='w:gz') as tar:
            tarinfo = tarfile.TarInfo('journal')
            tarinfo.size = len(out)
            tarinfo.mtime = time.time()
            tar.addfile(tarinfo, journal)

        fp.seek(0)
        data['logs'] = base64.b64encode(fp.getvalue())
Пример #51
0
    def get_cpus(self):
        lines = utils.execute('lscpu')[0]
        cpu_info = {k.strip().lower(): v.strip() for k, v in
                    (line.split(':', 1)
                     for line in lines.split('\n')
                     if line.strip())}
        # Current CPU frequency can be different from maximum one on modern
        # processors
        freq = cpu_info.get('cpu max mhz', cpu_info.get('cpu mhz'))

        flags = []
        out = utils.try_execute('grep', '-Em1', '^flags', '/proc/cpuinfo')
        if out:
            try:
                # Example output (much longer for a real system):
                # flags           : fpu vme de pse
                flags = out[0].strip().split(':', 1)[1].strip().split()
            except (IndexError, ValueError):
                LOG.warning('Malformed CPU flags information: %s', out)
        else:
            LOG.warning('Failed to get CPU flags')

        return CPU(model_name=cpu_info.get('model name'),
                   frequency=freq,
                   # this includes hyperthreading cores
                   count=int(cpu_info.get('cpu(s)')),
                   architecture=cpu_info.get('architecture'),
                   flags=flags)
Пример #52
0
def _get_partition(device, uuid):
    """Find the partition of a given device."""
    LOG.debug("Find the partition %(uuid)s on device %(dev)s",
              {'dev': device, 'uuid': uuid})

    try:
        # Try to tell the kernel to re-read the partition table
        try:
            utils.execute('partx', '-u', device, attempts=3,
                          delay_on_retry=True)
            utils.execute('udevadm', 'settle')
        except processutils.ProcessExecutionError:
            LOG.warning("Couldn't re-read the partition table "
                        "on device %s", device)

        lsblk = utils.execute('lsblk', '-PbioKNAME,UUID,PARTUUID,TYPE', device)
        report = lsblk[0]
        for line in report.split('\n'):
            part = {}
            # Split into KEY=VAL pairs
            vals = shlex.split(line)
            for key, val in (v.split('=', 1) for v in vals):
                part[key] = val.strip()
            # Ignore non partition
            if part.get('TYPE') != 'part':
                continue

            if part.get('UUID') == uuid:
                LOG.debug("Partition %(uuid)s found on device "
                          "%(dev)s", {'uuid': uuid, 'dev': device})
                return '/dev/' + part.get('KNAME')
            if part.get('PARTUUID') == uuid:
                LOG.debug("Partition %(uuid)s found on device "
                          "%(dev)s", {'uuid': uuid, 'dev': device})
                return '/dev/' + part.get('KNAME')
        else:
            error_msg = ("No partition with UUID %(uuid)s found on "
                         "device %(dev)s" % {'uuid': uuid, 'dev': device})
            LOG.error(error_msg)
            raise errors.DeviceNotFound(error_msg)
    except processutils.ProcessExecutionError as e:
        error_msg = ('Finding the partition with UUID %(uuid)s on '
                     'device %(dev)s failed with %(err)s' %
                     {'uuid': uuid, 'dev': device, 'err': e})
        LOG.error(error_msg)
        raise errors.CommandExecutionError(error_msg)
Пример #53
0
 def _run_shutdown_script(self, parameter):
     script = _path_to_script("shell/shutdown.sh")
     command = ["/bin/bash", script, parameter]
     # this should never return if successful
     try:
         stdout, stderr = utils.execute(*command, check_exit_code=[0])
     except processutils.ProcessExecutionError as e:
         raise errors.SystemRebootError(e.exit_code, e.stdout, e.stderr)
Пример #54
0
def _execute(cmd, error_msg, check_exit_code=None):
    if check_exit_code is None:
        check_exit_code = [0]

    try:
        stdout, stderr = utils.execute(*cmd, check_exit_code=check_exit_code)
    except processutils.ProcessExecutionError as e:
        LOG.error(error_msg)
        raise errors.ISCSIError(error_msg, e.exit_code, e.stdout, e.stderr)
Пример #55
0
 def run_image(self):
     script = _path_to_script('shell/reboot.sh')
     LOG.info('Rebooting system')
     command = ['/bin/bash', script]
     # this should never return if successful
     try:
         stdout, stderr = utils.execute(*command, check_exit_code=[0])
     except processutils.ProcessExecutionError as e:
         raise errors.SystemRebootError(e.exit_code, e.stdout, e.stderr)
    def _get_warpdrive_attributes(self, block_device):
        device = self._get_warpdrive_card(block_device)
        result = utils.execute(DDOEMCLI, '-c', device['id'], '-health')
        attributes = {}
        attrkey = None
        # note(JayF): What we really get here is SMART data for the 4 SSDs
        # behind the Warpdrive card. Split them up to parse separately.
        for idx, lines in enumerate(result[0].split('SSD Drive SMART')):
            # note(JayF): The first entry is headers, throw it away
            if idx == 0:
                continue
            it = iter(lines.split('\n'))
            for line in it:
                line = line.strip()
                if not line:
                    continue
                if line.startswith('Data Slot #'):
                    # note(JayF): Get the drive number and serial. The full
                    # line is actually "SSD Drive SMART Data Slot #" but by
                    # splitting on it above we lose the first three words.
                    drivenum = line.split()[3][0]
                    driveserial = line.split()[7]
                    attrkey = drivenum + '_' + driveserial
                    attributes[attrkey] = {}
                # note(JayF): Once we know what drive this is, skip past the
                # current metrics (which are only for a power cycle), to put
                # the iterator in the right place for starting to grab k:v
                # pairs below
                if line.startswith('-------------- Cumulative'):
                    break

            for line in it:
                line = line.strip()
                # note(JayF): It doesn't make sense to store time in graphite
                if not line or line.endswith('(Hours:Minutes:Seconds)'):
                    continue
                # note(JayF): This is the first line of the footer. If we get
                # here, we're done parsing.
                if line.startswith('Warranty Remaining'):
                    break
                # note(JayF): Some of the metrics have units or notes in
                # parens, we look for these and adjust our rsplit accordingly
                if line.endswith('(degree C)'):
                    key = line.rsplit(None, 3)[0].replace(" ", "")
                    value = line.rsplit(None, 3)[1]
                elif (line.endswith('(Gigabytes)')
                       or line.endswith('(%)')):
                    key = line.rsplit(None, 2)[0].replace(" ", "")
                    value = line.rsplit(None, 2)[1]
                else:
                    key = line.rsplit(None, 1)[0].replace(" ", "")
                    value = line.rsplit(None, 1)[1]
                # note(JayF): Ensure all characters are safe for graphite
                key = re.sub(r'[\(\)/\\]', '_', key)
                attributes[attrkey][key] = re.sub(r'[\(\)/\\]', '_', value)

        return attributes
Пример #57
0
def _check_for_iscsi():
    """Connect iSCSI shared connected via iBFT or OF.

    iscsistart -f will print the iBFT or OF info.
    In case such connection exists, we would like to issue
    iscsistart -b to create a session to the target.
    - If no connection is detected we simply return.
    """
    try:
        utils.execute('iscsistart', '-f')
    except (processutils.ProcessExecutionError, EnvironmentError) as e:
        LOG.debug("No iscsi connection detected. Skipping iscsi. "
                  "Error: %s", e)
        return
    try:
        utils.execute('iscsistart', '-b')
    except processutils.ProcessExecutionError as e:
        LOG.warning("Something went wrong executing 'iscsistart -b' "
                    "Error: %s", e)