Ejemplo n.º 1
0
 def _test_guess_root_disk(self, size=8, device_name='/dev/vda'):
     devices = [
         hardware.BlockDevice(name='/dev/sdd',
                              model='NWD-BLP4-1600',
                              size=207374182400,
                              rotational=False,
                              vendor='Super Vendor',
                              hctl='1:0:0:0'),
         hardware.BlockDevice(name='/dev/sda',
                              model='TinyUSB Drive',
                              size=3116853504,
                              rotational=False,
                              vendor='Super Vendor',
                              hctl='1:0:0:0'),
         hardware.BlockDevice(name='/dev/sdc',
                              model='NWD-BLP4-1600',
                              size=107374182400,
                              rotational=False,
                              vendor='Super Vendor',
                              hctl='1:0:0:0'),
         hardware.BlockDevice(name='/dev/sdb',
                              model='Fastable SD131 7',
                              size=107374182400,
                              rotational=False,
                              vendor='Super Vendor',
                              hctl='1:0:0:0'),
     ]
     require_device_name = device_name
     device = utils.guess_root_disk(devices, size * units.Gi)
     self.assertEqual(device.name, require_device_name)
Ejemplo n.º 2
0
 def _wait_for_disks(self):
     # Wait for at least one suitable disk to show up, otherwise neither
     # inspection not deployment have any chances to succeed.
     for attempt in range(_DISK_WAIT_ATTEMPTS):
         try:
             block_devices = self.list_block_devices()
             utils.guess_root_disk(block_devices)
         except errors.DeviceNotFound:
             LOG.debug('Still waiting for at least one disk to appear, '
                       'attempt %d of %d', attempt + 1, _DISK_WAIT_ATTEMPTS)
             time.sleep(_DISK_WAIT_DELAY)
         else:
             break
     else:
         LOG.warning('No disks detected in %d seconds',
                     _DISK_WAIT_DELAY * _DISK_WAIT_ATTEMPTS)
Ejemplo n.º 3
0
def collect_default(data, failures):
    """The default inspection collector.

    This is the only collector that is called by default. It collects
    the whole inventory as returned by the hardware manager(s).

    It also tries to get BMC address, PXE boot device and the expected
    root device.

    :param data: mutable data that we'll send to inspector
    :param failures: AccumulatedFailures object
    """
    wait_for_dhcp()
    inventory = hardware.list_hardware_info()

    data['inventory'] = inventory
    # Replicate the same logic as in deploy. We need to make sure that when
    # root device hints are not set, inspector will use the same root disk as
    # will be used for deploy.
    try:
        root_disk = utils.guess_root_disk(inventory['disks'][:])
    except errors.DeviceNotFound:
        root_disk = None
        LOG.warning('no suitable root device detected')
    else:
        data['root_disk'] = root_disk
        LOG.debug('default root device is %s', root_disk.name)
    # The boot interface might not be present, we don't count it as failure.
    # TODO(dtantsur): stop using the boot_interface field.
    data['boot_interface'] = inventory['boot'].pxe_interface
    LOG.debug('boot devices was %s', data['boot_interface'])
    LOG.debug('BMC IP address: %s', inventory.get('bmc_address'))
Ejemplo n.º 4
0
def collect_default(data, failures):
    """The default inspection collector.

    This is the only collector that is called by default. It collects
    the whole inventory as returned by the hardware manager(s).

    It also tries to get BMC address, PXE boot device and the expected
    root device.

    :param data: mutable data that we'll send to inspector
    :param failures: AccumulatedFailures object
    """
    wait_for_dhcp()
    inventory = hardware.dispatch_to_managers('list_hardware_info')

    data['inventory'] = inventory
    # Replicate the same logic as in deploy. We need to make sure that when
    # root device hints are not set, inspector will use the same root disk as
    # will be used for deploy.
    try:
        root_disk = utils.guess_root_disk(inventory['disks'][:])
    except errors.DeviceNotFound:
        root_disk = None
        LOG.warning('no suitable root device detected')
    else:
        data['root_disk'] = root_disk
        LOG.debug('default root device is %s', root_disk.name)
    # The boot interface might not be present, we don't count it as failure.
    # TODO(dtantsur): stop using the boot_interface field.
    data['boot_interface'] = inventory['boot'].pxe_interface
    LOG.debug('boot devices was %s', data['boot_interface'])
    LOG.debug('BMC IP address: %s', inventory.get('bmc_address'))
Ejemplo n.º 5
0
 def _wait_for_disks(self):
     # Wait for at least one suitable disk to show up, otherwise neither
     # inspection not deployment have any chances to succeed.
     for attempt in range(_DISK_WAIT_ATTEMPTS):
         try:
             block_devices = self.list_block_devices()
             utils.guess_root_disk(block_devices)
         except errors.DeviceNotFound:
             LOG.debug('Still waiting for at least one disk to appear, '
                       'attempt %d of %d', attempt + 1, _DISK_WAIT_ATTEMPTS)
             time.sleep(_DISK_WAIT_DELAY)
         else:
             break
     else:
         LOG.warning('No disks detected in %d seconds',
                     _DISK_WAIT_DELAY * _DISK_WAIT_ATTEMPTS)
Ejemplo n.º 6
0
    def get_os_install_device(self):
        cached_node = get_cached_node()
        root_device_hints = None
        if cached_node is not None:
            root_device_hints = cached_node['properties'].get('root_device')

        block_devices = self.list_block_devices()
        if not root_device_hints:
            return utils.guess_root_disk(block_devices).name
        else:
            serialized_devs = [dev.serialize() for dev in block_devices]
            try:
                device = il_utils.match_root_device_hints(serialized_devs,
                                                          root_device_hints)
            except ValueError as e:
                # NOTE(lucasagomes): Just playing on the safe side
                # here, this exception should never be raised because
                # Ironic should validate the root device hints before the
                # deployment starts.
                raise errors.DeviceNotFound(
                    'No devices could be found using the root device hints '
                    '%(hints)s because they failed to validate. Error: '
                    '%(error)s' % {'hints': root_device_hints, 'error': e})

            if not device:
                raise errors.DeviceNotFound(
                    "No suitable device was found for "
                    "deployment using these hints %s" % root_device_hints)

            return device['name']
Ejemplo n.º 7
0
    def get_os_install_device(self):
        cached_node = get_cached_node()
        root_device_hints = None
        if cached_node is not None:
            root_device_hints = cached_node['properties'].get('root_device')

        block_devices = self.list_block_devices()
        if not root_device_hints:
            return utils.guess_root_disk(block_devices).name
        else:

            def match(hint, current_value, device):
                hint_value = root_device_hints[hint]
                if hint_value != current_value:
                    LOG.debug(
                        "Root device hint %(hint)s=%(value)s does not "
                        "match the device %(device)s value of "
                        "%(current)s", {
                            'hint': hint,
                            'value': hint_value,
                            'device': device,
                            'current': current_value
                        })
                    return False
                return True

            def check_device_attrs(device):
                for key in ('model', 'wwn', 'serial', 'vendor',
                            'wwn_with_extension', 'wwn_vendor_extension',
                            'name'):
                    if key not in root_device_hints:
                        continue

                    value = getattr(device, key)
                    if not value:
                        return False
                    value = utils.normalize(value)
                    if not match(key, value, device.name):
                        return False

                return True

            for dev in block_devices:
                # TODO(lucasagomes): Add support for operators <, >, =, etc...
                # to better deal with sizes.
                if 'size' in root_device_hints:
                    # Since we don't support units yet we expect the size
                    # in GiB for now
                    size = dev.size / units.Gi
                    if not match('size', size, dev.name):
                        continue

                if check_device_attrs(dev):
                    return dev.name

            else:
                raise errors.DeviceNotFound("No suitable device was found for "
                                            "deployment using these hints %s" %
                                            root_device_hints)
Ejemplo n.º 8
0
    def get_os_install_device(self):
        cached_node = get_cached_node()
        root_device_hints = None
        if cached_node is not None:
            root_device_hints = cached_node['properties'].get('root_device')

        block_devices = self.list_block_devices()
        if not root_device_hints:
            return utils.guess_root_disk(block_devices).name
        else:

            def match(hint, current_value, device):
                hint_value = root_device_hints[hint]
                if hint_value != current_value:
                    LOG.debug("Root device hint %(hint)s=%(value)s does not "
                              "match the device %(device)s value of "
                              "%(current)s", {
                                  'hint': hint,
                                  'value': hint_value, 'device': device,
                                  'current': current_value})
                    return False
                return True

            def check_device_attrs(device):
                for key in ('model', 'wwn', 'serial', 'vendor',
                            'wwn_with_extension', 'wwn_vendor_extension',
                            'name'):
                    if key not in root_device_hints:
                        continue

                    value = getattr(device, key)
                    if not value:
                        return False
                    value = utils.normalize(value)
                    if not match(key, value, device.name):
                        return False

                return True

            for dev in block_devices:
                # TODO(lucasagomes): Add support for operators <, >, =, etc...
                # to better deal with sizes.
                if 'size' in root_device_hints:
                    # Since we don't support units yet we expect the size
                    # in GiB for now
                    size = dev.size / units.Gi
                    if not match('size', size, dev.name):
                        continue

                if check_device_attrs(dev):
                    return dev.name

            else:
                raise errors.DeviceNotFound(
                    "No suitable device was found for "
                    "deployment using these hints %s" % root_device_hints)
Ejemplo n.º 9
0
    def _wait_for_disks(self):
        """Wait for disk to appear

        Wait for at least one suitable disk to show up, otherwise neither
        inspection not deployment have any chances to succeed.

        """

        for attempt in range(CONF.disk_wait_attempts):
            try:
                block_devices = self.list_block_devices()
                utils.guess_root_disk(block_devices)
            except errors.DeviceNotFound:
                LOG.debug('Still waiting for at least one disk to appear, '
                          'attempt %d of %d', attempt + 1,
                          CONF.disk_wait_attempts)
                time.sleep(CONF.disk_wait_delay)
            else:
                break
        else:
            LOG.warning('No disks detected in %d seconds',
                        CONF.disk_wait_delay * CONF.disk_wait_attempts)
Ejemplo n.º 10
0
    def _wait_for_disks(self):
        """Wait for disk to appear

        Wait for at least one suitable disk to show up, otherwise neither
        inspection not deployment have any chances to succeed.

        """

        for attempt in range(CONF.disk_wait_attempts):
            try:
                block_devices = self.list_block_devices()
                utils.guess_root_disk(block_devices)
            except errors.DeviceNotFound:
                LOG.debug('Still waiting for at least one disk to appear, '
                          'attempt %d of %d', attempt + 1,
                          CONF.disk_wait_attempts)
                time.sleep(CONF.disk_wait_delay)
            else:
                break
        else:
            LOG.warning('No disks detected in %d seconds',
                        CONF.disk_wait_delay * CONF.disk_wait_attempts)
Ejemplo n.º 11
0
def collect_default(data, failures):
    """The default inspection collector.

    This is the only collector that is called by default. It is designed to be
    both backward and future compatible:
        1. it collects exactly the same data as the old bash-based ramdisk
        2. it also posts the whole inventory which we'll eventually use.

    In both cases it tries to get BMC address, PXE boot device and the expected
    root device.

    :param data: mutable data that we'll send to inspector
    :param failures: AccumulatedFailures object
    """
    wait_for_dhcp()
    inventory = hardware.dispatch_to_managers('list_hardware_info')

    # In the future we will only need the current version of inventory,
    # a guessed root disk, PXE boot interface and IPMI address.
    # Everything else will be done by inspector itself and its plugins.
    data['inventory'] = inventory
    # Replicate the same logic as in deploy. We need to make sure that when
    # root device hints are not set, inspector will use the same root disk as
    # will be used for deploy.
    try:
        root_disk = utils.guess_root_disk(inventory['disks'][:])
    except errors.DeviceNotFound:
        root_disk = None
        LOG.warning('no suitable root device detected')
    else:
        data['root_disk'] = root_disk
        LOG.debug('default root device is %s', root_disk.name)
    # Both boot interface and IPMI address might not be present,
    # we don't count it as failure
    data['boot_interface'] = inventory['boot'].pxe_interface
    LOG.debug('boot devices was %s', data['boot_interface'])
    data['ipmi_address'] = inventory.get('bmc_address')
    LOG.debug('BMC IP address: %s', data['ipmi_address'])

    # These 2 calls are required for backward compatibility and should be
    # dropped after inspector is ready (probably in Mitaka cycle).
    discover_network_properties(inventory, data, failures)
    discover_scheduling_properties(inventory, data, root_disk)
Ejemplo n.º 12
0
def collect_default(data, failures):
    """The default inspection collector.

    This is the only collector that is called by default. It is designed to be
    both backward and future compatible:
        1. it collects exactly the same data as the old bash-based ramdisk
        2. it also posts the whole inventory which we'll eventually use.

    In both cases it tries to get BMC address, PXE boot device and the expected
    root device.

    :param data: mutable data that we'll send to inspector
    :param failures: AccumulatedFailures object
    """
    wait_for_dhcp()
    inventory = hardware.dispatch_to_managers('list_hardware_info')

    # In the future we will only need the current version of inventory,
    # a guessed root disk, PXE boot interface and IPMI address.
    # Everything else will be done by inspector itself and its plugins.
    data['inventory'] = inventory
    # Replicate the same logic as in deploy. We need to make sure that when
    # root device hints are not set, inspector will use the same root disk as
    # will be used for deploy.
    try:
        root_disk = utils.guess_root_disk(inventory['disks'][:])
    except errors.DeviceNotFound:
        root_disk = None
        LOG.warning('no suitable root device detected')
    else:
        data['root_disk'] = root_disk
        LOG.debug('default root device is %s', root_disk.name)
    # Both boot interface and IPMI address might not be present,
    # we don't count it as failure
    data['boot_interface'] = inventory['boot'].pxe_interface
    LOG.debug('boot devices was %s', data['boot_interface'])
    data['ipmi_address'] = inventory.get('bmc_address')
    LOG.debug('BMC IP address: %s', data['ipmi_address'])

    # These 2 calls are required for backward compatibility and should be
    # dropped after inspector is ready (probably in Mitaka cycle).
    discover_network_properties(inventory, data, failures)
    discover_scheduling_properties(inventory, data, root_disk)
Ejemplo n.º 13
0
 def test_guess_root_disk_primary_sort(self, mock_call):
     block_devices = [
         hardware.BlockDevice(name='/dev/sdc',
                              model='too small',
                              size=4294967295,
                              rotational=True),
         hardware.BlockDevice(name='/dev/sda',
                              model='bigger than sdb',
                              size=21474836480,
                              rotational=True),
         hardware.BlockDevice(name='/dev/sdb',
                              model='',
                              size=10737418240,
                              rotational=True),
         hardware.BlockDevice(name='/dev/sdd',
                              model='bigger than sdb',
                              size=21474836480,
                              rotational=True),
     ]
     device = utils.guess_root_disk(block_devices)
     self.assertEqual(device.name, '/dev/sdb')
Ejemplo n.º 14
0
 def test_guess_root_disk_secondary_sort(self, mock_call):
     block_devices = [
         hardware.BlockDevice(name='/dev/sdc',
                              model='_',
                              size=10737418240,
                              rotational=True),
         hardware.BlockDevice(name='/dev/sdb',
                              model='_',
                              size=10737418240,
                              rotational=True),
         hardware.BlockDevice(name='/dev/sda',
                              model='_',
                              size=10737418240,
                              rotational=True),
         hardware.BlockDevice(name='/dev/sdd',
                              model='_',
                              size=10737418240,
                              rotational=True),
     ]
     device = utils.guess_root_disk(block_devices)
     self.assertEqual(device.name, '/dev/sda')
Ejemplo n.º 15
0
 def test_guess_root_disk_secondary_sort(self, mock_call):
     block_devices = [
         hardware.BlockDevice(name='/dev/sdc',
                              model='_',
                              size=10737418240,
                              rotational=True),
         hardware.BlockDevice(name='/dev/sdb',
                              model='_',
                              size=10737418240,
                              rotational=True),
         hardware.BlockDevice(name='/dev/sda',
                              model='_',
                              size=10737418240,
                              rotational=True),
         hardware.BlockDevice(name='/dev/sdd',
                              model='_',
                              size=10737418240,
                              rotational=True),
     ]
     device = utils.guess_root_disk(block_devices)
     self.assertEqual(device.name, '/dev/sda')
Ejemplo n.º 16
0
 def test_guess_root_disk_primary_sort(self, mock_call):
     block_devices = [
         hardware.BlockDevice(name='/dev/sdc',
                              model='too small',
                              size=4294967295,
                              rotational=True),
         hardware.BlockDevice(name='/dev/sda',
                              model='bigger than sdb',
                              size=21474836480,
                              rotational=True),
         hardware.BlockDevice(name='/dev/sdb',
                              model='',
                              size=10737418240,
                              rotational=True),
         hardware.BlockDevice(name='/dev/sdd',
                              model='bigger than sdb',
                              size=21474836480,
                              rotational=True),
     ]
     device = utils.guess_root_disk(block_devices)
     self.assertEqual(device.name, '/dev/sdb')
Ejemplo n.º 17
0
    def get_os_install_device(self):
        cached_node = get_cached_node()
        root_device_hints = None
        if cached_node is not None:
            root_device_hints = cached_node['properties'].get('root_device')
            LOG.debug('Looking for a device matching root hints %s',
                      root_device_hints)

        block_devices = self.list_block_devices()
        if not root_device_hints:
            dev_name = utils.guess_root_disk(block_devices).name
        else:
            serialized_devs = [dev.serialize() for dev in block_devices]
            try:
                device = il_utils.match_root_device_hints(serialized_devs,
                                                          root_device_hints)
            except ValueError as e:
                # NOTE(lucasagomes): Just playing on the safe side
                # here, this exception should never be raised because
                # Ironic should validate the root device hints before the
                # deployment starts.
                raise errors.DeviceNotFound(
                    'No devices could be found using the root device hints '
                    '%(hints)s because they failed to validate. Error: '
                    '%(error)s' % {'hints': root_device_hints, 'error': e})

            if not device:
                raise errors.DeviceNotFound(
                    "No suitable device was found for "
                    "deployment using these hints %s" % root_device_hints)

            dev_name = device['name']

        LOG.info('Picked root device %(dev)s for node %(node)s based on '
                 'root device hints %(hints)s',
                 {'dev': dev_name, 'hints': root_device_hints,
                  'node': cached_node['uuid'] if cached_node else None})
        return dev_name
Ejemplo n.º 18
0
    def get_os_install_device(self):
        cached_node = get_cached_node()
        root_device_hints = None
        if cached_node is not None:
            root_device_hints = cached_node['properties'].get('root_device')

        block_devices = self.list_block_devices()
        if not root_device_hints:
            return utils.guess_root_disk(block_devices).name
        else:

            def match(hint, current_value, device):
                hint_value = root_device_hints[hint]

                if hint == 'rotational':
                    hint_value = strutils.bool_from_string(hint_value)

                elif hint == 'size':
                    try:
                        hint_value = int(hint_value)
                    except (ValueError, TypeError):
                        LOG.warning(
                            'Root device hint "size" is not an integer. '
                            'Current value: "%(value)s"; and type: "%(type)s"',
                            {
                                'value': hint_value,
                                'type': type(hint_value)
                            })
                        return False

                if hint_value != current_value:
                    LOG.debug(
                        "Root device hint %(hint)s=%(value)s does not "
                        "match the device %(device)s value of "
                        "%(current)s", {
                            'hint': hint,
                            'value': hint_value,
                            'device': device,
                            'current': current_value
                        })
                    return False
                return True

            def check_device_attrs(device):
                for key in ('model', 'wwn', 'serial', 'vendor',
                            'wwn_with_extension', 'wwn_vendor_extension',
                            'name', 'rotational', 'size'):
                    if key not in root_device_hints:
                        continue

                    value = getattr(device, key)
                    if value is None:
                        return False

                    if isinstance(value, six.string_types):
                        value = utils.normalize(value)

                    if key == 'size':
                        # Since we don't support units yet we expect the size
                        # in GiB for now
                        value = value / units.Gi

                    if not match(key, value, device.name):
                        return False

                return True

            for dev in block_devices:
                if check_device_attrs(dev):
                    return dev.name

            else:
                raise errors.DeviceNotFound("No suitable device was found for "
                                            "deployment using these hints %s" %
                                            root_device_hints)