Example #1
0
    def prepare_instance_boot(self, task):
        if not task.driver.storage.should_write_image(task):
            task.driver.boot.prepare_instance(task)
            # Move straight to the final steps
            return

        node = task.node
        iwdi = task.node.driver_internal_info.get('is_whole_disk_image')
        cpu_arch = task.node.properties.get('cpu_arch')

        # If `boot_option` is set to `netboot`, PXEBoot.prepare_instance()
        # would need root_uuid of the whole disk image to add it into the
        # pxe config to perform chain boot.
        # IPA would have returned us the 'root_uuid_or_disk_id' if image
        # being provisioned is a whole disk image. IPA would also provide us
        # 'efi_system_partition_uuid' if the image being provisioned is a
        # partition image.
        # In case of local boot using partition image, we need both
        # 'root_uuid_or_disk_id' and 'efi_system_partition_uuid' to configure
        # bootloader for local boot.
        # NOTE(mjturek): In the case of local boot using a partition image on
        # ppc64* hardware we need to provide the 'PReP_Boot_partition_uuid' to
        # direct where the bootloader should be installed.
        driver_internal_info = task.node.driver_internal_info
        try:
            partition_uuids = self._client.get_partition_uuids(node).get(
                'command_result') or {}
            root_uuid = partition_uuids.get('root uuid')
        except exception.AgentAPIError:
            # TODO(dtantsur): remove in W
            LOG.warning('Old ironic-python-agent detected, please update '
                        'to Victoria or newer')
            partition_uuids = None
            root_uuid = self._get_uuid_from_result(task, 'root_uuid')

        if root_uuid:
            driver_internal_info['root_uuid_or_disk_id'] = root_uuid
            task.node.driver_internal_info = driver_internal_info
            task.node.save()
        elif not iwdi:
            LOG.error(
                'No root UUID returned from the ramdisk for node '
                '%(node)s, the deploy will likely fail. Partition '
                'UUIDs are %(uuids)s', {
                    'node': node.uuid,
                    'uuid': partition_uuids
                })

        efi_sys_uuid = None
        if not iwdi:
            if boot_mode_utils.get_boot_mode(node) == 'uefi':
                # TODO(dtantsur): remove in W
                if partition_uuids is None:
                    efi_sys_uuid = (self._get_uuid_from_result(
                        task, 'efi_system_partition_uuid'))
                else:
                    efi_sys_uuid = partition_uuids.get(
                        'efi system partition uuid')

        prep_boot_part_uuid = None
        if cpu_arch is not None and cpu_arch.startswith('ppc64'):
            # TODO(dtantsur): remove in W
            if partition_uuids is None:
                prep_boot_part_uuid = (self._get_uuid_from_result(
                    task, 'PReP_Boot_partition_uuid'))
            else:
                prep_boot_part_uuid = partition_uuids.get(
                    'PReP Boot partition uuid')

        LOG.info('Image successfully written to node %s', node.uuid)

        if CONF.agent.manage_agent_boot:
            # It is necessary to invoke prepare_instance() of the node's
            # boot interface, so that the any necessary configurations like
            # setting of the boot mode (e.g. UEFI secure boot) which cannot
            # be done on node during deploy stage can be performed.
            LOG.debug(
                'Executing driver specific tasks before booting up the '
                'instance for node %s', node.uuid)
            self.prepare_instance_to_boot(task, root_uuid, efi_sys_uuid,
                                          prep_boot_part_uuid)
        else:
            manager_utils.node_set_boot_device(task, 'disk', persistent=True)

        # Remove symbolic link when deploy is done.
        if CONF.agent.image_download_source == 'http':
            deploy_utils.remove_http_instance_symlink(task.node.uuid)
Example #2
0
    def reboot_to_instance(self, task):
        task.process_event('resume')
        node = task.node
        iwdi = task.node.driver_internal_info.get('is_whole_disk_image')
        cpu_arch = task.node.properties.get('cpu_arch')
        error = self.check_deploy_success(node)
        if error is not None:
            # TODO(jimrollenhagen) power off if using neutron dhcp to
            #                      align with pxe driver?
            msg = (_('node %(node)s command status errored: %(error)s') % {
                'node': node.uuid,
                'error': error
            })
            LOG.error(msg)
            deploy_utils.set_failed_state(task, msg)
            return

        # If `boot_option` is set to `netboot`, PXEBoot.prepare_instance()
        # would need root_uuid of the whole disk image to add it into the
        # pxe config to perform chain boot.
        # IPA would have returned us the 'root_uuid_or_disk_id' if image
        # being provisioned is a whole disk image. IPA would also provide us
        # 'efi_system_partition_uuid' if the image being provisioned is a
        # partition image.
        # In case of local boot using partition image, we need both
        # 'root_uuid_or_disk_id' and 'efi_system_partition_uuid' to configure
        # bootloader for local boot.
        # NOTE(mjturek): In the case of local boot using a partition image on
        # ppc64* hardware we need to provide the 'PReP_Boot_partition_uuid' to
        # direct where the bootloader should be installed.
        driver_internal_info = task.node.driver_internal_info
        root_uuid = self._get_uuid_from_result(task, 'root_uuid')
        if root_uuid:
            driver_internal_info['root_uuid_or_disk_id'] = root_uuid
            task.node.driver_internal_info = driver_internal_info
            task.node.save()
        elif iwdi and CONF.agent.manage_agent_boot:
            # IPA version less than 3.1.0 will not return root_uuid for
            # whole disk image. Also IPA version introduced a requirement
            # for hexdump utility that may not be always available. Need to
            # fall back to older behavior for the same.
            LOG.warning(
                "With the deploy ramdisk based on Ironic Python Agent "
                "version 3.1.0 and beyond, the drivers using "
                "`direct` deploy interface performs `netboot` or "
                "`local` boot for whole disk image based on value "
                "of boot option setting. When you upgrade Ironic "
                "Python Agent in your deploy ramdisk, ensure that "
                "boot option is set appropriately for the node %s. "
                "The boot option can be set using configuration "
                "`[deploy]/default_boot_option` or as a `boot_option` "
                "capability in node's `properties['capabilities']`. "
                "Also please note that this functionality requires "
                "`hexdump` command in the ramdisk.", node.uuid)

        efi_sys_uuid = None
        if not iwdi:
            if boot_mode_utils.get_boot_mode(node) == 'uefi':
                efi_sys_uuid = (self._get_uuid_from_result(
                    task, 'efi_system_partition_uuid'))

        prep_boot_part_uuid = None
        if cpu_arch is not None and cpu_arch.startswith('ppc64'):
            prep_boot_part_uuid = (self._get_uuid_from_result(
                task, 'PReP_Boot_partition_uuid'))

        LOG.info('Image successfully written to node %s', node.uuid)

        if CONF.agent.manage_agent_boot:
            # It is necessary to invoke prepare_instance() of the node's
            # boot interface, so that the any necessary configurations like
            # setting of the boot mode (e.g. UEFI secure boot) which cannot
            # be done on node during deploy stage can be performed.
            LOG.debug(
                'Executing driver specific tasks before booting up the '
                'instance for node %s', node.uuid)
            self.prepare_instance_to_boot(task, root_uuid, efi_sys_uuid,
                                          prep_boot_part_uuid)
        else:
            manager_utils.node_set_boot_device(task, 'disk', persistent=True)

        # Remove symbolic link when deploy is done.
        if CONF.agent.image_download_source == 'http':
            deploy_utils.remove_http_instance_symlink(task.node.uuid)

        LOG.debug('Rebooting node %s to instance', node.uuid)
        self.reboot_and_finish_deploy(task)