Exemplo n.º 1
0
    def get_interface_info(self, interface_name):
        """Return the interface information when its Mellanox and InfiniBand

        In case of Mellanox and InfiniBand interface we do the following:
            1. Calculate the "InfiniBand  MAC" according to InfiniBand GUID
            2. Calculate the client-id according to InfiniBand GUID
        """

        address = netutils.get_mac_addr(interface_name)
        if address is None:
            raise errors.IncompatibleHardwareMethodError()
        vendor = hardware._get_device_info(interface_name, 'net', 'vendor')
        if (len(address) != netutils.INFINIBAND_ADDR_LEN
                or vendor != MLNX_VENDOR_ID):
            raise errors.IncompatibleHardwareMethodError()

        mac_addr = _infiniband_address_to_mac(address)
        client_id = _generate_client_id(address)

        return hardware.NetworkInterface(
            interface_name, mac_addr,
            ipv4_address=netutils.get_ipv4_addr(interface_name),
            has_carrier=netutils.interface_has_carrier(interface_name),
            lldp=None,
            vendor=vendor,
            product=hardware._get_device_info(interface_name, 'net', 'device'),
            client_id=client_id)
Exemplo n.º 2
0
def _detect_hardware():
    """method for detection of Mellanox NICs

    :returns: Boolean value. True if the machine contain one
              or more Mellanox NIC(s), False otherwise.
    """
    iface_names = os.listdir('/sys/class/net')
    for ifname in iface_names:
        if (hardware._get_device_info(
                ifname, 'net', 'vendor') == MLNX_VENDOR_ID):
            return True
    return False
def list_all_block_devices(block_type='disk', ignore_raid=False):
    """List all physical block devices

    The switches we use for lsblk: P for KEY="value" output, b for size output
    in bytes, i to ensure ascii characters only, and o to specify the
    fields/columns we need.

    Broken out as its own function to facilitate custom hardware managers that
    don't need to subclass GenericHardwareManager.

    :param block_type: Type of block device to find
    :param ignore_raid: Ignore auto-identified raid devices, example: md0
                        Defaults to false as these are generally disk
                        devices and should be treated as such if encountered.
    :return: A list of BlockDevices
    """
    hardware._udev_settle()

    # map device names to /dev/disk/by-path symbolic links that points to it

    by_path_mapping = {}

    disk_by_path_dir = '/dev/disk/by-path'

    try:
        paths = os.listdir(disk_by_path_dir)

        for path in paths:
            path = os.path.join(disk_by_path_dir, path)
            # Turn possibly relative symbolic link into absolute
            devname = os.path.join(disk_by_path_dir, os.readlink(path))
            devname = os.path.abspath(devname)
            by_path_mapping[devname] = path

    except OSError as e:
        # NOTE(TheJulia): This is for multipath detection, and will raise
        # some warning logs with unrelated tests.
        LOG.warning(
            "Path %(path)s is inaccessible, /dev/disk/by-path/* "
            "version of block device name is unavailable "
            "Cause: %(error)s", {
                'path': disk_by_path_dir,
                'error': e
            })

    columns = ['KNAME', 'MODEL', 'SIZE', 'ROTA', 'TYPE']
    report = utils.execute('lsblk',
                           '-Pbi',
                           '-o{}'.format(','.join(columns)),
                           check_exit_code=[0])[0]
    # lines = report.split('\n')
    lines = report.splitlines()
    lines = list(set(lines))
    context = pyudev.Context()

    LOG.debug("list_block_devices(): found {}".format(lines))

    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 block types not specified
        devtype = device.get('TYPE')
        # Search for raid in the reply type, as RAID is a
        # disk device, and we should honor it if is present.
        # Other possible type values, which we skip recording:
        #   lvm, part, rom, loop
        if devtype != block_type:
            if devtype is not None and 'raid' in devtype and not ignore_raid:
                LOG.info("TYPE detected to contain 'raid', signifying a RAID "
                         "volume. Found: {!r}".format(line))
            else:
                LOG.info(
                    "TYPE did not match. Wanted: {!r} but found: {!r}".format(
                        block_type, line))
                continue

        # Ensure all required columns are at least present, even if blank
        missing = set(columns) - set(device)
        if missing:
            raise errors.BlockDeviceError('%s must be returned by lsblk.' %
                                          ', '.join(sorted(missing)))

        name = os.path.join('/dev', device['KNAME'])

        try:
            udev = pyudev.Device.from_device_file(context, name)
        # pyudev started raising another error in 0.18
        except (ValueError, EnvironmentError, pyudev.DeviceNotFoundError) as e:
            LOG.warning(
                "Device %(dev)s is inaccessible, skipping... "
                "Error: %(error)s", {
                    'dev': name,
                    'error': e
                })
            extra = {}
        else:
            # TODO(lucasagomes): Since lsblk only supports
            # returning the short serial we are using
            # ID_SERIAL_SHORT here to keep compatibility with the
            # bash deploy ramdisk
            extra = {
                key: udev.get('ID_%s' % udev_key)
                for key, udev_key in [('wwn', 'WWN'), (
                    'serial', 'SERIAL_SHORT'
                ), ('wwn_with_extension', 'WWN_WITH_EXTENSION'
                    ), ('wwn_vendor_extension', 'WWN_VENDOR_EXTENSION')]
            }

        # NOTE(lucasagomes): Newer versions of the lsblk tool supports
        # HCTL as a parameter but let's get it from sysfs to avoid breaking
        # old distros.
        try:
            extra['hctl'] = os.listdir('/sys/block/%s/device/scsi_device' %
                                       device['KNAME'])[0]
        except (OSError, IndexError):
            LOG.warning(
                'Could not find the SCSI address (HCTL) for '
                'device %s. Skipping', name)

        # Not all /dev entries are pointed to from /dev/disk/by-path
        by_path_name = by_path_mapping.get(name)

        devices.append(
            hardware.BlockDevice(name=name,
                                 model=device['MODEL'],
                                 size=int(device['SIZE']),
                                 rotational=bool(int(device['ROTA'])),
                                 vendor=hardware._get_device_info(
                                     device['KNAME'], 'block', 'vendor'),
                                 by_path=by_path_name,
                                 **extra))

    return devices