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)
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)