Ejemplo n.º 1
0
    def test_create_pxe_config_uefi_grub(self, ensure_tree_mock, render_mock,
                                         write_mock, link_ip_configs_mock,
                                         chmod_mock):
        grub_tmplte = "ironic/drivers/modules/pxe_grub_config.template"
        with task_manager.acquire(self.context, self.node.uuid) as task:
            task.node.properties['capabilities'] = 'boot_mode:uefi'
            pxe_utils.create_pxe_config(task, self.pxe_options,
                                        grub_tmplte)

            ensure_calls = [
                mock.call(os.path.join(CONF.pxe.tftp_root, self.node.uuid)),
                mock.call(os.path.join(CONF.pxe.tftp_root, 'pxelinux.cfg')),
            ]
            ensure_tree_mock.assert_has_calls(ensure_calls)
            chmod_mock.assert_not_called()
            render_mock.assert_called_with(
                grub_tmplte,
                {'pxe_options': self.pxe_options,
                 'ROOT': '(( ROOT ))',
                 'DISK_IDENTIFIER': '(( DISK_IDENTIFIER ))'})
            link_ip_configs_mock.assert_called_once_with(task, False)

        pxe_cfg_file_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
        write_mock.assert_called_with(pxe_cfg_file_path,
                                      render_mock.return_value)
Ejemplo n.º 2
0
    def _prepare_instance_pxe_config(self,
                                     task,
                                     image_info,
                                     iscsi_boot=False,
                                     ramdisk_boot=False):
        """Prepares the config file for PXE boot

        :param task: a task from TaskManager.
        :param image_info: a dict of values of instance image
            metadata to set on the configuration file.
        :param iscsi_boot: if boot is from an iSCSI volume or not.
        :param ramdisk_boot: if the boot is to a ramdisk configuration.
        :returns: None
        """

        node = task.node
        dhcp_opts = pxe_utils.dhcp_options_for_instance(task)
        provider = dhcp_factory.DHCPFactory()
        provider.update_dhcp(task, dhcp_opts)
        pxe_config_path = pxe_utils.get_pxe_config_file_path(node.uuid)
        if not os.path.isfile(pxe_config_path):
            pxe_options = _build_pxe_config_options(task,
                                                    image_info,
                                                    service=ramdisk_boot)
            pxe_config_template = (deploy_utils.get_pxe_config_template(node))
            pxe_utils.create_pxe_config(task, pxe_options, pxe_config_template)
        deploy_utils.switch_pxe_config(
            pxe_config_path,
            None,
            boot_mode_utils.get_boot_mode_for_deploy(node),
            False,
            iscsi_boot=iscsi_boot,
            ramdisk_boot=ramdisk_boot)
Ejemplo n.º 3
0
    def test_continue_deploy_good(self, mock_image_cache, mock_switch_config,
            notify_mock):
        token_path = self._create_token_file()
        self.node.power_state = states.POWER_ON
        self.node.provision_state = states.DEPLOYWAIT
        self.node.target_provision_state = states.ACTIVE
        self.node.save()

        root_uuid = "12345678-1234-1234-1234-1234567890abcxyz"
        boot_mode = None

        def fake_deploy(**kwargs):
            return root_uuid

        self.useFixture(fixtures.MonkeyPatch(
                'ironic.drivers.modules.deploy_utils.deploy',
                fake_deploy))

        with task_manager.acquire(self.context, self.node.uuid) as task:
            task.driver.vendor._continue_deploy(
                    task, address='123456', iqn='aaa-bbb', key='fake-56789')

        self.node.refresh()
        self.assertEqual(states.ACTIVE, self.node.provision_state)
        self.assertEqual(states.NOSTATE, self.node.target_provision_state)
        self.assertEqual(states.POWER_ON, self.node.power_state)
        self.assertIsNone(self.node.last_error)
        self.assertFalse(os.path.exists(token_path))
        mock_image_cache.assert_called_once_with()
        mock_image_cache.return_value.clean_up.assert_called_once_with()
        pxe_config_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
        mock_switch_config.assert_called_once_with(pxe_config_path, root_uuid,
                                boot_mode)
        notify_mock.assert_called_once_with('123456')
Ejemplo n.º 4
0
Archivo: pxe.py Proyecto: n1zyy/ironic
    def _get_deploy_info(self, node, **kwargs):
        d_info = _parse_deploy_info(node)

        deploy_key = kwargs.get('key')
        if d_info['deploy_key'] != deploy_key:
            raise exception.InvalidParameterValue(_("Deploy key does not"
                                                    " match"))

        params = {'address': kwargs.get('address'),
                  'port': kwargs.get('port', '3260'),
                  'iqn': kwargs.get('iqn'),
                  'lun': kwargs.get('lun', '1'),
                  'image_path': _get_image_file_path(node.uuid),
                  'pxe_config_path':
                      pxe_utils.get_pxe_config_file_path(node.uuid),
                  'root_mb': 1024 * int(d_info['root_gb']),
                  'swap_mb': int(d_info['swap_mb']),
                  'ephemeral_mb': 1024 * int(d_info['ephemeral_gb']),
                  'preserve_ephemeral': d_info['preserve_ephemeral'],
                  'node_uuid': node.uuid,
            }

        missing = [key for key in params.keys() if params[key] is None]
        if missing:
            raise exception.InvalidParameterValue(_(
                    "Parameters %s were not passed to ironic"
                    " for deploy.") % missing)

        # ephemeral_format is nullable
        params['ephemeral_format'] = d_info.get('ephemeral_format')

        return params
Ejemplo n.º 5
0
Archivo: pxe.py Proyecto: uggla/ironic
    def prepare(self, task):
        """Prepare the deployment environment for this task's node.

        Generates the TFTP configuration for PXE-booting both the deployment
        and user images, fetches the TFTP image from Glance and add it to the
        local cache.

        :param task: a TaskManager instance containing the node to act on.
        """
        node = task.node
        # TODO(deva): optimize this if rerun on existing files
        if CONF.pxe.ipxe_enabled:
            # Copy the iPXE boot script to HTTP root directory
            bootfile_path = os.path.join(CONF.pxe.http_root,
                                   os.path.basename(CONF.pxe.ipxe_boot_script))
            shutil.copyfile(CONF.pxe.ipxe_boot_script, bootfile_path)
        pxe_info = _get_image_info(node, task.context)
        pxe_options = _build_pxe_config_options(node, pxe_info,
                                                task.context)

        if deploy_utils.get_boot_mode_for_deploy(node) == 'uefi':
            pxe_config_template = CONF.pxe.uefi_pxe_config_template
        else:
            pxe_config_template = CONF.pxe.pxe_config_template

        pxe_utils.create_pxe_config(task, pxe_options,
                                    pxe_config_template)

        # FIXME(lucasagomes): If it's local boot we should not cache
        # the image kernel and ramdisk (Or even require it).
        _cache_ramdisk_kernel(task.context, node, pxe_info)

        # NOTE(deva): prepare may be called from conductor._do_takeover
        # in which case, it may need to regenerate the PXE config file for an
        # already-active deployment.
        if node.provision_state == states.ACTIVE:
            # this should have been stashed when the deploy was done
            # but let's guard, just in case it's missing
            iwdi = node.driver_internal_info.get('is_whole_disk_image')
            try:
                root_uuid_or_disk_id = node.driver_internal_info[
                                                'root_uuid_or_disk_id']
            except KeyError:
                if not iwdi:
                    LOG.warn(_LW("The UUID for the root partition can't be "
                             "found, unable to switch the pxe config from "
                             "deployment mode to service (boot) mode for node "
                             "%(node)s"), {"node": node.uuid})
                else:
                    LOG.warn(_LW("The disk id for the whole disk image can't "
                             "be found, unable to switch the pxe config from "
                             "deployment mode to service (boot) mode for "
                             "node %(node)s"), {"node": node.uuid})
            else:
                pxe_config_path = pxe_utils.get_pxe_config_file_path(
                    node.uuid)
                deploy_utils.switch_pxe_config(
                    pxe_config_path, root_uuid_or_disk_id,
                    deploy_utils.get_boot_mode_for_deploy(node),
                    iwdi)
Ejemplo n.º 6
0
    def setUp(self):
        super(CleanUpFullFlowTestCase, self).setUp()
        self.config(image_cache_size=0, group='pxe')

        # Configure node
        mgr_utils.mock_the_extension_manager(driver="fake_pxe")
        instance_info = INST_INFO_DICT
        instance_info['deploy_key'] = 'fake-56789'
        self.node = obj_utils.create_test_node(self.context,
                                               driver='fake_pxe',
                                               instance_info=instance_info,
                                               driver_info=DRV_INFO_DICT)
        self.dbapi = dbapi.get_instance()
        self.port = obj_utils.create_test_port(self.context,
                                               node_id=self.node.id)

        # Configure temporary directories
        pxe_temp_dir = tempfile.mkdtemp()
        self.config(tftp_root=pxe_temp_dir, group='pxe')
        tftp_master_dir = os.path.join(CONF.pxe.tftp_root, 'tftp_master')
        self.config(tftp_master_path=tftp_master_dir, group='pxe')
        os.makedirs(tftp_master_dir)

        instance_temp_dir = tempfile.mkdtemp()
        self.config(images_path=instance_temp_dir, group='pxe')
        instance_master_dir = os.path.join(CONF.pxe.images_path,
                                           'instance_master')
        self.config(instance_master_path=instance_master_dir, group='pxe')
        os.makedirs(instance_master_dir)
        self.pxe_config_dir = os.path.join(CONF.pxe.tftp_root, 'pxelinux.cfg')
        os.makedirs(self.pxe_config_dir)

        # Populate some file names
        self.master_kernel_path = os.path.join(CONF.pxe.tftp_master_path,
                                               'kernel')
        self.master_instance_path = os.path.join(CONF.pxe.instance_master_path,
                                                 'image_uuid')
        self.node_tftp_dir = os.path.join(CONF.pxe.tftp_root, self.node.uuid)
        os.makedirs(self.node_tftp_dir)
        self.kernel_path = os.path.join(self.node_tftp_dir, 'kernel')
        self.node_image_dir = iscsi_deploy._get_image_dir_path(self.node.uuid)
        os.makedirs(self.node_image_dir)
        self.image_path = iscsi_deploy._get_image_file_path(self.node.uuid)
        self.config_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
        self.mac_path = pxe_utils._get_pxe_mac_path(self.port.address)
        self.token_path = pxe._get_token_file_path(self.node.uuid)

        # Create files
        self.files = [
            self.config_path, self.master_kernel_path,
            self.master_instance_path, self.token_path
        ]
        for fname in self.files:
            # NOTE(dtantsur): files with 0 size won't be cleaned up
            with open(fname, 'w') as fp:
                fp.write('test')

        os.link(self.config_path, self.mac_path)
        os.link(self.master_kernel_path, self.kernel_path)
        os.link(self.master_instance_path, self.image_path)
Ejemplo n.º 7
0
    def test_create_pxe_config_uefi_elilo(self, ensure_tree_mock, render_mock,
                                          write_mock, link_ip_configs_mock):
        self.config(uefi_pxe_config_template=('ironic/drivers/modules/'
                                              'elilo_efi_pxe_config.template'),
                    group='pxe')
        with task_manager.acquire(self.context, self.node.uuid) as task:
            task.node.properties['capabilities'] = 'boot_mode:uefi'
            pxe_utils.create_pxe_config(task, self.pxe_options,
                                        CONF.pxe.uefi_pxe_config_template)

            ensure_calls = [
                mock.call(os.path.join(CONF.pxe.tftp_root, self.node.uuid)),
                mock.call(os.path.join(CONF.pxe.tftp_root, 'pxelinux.cfg'))
            ]
            ensure_tree_mock.assert_has_calls(ensure_calls)
            render_mock.assert_called_with(
                CONF.pxe.uefi_pxe_config_template, {
                    'pxe_options': self.pxe_options,
                    'ROOT': '{{ ROOT }}',
                    'DISK_IDENTIFIER': '{{ DISK_IDENTIFIER }}'
                })
            link_ip_configs_mock.assert_called_once_with(task, True)

        pxe_cfg_file_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
        write_mock.assert_called_with(pxe_cfg_file_path,
                                      render_mock.return_value)
Ejemplo n.º 8
0
    def test_create_pxe_config_uefi_ipxe(self, ensure_tree_mock, render_mock,
                                         write_mock, link_mac_pxe_mock,
                                         chmod_mock):
        self.config(ipxe_enabled=True, group='pxe')
        ipxe_template = "ironic/drivers/modules/ipxe_config.template"
        with task_manager.acquire(self.context, self.node.uuid) as task:
            task.node.properties['capabilities'] = 'boot_mode:uefi'
            pxe_utils.create_pxe_config(task, self.ipxe_options, ipxe_template)

            ensure_calls = [
                mock.call(os.path.join(CONF.deploy.http_root, self.node.uuid)),
                mock.call(os.path.join(CONF.deploy.http_root, 'pxelinux.cfg')),
            ]
            ensure_tree_mock.assert_has_calls(ensure_calls)
            chmod_mock.assert_not_called()
            render_mock.assert_called_with(
                ipxe_template, {
                    'pxe_options': self.ipxe_options,
                    'ROOT': '{{ ROOT }}',
                    'DISK_IDENTIFIER': '{{ DISK_IDENTIFIER }}'
                })
            link_mac_pxe_mock.assert_called_once_with(task)

        pxe_cfg_file_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
        write_mock.assert_called_with(pxe_cfg_file_path,
                                      render_mock.return_value)
Ejemplo n.º 9
0
    def test_create_pxe_config_set_dir_permission(self, ensure_tree_mock,
                                                  render_mock,
                                                  write_mock, chmod_mock):
        self.config(dir_permission=0o755, group='pxe')
        with task_manager.acquire(self.context, self.node.uuid) as task:
            pxe_utils.create_pxe_config(task, self.pxe_options,
                                        CONF.pxe.pxe_config_template)
            render_mock.assert_called_with(
                CONF.pxe.pxe_config_template,
                {'pxe_options': self.pxe_options,
                 'ROOT': '{{ ROOT }}',
                 'DISK_IDENTIFIER': '{{ DISK_IDENTIFIER }}'}
            )
        node_dir = os.path.join(CONF.pxe.tftp_root, self.node.uuid)
        pxe_dir = os.path.join(CONF.pxe.tftp_root, 'pxelinux.cfg')
        ensure_calls = [
            mock.call(node_dir), mock.call(pxe_dir),
        ]
        ensure_tree_mock.assert_has_calls(ensure_calls)
        chmod_calls = [mock.call(node_dir, 0o755), mock.call(pxe_dir, 0o755)]
        chmod_mock.assert_has_calls(chmod_calls)

        pxe_cfg_file_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
        write_mock.assert_called_with(pxe_cfg_file_path,
                                      render_mock.return_value)
Ejemplo n.º 10
0
    def test_continue_deploy_good(self, mock_image_cache, mock_switch_config,
            notify_mock):
        token_path = self._create_token_file()
        self.node.power_state = states.POWER_ON
        self.node.provision_state = states.DEPLOYWAIT
        self.node.save()

        root_uuid = "12345678-1234-1234-1234-1234567890abcxyz"
        boot_mode = None

        def fake_deploy(**kwargs):
            return root_uuid

        self.useFixture(fixtures.MonkeyPatch(
                'ironic.drivers.modules.deploy_utils.deploy',
                fake_deploy))

        with task_manager.acquire(self.context, self.node.uuid) as task:
            task.driver.vendor.vendor_passthru(
                    task, method='pass_deploy_info', address='123456',
                    iqn='aaa-bbb', key='fake-56789')
        self.node.refresh(self.context)
        self.assertEqual(states.ACTIVE, self.node.provision_state)
        self.assertEqual(states.POWER_ON, self.node.power_state)
        self.assertIsNone(self.node.last_error)
        self.assertFalse(os.path.exists(token_path))
        mock_image_cache.assert_called_once_with()
        mock_image_cache.return_value.clean_up.assert_called_once_with()
        pxe_config_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
        mock_switch_config.assert_called_once_with(pxe_config_path, root_uuid,
                                boot_mode)
        notify_mock.assert_called_once_with('123456')
Ejemplo n.º 11
0
    def test_create_pxe_config_set_dir_permission(self, ensure_tree_mock,
                                                  render_mock, write_mock,
                                                  chmod_mock):
        self.config(dir_permission=0o755, group='pxe')
        with task_manager.acquire(self.context, self.node.uuid) as task:
            pxe_utils.create_pxe_config(task, self.pxe_options,
                                        CONF.pxe.pxe_config_template)
            render_mock.assert_called_with(
                CONF.pxe.pxe_config_template, {
                    'pxe_options': self.pxe_options,
                    'ROOT': '{{ ROOT }}',
                    'DISK_IDENTIFIER': '{{ DISK_IDENTIFIER }}'
                })
        node_dir = os.path.join(CONF.pxe.tftp_root, self.node.uuid)
        pxe_dir = os.path.join(CONF.pxe.tftp_root, 'pxelinux.cfg')
        ensure_calls = [
            mock.call(node_dir),
            mock.call(pxe_dir),
        ]
        ensure_tree_mock.assert_has_calls(ensure_calls)
        chmod_calls = [mock.call(node_dir, 0o755), mock.call(pxe_dir, 0o755)]
        chmod_mock.assert_has_calls(chmod_calls)

        pxe_cfg_file_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
        write_mock.assert_called_with(pxe_cfg_file_path,
                                      render_mock.return_value)
Ejemplo n.º 12
0
    def test_prepare_instance_netboot(
            self, get_image_info_mock, cache_mock,
            dhcp_factory_mock, switch_pxe_config_mock,
            set_boot_device_mock):
        provider_mock = mock.MagicMock()
        dhcp_factory_mock.return_value = provider_mock
        image_info = {'kernel': ('', '/path/to/kernel'),
                      'ramdisk': ('', '/path/to/ramdisk')}
        get_image_info_mock.return_value = image_info
        with task_manager.acquire(self.context, self.node.uuid) as task:
            dhcp_opts = pxe_utils.dhcp_options_for_instance(task)
            pxe_config_path = pxe_utils.get_pxe_config_file_path(
                task.node.uuid)
            task.node.properties['capabilities'] = 'boot_mode:bios'
            task.node.driver_internal_info['root_uuid_or_disk_id'] = (
                "30212642-09d3-467f-8e09-21685826ab50")
            task.node.driver_internal_info['is_whole_disk_image'] = False

            task.driver.boot.prepare_instance(task)

            get_image_info_mock.assert_called_once_with(
                task.node, task.context)
            cache_mock.assert_called_once_with(
                task.context, task.node, image_info)
            provider_mock.update_dhcp.assert_called_once_with(task, dhcp_opts)
            switch_pxe_config_mock.assert_called_once_with(
                pxe_config_path, "30212642-09d3-467f-8e09-21685826ab50",
                'bios', False, False)
            set_boot_device_mock.assert_called_once_with(task,
                                                         boot_devices.PXE)
Ejemplo n.º 13
0
    def test_prepare_instance_localboot_with_fallback(
            self, get_image_info_mock, cache_mock,
            dhcp_factory_mock, switch_pxe_config_mock,
            clean_up_pxe_config_mock, set_boot_device_mock):
        self.config(enable_netboot_fallback=True, group='pxe')
        with task_manager.acquire(self.context, self.node.uuid) as task:
            task.node.instance_info = task.node.instance_info
            task.node.instance_info['capabilities'] = {'boot_option': 'local'}
            task.node.driver_internal_info['root_uuid_or_disk_id'] = (
                "30212642-09d3-467f-8e09-21685826ab50")
            task.node.driver_internal_info['is_whole_disk_image'] = False
            pxe_config_path = pxe_utils.get_pxe_config_file_path(
                task.node.uuid, ipxe_enabled=True)

            task.driver.boot.prepare_instance(task)

            set_boot_device_mock.assert_called_once_with(task,
                                                         boot_devices.DISK,
                                                         persistent=True)
            switch_pxe_config_mock.assert_called_once_with(
                pxe_config_path, "30212642-09d3-467f-8e09-21685826ab50",
                'bios', True, False, False, False, ipxe_enabled=True)
            # No clean up
            self.assertFalse(clean_up_pxe_config_mock.called)
            # No netboot configuration beyond the PXE files
            self.assertFalse(get_image_info_mock.called)
            self.assertFalse(cache_mock.called)
            self.assertFalse(dhcp_factory_mock.return_value.update_dhcp.called)
Ejemplo n.º 14
0
    def test_create_pxe_config_uefi_grub(self, ensure_tree_mock, render_mock,
                                         write_mock, link_ip_configs_mock,
                                         chmod_mock):
        grub_tmplte = "ironic/drivers/modules/pxe_grub_config.template"
        with task_manager.acquire(self.context, self.node.uuid) as task:
            task.node.properties['capabilities'] = 'boot_mode:uefi'
            pxe_utils.create_pxe_config(task, self.pxe_options, grub_tmplte)

            ensure_calls = [
                mock.call(os.path.join(CONF.pxe.tftp_root, self.node.uuid)),
                mock.call(os.path.join(CONF.pxe.tftp_root, 'pxelinux.cfg')),
            ]
            ensure_tree_mock.assert_has_calls(ensure_calls)
            chmod_mock.assert_not_called()
            render_mock.assert_called_with(
                grub_tmplte, {
                    'pxe_options': self.pxe_options,
                    'ROOT': '(( ROOT ))',
                    'DISK_IDENTIFIER': '(( DISK_IDENTIFIER ))'
                })
            link_ip_configs_mock.assert_called_once_with(task, False)

        pxe_cfg_file_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
        write_mock.assert_called_with(pxe_cfg_file_path,
                                      render_mock.return_value)
Ejemplo n.º 15
0
    def prepare(self, task):
        """Prepare the deployment environment for this task's node.

        Generates the TFTP configuration for PXE-booting both the deployment
        and user images, fetches the TFTP image from Glance and add it to the
        local cache.

        :param task: a TaskManager instance containing the node to act on.
        """
        node = task.node
        # TODO(deva): optimize this if rerun on existing files
        if CONF.pxe.ipxe_enabled:
            # Copy the iPXE boot script to HTTP root directory
            bootfile_path = os.path.join(
                CONF.pxe.http_root,
                os.path.basename(CONF.pxe.ipxe_boot_script))
            shutil.copyfile(CONF.pxe.ipxe_boot_script, bootfile_path)
        pxe_info = _get_image_info(node, task.context)
        pxe_options = _build_pxe_config_options(node, pxe_info, task.context)

        if deploy_utils.get_boot_mode_for_deploy(node) == 'uefi':
            pxe_config_template = CONF.pxe.uefi_pxe_config_template
        else:
            pxe_config_template = CONF.pxe.pxe_config_template

        pxe_utils.create_pxe_config(task, pxe_options, pxe_config_template)

        # FIXME(lucasagomes): If it's local boot we should not cache
        # the image kernel and ramdisk (Or even require it).
        _cache_ramdisk_kernel(task.context, node, pxe_info)

        # NOTE(deva): prepare may be called from conductor._do_takeover
        # in which case, it may need to regenerate the PXE config file for an
        # already-active deployment.
        if node.provision_state == states.ACTIVE:
            # this should have been stashed when the deploy was done
            # but let's guard, just in case it's missing
            iwdi = node.driver_internal_info.get('is_whole_disk_image')
            try:
                root_uuid_or_disk_id = (
                    node.driver_internal_info['root_uuid_or_disk_id'])
            except KeyError:
                if not iwdi:
                    LOG.warn(
                        _LW("The UUID for the root partition can't be "
                            "found, unable to switch the pxe config from "
                            "deployment mode to service (boot) mode for node "
                            "%(node)s"), {"node": node.uuid})
                else:
                    LOG.warn(
                        _LW("The disk id for the whole disk image can't "
                            "be found, unable to switch the pxe config from "
                            "deployment mode to service (boot) mode for "
                            "node %(node)s"), {"node": node.uuid})
            else:
                pxe_config_path = pxe_utils.get_pxe_config_file_path(node.uuid)
                deploy_utils.switch_pxe_config(
                    pxe_config_path, root_uuid_or_disk_id,
                    deploy_utils.get_boot_mode_for_deploy(node), iwdi,
                    deploy_utils.is_trusted_boot_requested(node))
Ejemplo n.º 16
0
    def _get_deploy_info(self, node, **kwargs):
        d_info = _parse_deploy_info(node)

        deploy_key = kwargs.get('key')
        if d_info['deploy_key'] != deploy_key:
            raise exception.InvalidParameterValue(
                _("Deploy key does not"
                  " match"))

        params = {
            'address': kwargs.get('address'),
            'port': kwargs.get('port', '3260'),
            'iqn': kwargs.get('iqn'),
            'lun': kwargs.get('lun', '1'),
            'image_path': _get_image_file_path(node.uuid),
            'pxe_config_path': pxe_utils.get_pxe_config_file_path(node.uuid),
            'root_mb': 1024 * int(d_info['root_gb']),
            'swap_mb': int(d_info['swap_mb']),
            'ephemeral_mb': 1024 * int(d_info['ephemeral_gb']),
            'preserve_ephemeral': d_info['preserve_ephemeral'],
            'node_uuid': node.uuid,
        }

        missing = [key for key in params.keys() if params[key] is None]
        if missing:
            raise exception.InvalidParameterValue(
                _("Parameters %s were not passed to ironic"
                  " for deploy.") % missing)

        # ephemeral_format is nullable
        params['ephemeral_format'] = d_info.get('ephemeral_format')

        return params
Ejemplo n.º 17
0
Archivo: pxe.py Proyecto: skw0rm/ironic
    def _continue_deploy(self, task, **kwargs):
        """Continues the deployment of baremetal node over iSCSI.

        This method continues the deployment of the baremetal node over iSCSI
        from where the deployment ramdisk has left off.

        :param task: a TaskManager instance containing the node to act on.
        :param kwargs: kwargs for performing iscsi deployment.
        :raises: InvalidState
        """
        node = task.node
        task.process_event('resume')

        _destroy_token_file(node)

        root_uuid = iscsi_deploy.continue_deploy(task, **kwargs)

        if not root_uuid:
            return

        try:
            pxe_config_path = pxe_utils.get_pxe_config_file_path(node.uuid)
            deploy_utils.switch_pxe_config(pxe_config_path, root_uuid,
                          driver_utils.get_node_capability(node, 'boot_mode'))

            deploy_utils.notify_deploy_complete(kwargs['address'])

            LOG.info(_LI('Deployment to node %s done'), node.uuid)
            task.process_event('done')
        except Exception as e:
            LOG.error(_LE('Deploy failed for instance %(instance)s. '
                          'Error: %(error)s'),
                      {'instance': node.instance_uuid, 'error': e})
            msg = _('Failed to continue iSCSI deployment.')
            deploy_utils.set_failed_state(task, msg)
Ejemplo n.º 18
0
    def test_prepare_instance_netboot(
            self, get_image_info_mock, cache_mock,
            dhcp_factory_mock, switch_pxe_config_mock,
            set_boot_device_mock):
        provider_mock = mock.MagicMock()
        dhcp_factory_mock.return_value = provider_mock
        image_info = {'kernel': ('', '/path/to/kernel'),
                      'ramdisk': ('', '/path/to/ramdisk')}
        get_image_info_mock.return_value = image_info
        with task_manager.acquire(self.context, self.node.uuid) as task:
            dhcp_opts = pxe_utils.dhcp_options_for_instance(task)
            pxe_config_path = pxe_utils.get_pxe_config_file_path(
                task.node.uuid)
            task.node.properties['capabilities'] = 'boot_mode:bios'
            task.node.driver_internal_info['root_uuid_or_disk_id'] = (
                "30212642-09d3-467f-8e09-21685826ab50")
            task.node.driver_internal_info['is_whole_disk_image'] = False

            task.driver.boot.prepare_instance(task)

            get_image_info_mock.assert_called_once_with(
                task.node, task.context)
            cache_mock.assert_called_once_with(
                task.context, task.node, image_info)
            provider_mock.update_dhcp.assert_called_once_with(task, dhcp_opts)
            switch_pxe_config_mock.assert_called_once_with(
                pxe_config_path, "30212642-09d3-467f-8e09-21685826ab50",
                'bios', False, False)
            set_boot_device_mock.assert_called_once_with(task,
                                                         boot_devices.PXE)
Ejemplo n.º 19
0
    def test_create_pxe_config_uefi_ipxe(self, ensure_tree_mock, render_mock,
                                         write_mock, link_mac_pxe_mock,
                                         chmod_mock):
        self.config(ipxe_enabled=True, group='pxe')
        ipxe_template = "ironic/drivers/modules/ipxe_config.template"
        with task_manager.acquire(self.context, self.node.uuid) as task:
            task.node.properties['capabilities'] = 'boot_mode:uefi'
            pxe_utils.create_pxe_config(task, self.ipxe_options,
                                        ipxe_template)

            ensure_calls = [
                mock.call(os.path.join(CONF.deploy.http_root, self.node.uuid)),
                mock.call(os.path.join(CONF.deploy.http_root, 'pxelinux.cfg')),
            ]
            ensure_tree_mock.assert_has_calls(ensure_calls)
            chmod_mock.assert_not_called()
            render_mock.assert_called_with(
                ipxe_template,
                {'pxe_options': self.ipxe_options,
                 'ROOT': '{{ ROOT }}',
                 'DISK_IDENTIFIER': '{{ DISK_IDENTIFIER }}'})
            link_mac_pxe_mock.assert_called_once_with(task)

        pxe_cfg_file_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
        write_mock.assert_called_with(pxe_cfg_file_path,
                                      render_mock.return_value)
Ejemplo n.º 20
0
    def pass_deploy_info(self, task, **kwargs):
        """Continues the deployment of baremetal node over iSCSI.

        This method continues the deployment of the baremetal node over iSCSI
        from where the deployment ramdisk has left off.

        :param task: a TaskManager instance containing the node to act on.
        :param kwargs: kwargs for performing iscsi deployment.
        :raises: InvalidState
        """
        node = task.node
        task.process_event('resume')

        _destroy_token_file(node)
        is_whole_disk_image = node.driver_internal_info['is_whole_disk_image']
        uuid_dict = iscsi_deploy.continue_deploy(task, **kwargs)
        root_uuid_or_disk_id = uuid_dict.get(
            'root uuid', uuid_dict.get('disk identifier'))

        # save the node's root disk UUID so that another conductor could
        # rebuild the PXE config file. Due to a shortcoming in Nova objects,
        # we have to assign to node.driver_internal_info so the node knows it
        # has changed.
        driver_internal_info = node.driver_internal_info
        driver_internal_info['root_uuid_or_disk_id'] = root_uuid_or_disk_id
        node.driver_internal_info = driver_internal_info
        node.save()

        try:
            if iscsi_deploy.get_boot_option(node) == "local":
                deploy_utils.try_set_boot_device(task, boot_devices.DISK)

                # If it's going to boot from the local disk, get rid of
                # the PXE configuration files used for the deployment
                pxe_utils.clean_up_pxe_config(task)

                # Ask the ramdisk to install bootloader and
                # wait for the call-back through the vendor passthru
                # 'pass_bootloader_install_info', if it's not a
                # whole disk image.
                if not is_whole_disk_image:
                    deploy_utils.notify_ramdisk_to_proceed(kwargs['address'])
                    task.process_event('wait')
                    return
            else:
                pxe_config_path = pxe_utils.get_pxe_config_file_path(node.uuid)
                boot_mode = deploy_utils.get_boot_mode_for_deploy(node)
                deploy_utils.switch_pxe_config(pxe_config_path,
                                               root_uuid_or_disk_id,
                                               boot_mode, is_whole_disk_image)

        except Exception as e:
            LOG.error(_LE('Deploy failed for instance %(instance)s. '
                          'Error: %(error)s'),
                      {'instance': node.instance_uuid, 'error': e})
            msg = _('Failed to continue iSCSI deployment.')
            deploy_utils.set_failed_state(task, msg)
        else:
            iscsi_deploy.finish_deploy(task, kwargs.get('address'))
Ejemplo n.º 21
0
    def prepare_instance(self, task):
        """Prepares the boot of instance.

        This method prepares the boot of the instance after reading
        relevant information from the node's instance_info. In case of netboot,
        it updates the dhcp entries and switches the PXE config. In case of
        localboot, it cleans up the PXE config.

        :param task: a task from TaskManager.
        :returns: None
        """
        node = task.node
        boot_option = deploy_utils.get_boot_option(node)

        if boot_option != "local":
            # Make sure that the instance kernel/ramdisk is cached.
            # This is for the takeover scenario for active nodes.
            instance_image_info = _get_instance_image_info(
                task.node, task.context)
            _cache_ramdisk_kernel(task.context, task.node, instance_image_info)

            # If it's going to PXE boot we need to update the DHCP server
            dhcp_opts = pxe_utils.dhcp_options_for_instance(task)
            provider = dhcp_factory.DHCPFactory()
            provider.update_dhcp(task, dhcp_opts)

            iwdi = task.node.driver_internal_info.get('is_whole_disk_image')
            try:
                root_uuid_or_disk_id = task.node.driver_internal_info[
                    'root_uuid_or_disk_id'
                ]
            except KeyError:
                if not iwdi:
                    LOG.warn(_LW("The UUID for the root partition can't be "
                                 "found, unable to switch the pxe config from "
                                 "deployment mode to service (boot) mode for "
                                 "node %(node)s"), {"node": task.node.uuid})
                else:
                    LOG.warn(_LW("The disk id for the whole disk image can't "
                                 "be found, unable to switch the pxe config "
                                 "from deployment mode to service (boot) mode "
                                 "for node %(node)s"),
                             {"node": task.node.uuid})
            else:
                pxe_config_path = pxe_utils.get_pxe_config_file_path(
                    task.node.uuid)
                deploy_utils.switch_pxe_config(
                    pxe_config_path, root_uuid_or_disk_id,
                    deploy_utils.get_boot_mode_for_deploy(node),
                    iwdi, deploy_utils.is_trusted_boot_requested(node))

        else:
            # If it's going to boot from the local disk, we don't need
            # PXE config files. They still need to be generated as part
            # of the prepare() because the deployment does PXE boot the
            # deploy ramdisk
            pxe_utils.clean_up_pxe_config(task)
Ejemplo n.º 22
0
    def prepare_instance(self, task):
        """Prepares the boot of instance.

        This method prepares the boot of the instance after reading
        relevant information from the node's instance_info. In case of netboot,
        it updates the dhcp entries and switches the PXE config. In case of
        localboot, it cleans up the PXE config.

        :param task: a task from TaskManager.
        :returns: None
        """
        node = task.node
        boot_option = deploy_utils.get_boot_option(node)

        if boot_option != "local":
            # Make sure that the instance kernel/ramdisk is cached.
            # This is for the takeover scenario for active nodes.
            instance_image_info = _get_instance_image_info(
                task.node, task.context)
            _cache_ramdisk_kernel(task.context, task.node, instance_image_info)

            # If it's going to PXE boot we need to update the DHCP server
            dhcp_opts = pxe_utils.dhcp_options_for_instance(task)
            provider = dhcp_factory.DHCPFactory()
            provider.update_dhcp(task, dhcp_opts)

            iwdi = task.node.driver_internal_info.get('is_whole_disk_image')
            try:
                root_uuid_or_disk_id = task.node.driver_internal_info[
                    'root_uuid_or_disk_id']
            except KeyError:
                if not iwdi:
                    LOG.warn(
                        _LW("The UUID for the root partition can't be "
                            "found, unable to switch the pxe config from "
                            "deployment mode to service (boot) mode for "
                            "node %(node)s"), {"node": task.node.uuid})
                else:
                    LOG.warn(
                        _LW("The disk id for the whole disk image can't "
                            "be found, unable to switch the pxe config "
                            "from deployment mode to service (boot) mode "
                            "for node %(node)s"), {"node": task.node.uuid})
            else:
                pxe_config_path = pxe_utils.get_pxe_config_file_path(
                    task.node.uuid)
                deploy_utils.switch_pxe_config(
                    pxe_config_path, root_uuid_or_disk_id,
                    deploy_utils.get_boot_mode_for_deploy(node), iwdi,
                    deploy_utils.is_trusted_boot_requested(node))

        else:
            # If it's going to boot from the local disk, we don't need
            # PXE config files. They still need to be generated as part
            # of the prepare() because the deployment does PXE boot the
            # deploy ramdisk
            pxe_utils.clean_up_pxe_config(task)
Ejemplo n.º 23
0
 def test_prepare_instance_netboot_iscsi(self, get_image_info_mock,
                                         cache_mock, dhcp_factory_mock,
                                         switch_pxe_config_mock,
                                         set_boot_device_mock,
                                         create_pxe_config_mock):
     http_url = 'http://192.1.2.3:1234'
     self.config(http_url=http_url, group='deploy')
     provider_mock = mock.MagicMock()
     dhcp_factory_mock.return_value = provider_mock
     vol_id = uuidutils.generate_uuid()
     obj_utils.create_test_volume_target(self.context,
                                         node_id=self.node.id,
                                         volume_type='iscsi',
                                         boot_index=0,
                                         volume_id='1234',
                                         uuid=vol_id,
                                         properties={
                                             'target_lun': 0,
                                             'target_portal':
                                             'fake_host:3260',
                                             'target_iqn': 'fake_iqn',
                                             'auth_username':
                                             '******',
                                             'auth_password':
                                             '******'
                                         })
     with task_manager.acquire(self.context, self.node.uuid) as task:
         task.node.driver_internal_info = {'boot_from_volume': vol_id}
         dhcp_opts = pxe_utils.dhcp_options_for_instance(task,
                                                         ipxe_enabled=True)
         dhcp_opts += pxe_utils.dhcp_options_for_instance(task,
                                                          ipxe_enabled=True,
                                                          ip_version=6)
         pxe_config_path = pxe_utils.get_pxe_config_file_path(
             task.node.uuid, ipxe_enabled=True)
         task.node.properties['capabilities'] = 'boot_mode:bios'
         task.driver.boot.prepare_instance(task)
         self.assertFalse(get_image_info_mock.called)
         self.assertFalse(cache_mock.called)
         provider_mock.update_dhcp.assert_called_once_with(task, dhcp_opts)
         create_pxe_config_mock.assert_called_once_with(
             task,
             mock.ANY,
             CONF.pxe.pxe_config_template,
             ipxe_enabled=True)
         switch_pxe_config_mock.assert_called_once_with(
             pxe_config_path,
             None,
             boot_modes.LEGACY_BIOS,
             False,
             ipxe_enabled=True,
             iscsi_boot=True,
             ramdisk_boot=False)
         set_boot_device_mock.assert_called_once_with(task,
                                                      boot_devices.PXE,
                                                      persistent=True)
Ejemplo n.º 24
0
    def _test_continue_deploy(self, is_localboot, mock_image_cache,
                              mock_switch_config, notify_mock,
                              mock_node_boot_dev, mock_clean_pxe):
        token_path = self._create_token_file()

        # set local boot
        if is_localboot:
            i_info = self.node.instance_info
            i_info['capabilities'] = '{"boot_option": "local"}'
            self.node.instance_info = i_info

        self.node.power_state = states.POWER_ON
        self.node.provision_state = states.DEPLOYWAIT
        self.node.target_provision_state = states.ACTIVE
        self.node.save()

        root_uuid = "12345678-1234-1234-1234-1234567890abcxyz"
        boot_mode = None

        def fake_deploy(**kwargs):
            return root_uuid

        self.useFixture(
            fixtures.MonkeyPatch('ironic.drivers.modules.deploy_utils.deploy',
                                 fake_deploy))

        with task_manager.acquire(self.context, self.node.uuid) as task:
            task.driver.vendor._continue_deploy(task,
                                                address='123456',
                                                iqn='aaa-bbb',
                                                key='fake-56789')

        self.node.refresh()
        self.assertEqual(states.ACTIVE, self.node.provision_state)
        self.assertEqual(states.NOSTATE, self.node.target_provision_state)
        self.assertEqual(states.POWER_ON, self.node.power_state)
        self.assertIn('root_uuid', self.node.driver_internal_info)
        self.assertIsNone(self.node.last_error)
        self.assertFalse(os.path.exists(token_path))
        mock_image_cache.assert_called_once_with()
        mock_image_cache.return_value.clean_up.assert_called_once_with()
        pxe_config_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
        notify_mock.assert_called_once_with('123456')
        if is_localboot:
            mock_node_boot_dev.assert_called_once_with(mock.ANY,
                                                       boot_devices.DISK,
                                                       persistent=True)
            mock_clean_pxe.assert_called_once_with(mock.ANY)
            self.assertFalse(mock_switch_config.called)
        else:
            mock_switch_config.assert_called_once_with(pxe_config_path,
                                                       root_uuid, boot_mode)
            self.assertFalse(mock_node_boot_dev.called)
            self.assertFalse(mock_clean_pxe.called)
Ejemplo n.º 25
0
    def test_prepare_instance_netboot_active(self, get_image_info_mock,
                                             cache_mock, dhcp_factory_mock,
                                             switch_pxe_config_mock,
                                             set_boot_device_mock,
                                             create_pxe_config_mock,
                                             isfile_mock):
        provider_mock = mock.MagicMock()
        dhcp_factory_mock.return_value = provider_mock
        image_info = {
            'kernel': ('', '/path/to/kernel'),
            'ramdisk': ('', '/path/to/ramdisk')
        }
        instance_info = {"boot_option": "netboot"}
        get_image_info_mock.return_value = image_info
        self.node.provision_state = states.ACTIVE
        self.node.save()
        with task_manager.acquire(self.context, self.node.uuid) as task:
            dhcp_opts = pxe_utils.dhcp_options_for_instance(task,
                                                            ipxe_enabled=True)
            dhcp_opts += pxe_utils.dhcp_options_for_instance(task,
                                                             ipxe_enabled=True,
                                                             ip_version=6)
            pxe_config_path = pxe_utils.get_pxe_config_file_path(
                task.node.uuid, ipxe_enabled=True)
            task.node.properties['capabilities'] = 'boot_mode:bios'
            task.node.instance_info['capabilities'] = instance_info
            task.node.driver_internal_info['root_uuid_or_disk_id'] = (
                "30212642-09d3-467f-8e09-21685826ab50")
            task.node.driver_internal_info['is_whole_disk_image'] = False

            task.driver.boot.prepare_instance(task)

            get_image_info_mock.assert_called_once_with(task,
                                                        ipxe_enabled=True)
            cache_mock.assert_called_once_with(task,
                                               image_info,
                                               ipxe_enabled=True)
            provider_mock.update_dhcp.assert_called_once_with(task, dhcp_opts)
            create_pxe_config_mock.assert_called_once_with(
                task,
                mock.ANY,
                CONF.pxe.pxe_config_template,
                ipxe_enabled=True)
            switch_pxe_config_mock.assert_called_once_with(
                pxe_config_path,
                "30212642-09d3-467f-8e09-21685826ab50",
                'bios',
                False,
                False,
                False,
                False,
                ipxe_enabled=True)
            self.assertFalse(set_boot_device_mock.called)
Ejemplo n.º 26
0
    def test_create_pxe_config(self, ensure_tree_mock, build_mock, write_mock):
        build_mock.return_value = self.pxe_options
        with task_manager.acquire(self.context, self.node.uuid) as task:
            pxe_utils.create_pxe_config(task, self.pxe_options, CONF.pxe.pxe_config_template)
            build_mock.assert_called_with(self.pxe_options, CONF.pxe.pxe_config_template)
        ensure_calls = [
            mock.call(os.path.join(CONF.pxe.tftp_root, self.node.uuid)),
            mock.call(os.path.join(CONF.pxe.tftp_root, "pxelinux.cfg")),
        ]
        ensure_tree_mock.has_calls(ensure_calls)

        pxe_cfg_file_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
        write_mock.assert_called_with(pxe_cfg_file_path, self.pxe_options)
Ejemplo n.º 27
0
    def _test_continue_deploy(self, is_localboot, mock_image_cache,
                              mock_switch_config, notify_mock,
                              mock_node_boot_dev, mock_clean_pxe):
        token_path = self._create_token_file()

        # set local boot
        if is_localboot:
            i_info = self.node.instance_info
            i_info['capabilities'] = '{"boot_option": "local"}'
            self.node.instance_info = i_info

        self.node.power_state = states.POWER_ON
        self.node.provision_state = states.DEPLOYWAIT
        self.node.target_provision_state = states.ACTIVE
        self.node.save()

        root_uuid = "12345678-1234-1234-1234-1234567890abcxyz"
        boot_mode = None

        def fake_deploy(**kwargs):
            return root_uuid

        self.useFixture(fixtures.MonkeyPatch(
                'ironic.drivers.modules.deploy_utils.deploy',
                fake_deploy))

        with task_manager.acquire(self.context, self.node.uuid) as task:
            task.driver.vendor._continue_deploy(
                    task, address='123456', iqn='aaa-bbb', key='fake-56789')

        self.node.refresh()
        self.assertEqual(states.ACTIVE, self.node.provision_state)
        self.assertEqual(states.NOSTATE, self.node.target_provision_state)
        self.assertEqual(states.POWER_ON, self.node.power_state)
        self.assertIsNone(self.node.last_error)
        self.assertFalse(os.path.exists(token_path))
        mock_image_cache.assert_called_once_with()
        mock_image_cache.return_value.clean_up.assert_called_once_with()
        pxe_config_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
        notify_mock.assert_called_once_with('123456')
        if is_localboot:
            mock_node_boot_dev.assert_called_once_with(
                mock.ANY, boot_devices.DISK, persistent=True)
            mock_clean_pxe.assert_called_once_with(mock.ANY)
            self.assertFalse(mock_switch_config.called)
        else:
            mock_switch_config.assert_called_once_with(
                pxe_config_path, root_uuid, boot_mode)
            self.assertFalse(mock_node_boot_dev.called)
            self.assertFalse(mock_clean_pxe.called)
Ejemplo n.º 28
0
    def _continue_deploy(self, task, **kwargs):
        """Continues the deployment of baremetal node over iSCSI.

        This method continues the deployment of the baremetal node over iSCSI
        from where the deployment ramdisk has left off.

        :param task: a TaskManager instance containing the node to act on.
        :param kwargs: kwargs for performing iscsi deployment.
        :raises: InvalidState
        """
        node = task.node
        task.process_event('resume')

        _destroy_token_file(node)

        root_uuid = iscsi_deploy.continue_deploy(task, **kwargs)

        if not root_uuid:
            return

        # save the node's root disk UUID so that another conductor could
        # rebuild the PXE config file. Due to a shortcoming in Nova objects,
        # we have to assign to node.driver_internal_info so the node knows it
        # has changed.
        driver_internal_info = node.driver_internal_info
        driver_internal_info['root_uuid'] = root_uuid
        node.driver_internal_info = driver_internal_info
        node.save()

        try:
            if iscsi_deploy.get_boot_option(node) == "local":
                try_set_boot_device(task, boot_devices.DISK)
                # If it's going to boot from the local disk, get rid of
                # the PXE configuration files used for the deployment
                pxe_utils.clean_up_pxe_config(task)
            else:
                pxe_config_path = pxe_utils.get_pxe_config_file_path(node.uuid)
                deploy_utils.switch_pxe_config(pxe_config_path, root_uuid,
                    driver_utils.get_node_capability(node, 'boot_mode'))

            deploy_utils.notify_deploy_complete(kwargs['address'])
            LOG.info(_LI('Deployment to node %s done'), node.uuid)
            task.process_event('done')
        except Exception as e:
            LOG.error(_LE('Deploy failed for instance %(instance)s. '
                          'Error: %(error)s'),
                      {'instance': node.instance_uuid, 'error': e})
            msg = _('Failed to continue iSCSI deployment.')
            deploy_utils.set_failed_state(task, msg)
Ejemplo n.º 29
0
    def test_create_pxe_config(self, ensure_tree_mock, build_mock, write_mock):
        build_mock.return_value = self.pxe_options
        with task_manager.acquire(self.context, self.node.uuid) as task:
            pxe_utils.create_pxe_config(task, self.pxe_options,
                                        CONF.pxe.pxe_config_template)
            build_mock.assert_called_with(self.pxe_options,
                                          CONF.pxe.pxe_config_template)
        ensure_calls = [
            mock.call(os.path.join(CONF.pxe.tftp_root, self.node.uuid)),
            mock.call(os.path.join(CONF.pxe.tftp_root, 'pxelinux.cfg'))
        ]
        ensure_tree_mock.assert_has_calls(ensure_calls)

        pxe_cfg_file_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
        write_mock.assert_called_with(pxe_cfg_file_path, self.pxe_options)
Ejemplo n.º 30
0
    def continue_deploy(self, task, **kwargs):
        """Method invoked when deployed with the IPA ramdisk.

        This method is invoked during a heartbeat from an agent when
        the node is in wait-call-back state. This deploys the image on
        the node and then configures the node to boot according to the
        desired boot option (netboot or localboot).

        :param task: a TaskManager object containing the node.
        :param kwargs: the kwargs passed from the heartbeat method.
        :raises: InstanceDeployFailure, if it encounters some error during
            the deploy.
        """
        task.process_event('resume')
        node = task.node
        LOG.debug('Continuing the deployment on node %s', node.uuid)

        # NOTE(lucasagomes): We don't use the token file with the agent,
        # but as it's created as part of deploy() we are going to remove
        # it here.
        _destroy_token_file(node)

        uuid_dict = iscsi_deploy.do_agent_iscsi_deploy(task, self._client)

        is_whole_disk_image = node.driver_internal_info['is_whole_disk_image']
        if iscsi_deploy.get_boot_option(node) == "local":
            # Install the boot loader
            root_uuid = uuid_dict.get('root uuid')
            efi_sys_uuid = uuid_dict.get('efi system partition uuid')
            self.configure_local_boot(task,
                                      root_uuid=root_uuid,
                                      efi_system_part_uuid=efi_sys_uuid)

            # If it's going to boot from the local disk, get rid of
            # the PXE configuration files used for the deployment
            pxe_utils.clean_up_pxe_config(task)
        else:
            root_uuid_or_disk_id = uuid_dict.get(
                'root uuid', uuid_dict.get('disk identifier'))
            pxe_config_path = pxe_utils.get_pxe_config_file_path(node.uuid)
            boot_mode = deploy_utils.get_boot_mode_for_deploy(node)
            deploy_utils.switch_pxe_config(pxe_config_path,
                                           root_uuid_or_disk_id, boot_mode,
                                           is_whole_disk_image)

        self.reboot_and_finish_deploy(task)
Ejemplo n.º 31
0
    def continue_deploy(self, task, **kwargs):
        """Method invoked when deployed with the IPA ramdisk.

        This method is invoked during a heartbeat from an agent when
        the node is in wait-call-back state. This deploys the image on
        the node and then configures the node to boot according to the
        desired boot option (netboot or localboot).

        :param task: a TaskManager object containing the node.
        :param kwargs: the kwargs passed from the heartbeat method.
        :raises: InstanceDeployFailure, if it encounters some error during
            the deploy.
        """
        task.process_event('resume')
        node = task.node
        LOG.debug('Continuing the deployment on node %s', node.uuid)

        # NOTE(lucasagomes): We don't use the token file with the agent,
        # but as it's created as part of deploy() we are going to remove
        # it here.
        _destroy_token_file(node)

        uuid_dict = iscsi_deploy.do_agent_iscsi_deploy(task, self._client)

        is_whole_disk_image = node.driver_internal_info['is_whole_disk_image']
        if iscsi_deploy.get_boot_option(node) == "local":
            # Install the boot loader
            root_uuid = uuid_dict.get('root uuid')
            efi_sys_uuid = uuid_dict.get('efi system partition uuid')
            self.configure_local_boot(
                task, root_uuid=root_uuid,
                efi_system_part_uuid=efi_sys_uuid)

            # If it's going to boot from the local disk, get rid of
            # the PXE configuration files used for the deployment
            pxe_utils.clean_up_pxe_config(task)
        else:
            root_uuid_or_disk_id = uuid_dict.get(
                'root uuid', uuid_dict.get('disk identifier'))
            pxe_config_path = pxe_utils.get_pxe_config_file_path(node.uuid)
            boot_mode = deploy_utils.get_boot_mode_for_deploy(node)
            deploy_utils.switch_pxe_config(pxe_config_path,
                                           root_uuid_or_disk_id,
                                           boot_mode, is_whole_disk_image)

        self.reboot_and_finish_deploy(task)
Ejemplo n.º 32
0
    def _link_mac_pxe_configs(self, task):
        def create_link(mac_path):
            ironic_utils.unlink_without_raise(mac_path)
            relative_source_path = os.path.relpath(pxe_config_file_path,
                                                   os.path.dirname(mac_path))
            utils.create_link_without_raise(relative_source_path, mac_path)

        pxe_config_file_path = pxe_utils.get_pxe_config_file_path(
            task.node.uuid)
        pxe_boot_interface_mac = self._get_boot_interface_mac(task)
        LOG.info("pxe_boot_interface_mac: %s", pxe_boot_interface_mac)
        for port in task.ports:
            LOG.info("port.address: %s", port.address)
            if port.address == pxe_boot_interface_mac:
                client_id = port.extra.get('client-id')
                create_link(
                    self._get_pxe_mac_path(port.address, client_id=client_id))
Ejemplo n.º 33
0
def _build_service_pxe_config(task, instance_image_info, root_uuid_or_disk_id):
    node = task.node
    pxe_config_path = pxe_utils.get_pxe_config_file_path(node.uuid)
    # NOTE(pas-ha) if it is takeover of ACTIVE node,
    # first ensure that basic PXE configs and links
    # are in place before switching pxe config
    if (node.provision_state == states.ACTIVE
            and not os.path.isfile(pxe_config_path)):
        pxe_options = _build_pxe_config_options(task,
                                                instance_image_info,
                                                service=True)
        pxe_config_template = deploy_utils.get_pxe_config_template(node)
        pxe_utils.create_pxe_config(task, pxe_options, pxe_config_template)
    iwdi = node.driver_internal_info.get('is_whole_disk_image')
    deploy_utils.switch_pxe_config(
        pxe_config_path, root_uuid_or_disk_id,
        deploy_utils.get_boot_mode_for_deploy(node), iwdi,
        deploy_utils.is_trusted_boot_requested(node))
Ejemplo n.º 34
0
    def _continue_deploy(self, task, **kwargs):
        """Continues the deployment of baremetal node over iSCSI.

        This method continues the deployment of the baremetal node over iSCSI
        from where the deployment ramdisk has left off.

        :param task: a TaskManager instance containing the node to act on.
        :param kwargs: kwargs for performing iscsi deployment.
        """
        node = task.node

        if node.provision_state != states.DEPLOYWAIT:
            LOG.error(_LE('Node %s is not waiting to be deployed.'), node.uuid)
            return

        _destroy_token_file(node)

        root_uuid = iscsi_deploy.continue_deploy(task, **kwargs)

        if not root_uuid:
            return

        try:
            pxe_config_path = pxe_utils.get_pxe_config_file_path(node.uuid)
            deploy_utils.switch_pxe_config(
                pxe_config_path, root_uuid,
                driver_utils.get_node_capability(node, 'boot_mode'))

            deploy_utils.notify_deploy_complete(kwargs['address'])

            LOG.info(_LI('Deployment to node %s done'), node.uuid)
            node.provision_state = states.ACTIVE
            node.target_provision_state = states.NOSTATE
            node.save()
        except Exception as e:

            LOG.error(
                _LE('Deploy failed for instance %(instance)s. '
                    'Error: %(error)s'), {
                        'instance': node.instance_uuid,
                        'error': e
                    })
            msg = _('Failed to continue iSCSI deployment.')
            iscsi_deploy.set_failed_state(task, msg)
Ejemplo n.º 35
0
def _build_service_pxe_config(task, instance_image_info,
                              root_uuid_or_disk_id):
    node = task.node
    pxe_config_path = pxe_utils.get_pxe_config_file_path(node.uuid)
    # NOTE(pas-ha) if it is takeover of ACTIVE node,
    # first ensure that basic PXE configs and links
    # are in place before switching pxe config
    if (node.provision_state == states.ACTIVE and
            not os.path.isfile(pxe_config_path)):
        pxe_options = _build_pxe_config_options(task, instance_image_info,
                                                service=True)
        pxe_config_template = deploy_utils.get_pxe_config_template(node)
        pxe_utils.create_pxe_config(task, pxe_options, pxe_config_template)
    iwdi = node.driver_internal_info.get('is_whole_disk_image')
    deploy_utils.switch_pxe_config(
        pxe_config_path, root_uuid_or_disk_id,
        deploy_utils.get_boot_mode_for_deploy(node),
        iwdi, deploy_utils.is_trusted_boot_requested(node),
        deploy_utils.is_iscsi_boot(task))
Ejemplo n.º 36
0
    def continue_deploy(self, task, **kwargs):
        """Method invoked when deployed with the IPA ramdisk.

        This method is invoked during a heartbeat from an agent when
        the node is in wait-call-back state. This deploys the image on
        the node and then configures the node to boot according to the
        desired boot option (netboot or localboot).

        :param task: a TaskManager object containing the node.
        :param kwargs: the kwargs passed from the heartbeat method.
        :raises: InstanceDeployFailure, if it encounters some error during
            the deploy.
        """
        task.process_event("resume")
        node = task.node
        LOG.debug("Continuing the deployment on node %s", node.uuid)

        uuid_dict = iscsi_deploy.do_agent_iscsi_deploy(task, self._client)

        is_whole_disk_image = node.driver_internal_info["is_whole_disk_image"]
        if iscsi_deploy.get_boot_option(node) == "local":
            # Install the boot loader
            root_uuid = uuid_dict.get("root uuid")
            efi_sys_uuid = uuid_dict.get("efi system partition uuid")
            self.configure_local_boot(task, root_uuid=root_uuid, efi_system_part_uuid=efi_sys_uuid)

            # If it's going to boot from the local disk, get rid of
            # the PXE configuration files used for the deployment
            pxe_utils.clean_up_pxe_config(task)
        else:
            root_uuid_or_disk_id = uuid_dict.get("root uuid", uuid_dict.get("disk identifier"))
            pxe_config_path = pxe_utils.get_pxe_config_file_path(node.uuid)
            boot_mode = deploy_utils.get_boot_mode_for_deploy(node)
            deploy_utils.switch_pxe_config(
                pxe_config_path,
                root_uuid_or_disk_id,
                boot_mode,
                is_whole_disk_image,
                deploy_utils.is_trusted_boot_requested(node),
            )

        self.reboot_and_finish_deploy(task)
Ejemplo n.º 37
0
    def _create_pxe_config(self, task):
        pxe_options = self._build_pxe_options(task.node)

        pxe_config_template = CONF.pxe.pxe_config_template
        node_uuid = task.node.uuid
        root_dir = CONF.pxe.tftp_root
        fileutils.ensure_tree(os.path.join(root_dir, node_uuid))
        fileutils.ensure_tree(os.path.join(root_dir, PXE_CFG_DIR_NAME))

        pxe_config_file_path = pxe_utils.get_pxe_config_file_path(node_uuid)
        tmpl_path, tmpl_file = os.path.split(pxe_config_template)
        env = jinja2.Environment(loader=jinja2.FileSystemLoader(tmpl_path))
        template = env.get_template(tmpl_file)
        pxe_config = template.render({
            'pxe_options': pxe_options,
            'server_ip': CONF.my_ip,
            'UUID': node_uuid,
        })
        utils.write_to_file(pxe_config_file_path, pxe_config)
        self._link_mac_pxe_configs(task)
Ejemplo n.º 38
0
    def clean_up(self, task):

        extra_info = task.node.extra
        pxe_boot_interface_mac = extra_info.get('boot_detailed').get(
            'pxe_interface')
        pxe_boot_interface_mac.replace('-', ':')
        for port in task.ports:
            if port.address == pxe_boot_interface_mac:
                client_id = port.extra.get('client-id')
                ironic_utils.unlink_without_raise(
                    self._get_pxe_mac_path(port.address, client_id=client_id))

        pxe_config_file_path = pxe_utils.get_pxe_config_file_path(
            task.node.uuid)
        fileutils.delete_if_exists(pxe_config_file_path)
        if os.path.exists(os.path.join(CONF.pxe.tftp_root, task.node.uuid)):
            rmtree(os.path.join(CONF.pxe.tftp_root, task.node.uuid))

        auto_file_name = task.node.uuid + '_auto.cfg'
        fileutils.delete_if_exists(AUTO_FILE_DIR + auto_file_name)
Ejemplo n.º 39
0
    def test_create_pxe_config(self, ensure_tree_mock, render_mock,
                               write_mock):
        with task_manager.acquire(self.context, self.node.uuid) as task:
            pxe_utils.create_pxe_config(task, self.pxe_options,
                                        CONF.pxe.pxe_config_template)
            render_mock.assert_called_with(
                CONF.pxe.pxe_config_template, {
                    'pxe_options': self.pxe_options,
                    'ROOT': '{{ ROOT }}',
                    'DISK_IDENTIFIER': '{{ DISK_IDENTIFIER }}'
                })
        ensure_calls = [
            mock.call(os.path.join(CONF.pxe.tftp_root, self.node.uuid)),
            mock.call(os.path.join(CONF.pxe.tftp_root, 'pxelinux.cfg'))
        ]
        ensure_tree_mock.assert_has_calls(ensure_calls)

        pxe_cfg_file_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
        write_mock.assert_called_with(pxe_cfg_file_path,
                                      render_mock.return_value)
Ejemplo n.º 40
0
 def test_create_pxe_config_existing_dirs(self, ensure_tree_mock,
                                          render_mock, write_mock,
                                          chmod_mock, isdir_mock):
     self.config(dir_permission=0o755, group='pxe')
     with task_manager.acquire(self.context, self.node.uuid) as task:
         isdir_mock.return_value = True
         pxe_utils.create_pxe_config(task, self.pxe_options,
                                     CONF.pxe.pxe_config_template)
         render_mock.assert_called_with(
             CONF.pxe.pxe_config_template, {
                 'pxe_options': self.pxe_options,
                 'ROOT': '{{ ROOT }}',
                 'DISK_IDENTIFIER': '{{ DISK_IDENTIFIER }}'
             })
     ensure_tree_mock.assert_has_calls([])
     chmod_mock.assert_not_called()
     isdir_mock.assert_has_calls([])
     pxe_cfg_file_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
     write_mock.assert_called_with(pxe_cfg_file_path,
                                   render_mock.return_value)
Ejemplo n.º 41
0
 def test_create_pxe_config_existing_dirs(self, ensure_tree_mock,
                                          render_mock,
                                          write_mock, chmod_mock,
                                          isdir_mock):
     self.config(dir_permission=0o755, group='pxe')
     with task_manager.acquire(self.context, self.node.uuid) as task:
         isdir_mock.return_value = True
         pxe_utils.create_pxe_config(task, self.pxe_options,
                                     CONF.pxe.pxe_config_template)
         render_mock.assert_called_with(
             CONF.pxe.pxe_config_template,
             {'pxe_options': self.pxe_options,
              'ROOT': '{{ ROOT }}',
              'DISK_IDENTIFIER': '{{ DISK_IDENTIFIER }}'}
         )
     ensure_tree_mock.assert_has_calls([])
     chmod_mock.assert_not_called()
     isdir_mock.assert_has_calls([])
     pxe_cfg_file_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
     write_mock.assert_called_with(pxe_cfg_file_path,
                                   render_mock.return_value)
Ejemplo n.º 42
0
    def test_create_pxe_config_uefi_elilo(self, ensure_tree_mock, build_mock,
                                          write_mock, link_ip_configs_mock):
        build_mock.return_value = self.pxe_options_uefi
        with task_manager.acquire(self.context, self.node.uuid) as task:
            task.node.properties['capabilities'] = 'boot_mode:uefi'
            pxe_utils.create_pxe_config(task, self.pxe_options_uefi,
                                        CONF.pxe.uefi_pxe_config_template)

            ensure_calls = [
                mock.call(os.path.join(CONF.pxe.tftp_root, self.node.uuid)),
                mock.call(os.path.join(CONF.pxe.tftp_root, 'pxelinux.cfg'))
            ]
            ensure_tree_mock.assert_has_calls(ensure_calls)
            build_mock.assert_called_with(self.pxe_options_uefi,
                                          CONF.pxe.uefi_pxe_config_template,
                                          '{{ ROOT }}',
                                          '{{ DISK_IDENTIFIER }}')
            link_ip_configs_mock.assert_called_once_with(task, True)

        pxe_cfg_file_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
        write_mock.assert_called_with(pxe_cfg_file_path, self.pxe_options_uefi)
Ejemplo n.º 43
0
    def test_create_pxe_config_uefi_elilo(self, ensure_tree_mock, build_mock,
                                          write_mock, link_ip_configs_mock):
        build_mock.return_value = self.pxe_options_uefi
        with task_manager.acquire(self.context, self.node.uuid) as task:
            task.node.properties['capabilities'] = 'boot_mode:uefi'
            pxe_utils.create_pxe_config(task, self.pxe_options_uefi,
                                        CONF.pxe.uefi_pxe_config_template)

            ensure_calls = [
                mock.call(os.path.join(CONF.pxe.tftp_root, self.node.uuid)),
                mock.call(os.path.join(CONF.pxe.tftp_root, 'pxelinux.cfg'))
            ]
            ensure_tree_mock.assert_has_calls(ensure_calls)
            build_mock.assert_called_with(self.pxe_options_uefi,
                                          CONF.pxe.uefi_pxe_config_template,
                                          '{{ ROOT }}',
                                          '{{ DISK_IDENTIFIER }}')
            link_ip_configs_mock.assert_called_once_with(task, True)

        pxe_cfg_file_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
        write_mock.assert_called_with(pxe_cfg_file_path, self.pxe_options_uefi)
Ejemplo n.º 44
0
    def _continue_deploy(self, task, **kwargs):
        """Continues the deployment of baremetal node over iSCSI.

        This method continues the deployment of the baremetal node over iSCSI
        from where the deployment ramdisk has left off.

        :param task: a TaskManager instance containing the node to act on.
        :param kwargs: kwargs for performing iscsi deployment.
        """
        node = task.node

        if node.provision_state != states.DEPLOYWAIT:
            LOG.error(_LE('Node %s is not waiting to be deployed.'), node.uuid)
            return

        _destroy_token_file(node)

        root_uuid = iscsi_deploy.continue_deploy(task, **kwargs)

        if not root_uuid:
            return

        try:
            pxe_config_path = pxe_utils.get_pxe_config_file_path(node.uuid)
            deploy_utils.switch_pxe_config(pxe_config_path, root_uuid,
                          driver_utils.get_node_capability(node, 'boot_mode'))

            deploy_utils.notify_deploy_complete(kwargs['address'])

            LOG.info(_LI('Deployment to node %s done'), node.uuid)
            node.provision_state = states.ACTIVE
            node.target_provision_state = states.NOSTATE
            node.save()
        except Exception as e:

            LOG.error(_LE('Deploy failed for instance %(instance)s. '
                          'Error: %(error)s'),
                      {'instance': node.instance_uuid, 'error': e})
            msg = _('Failed to continue iSCSI deployment.')
            iscsi_deploy.set_failed_state(task, msg)
Ejemplo n.º 45
0
    def _continue_deploy(self, task, **kwargs):
        """Continues the deployment of baremetal node over iSCSI.

        This method continues the deployment of the baremetal node over iSCSI
        from where the deployment ramdisk has left off.

        :param task: a TaskManager instance containing the node to act on.
        :param kwargs: kwargs for performing iscsi deployment.
        :raises: InvalidState
        """
        node = task.node
        task.process_event('resume')

        _destroy_token_file(node)

        root_uuid = iscsi_deploy.continue_deploy(task, **kwargs)

        if not root_uuid:
            return

        try:
            if iscsi_deploy.get_boot_option(node) == "local":
                try_set_boot_device(task, boot_devices.DISK)
                # If it's going to boot from the local disk, get rid of
                # the PXE configuration files used for the deployment
                pxe_utils.clean_up_pxe_config(task)
            else:
                pxe_config_path = pxe_utils.get_pxe_config_file_path(node.uuid)
                deploy_utils.switch_pxe_config(pxe_config_path, root_uuid,
                    driver_utils.get_node_capability(node, 'boot_mode'))

            deploy_utils.notify_deploy_complete(kwargs['address'])
            LOG.info(_LI('Deployment to node %s done'), node.uuid)
            task.process_event('done')
        except Exception as e:
            LOG.error(_LE('Deploy failed for instance %(instance)s. '
                          'Error: %(error)s'),
                      {'instance': node.instance_uuid, 'error': e})
            msg = _('Failed to continue iSCSI deployment.')
            deploy_utils.set_failed_state(task, msg)
Ejemplo n.º 46
0
 def test_prepare_instance_netboot_iscsi(
         self, get_image_info_mock, cache_mock,
         dhcp_factory_mock, switch_pxe_config_mock,
         set_boot_device_mock, create_pxe_config_mock):
     http_url = 'http://192.1.2.3:1234'
     self.config(ipxe_enabled=False, group='pxe')
     self.config(http_url=http_url, group='deploy')
     provider_mock = mock.MagicMock()
     dhcp_factory_mock.return_value = provider_mock
     vol_id = uuidutils.generate_uuid()
     obj_utils.create_test_volume_target(
         self.context, node_id=self.node.id, volume_type='iscsi',
         boot_index=0, volume_id='1234', uuid=vol_id,
         properties={'target_lun': 0,
                     'target_portal': 'fake_host:3260',
                     'target_iqn': 'fake_iqn',
                     'auth_username': '******',
                     'auth_password': '******'})
     with task_manager.acquire(self.context, self.node.uuid) as task:
         task.node.driver_internal_info = {
             'boot_from_volume': vol_id}
         dhcp_opts = pxe_utils.dhcp_options_for_instance(task,
                                                         ipxe_enabled=True)
         pxe_config_path = pxe_utils.get_pxe_config_file_path(
             task.node.uuid)
         task.node.properties['capabilities'] = 'boot_mode:bios'
         task.driver.boot.prepare_instance(task)
         self.assertFalse(get_image_info_mock.called)
         self.assertFalse(cache_mock.called)
         provider_mock.update_dhcp.assert_called_once_with(task, dhcp_opts)
         create_pxe_config_mock.assert_called_once_with(
             task, mock.ANY, CONF.pxe.pxe_config_template,
             ipxe_enabled=True)
         switch_pxe_config_mock.assert_called_once_with(
             pxe_config_path, None, boot_modes.LEGACY_BIOS, False,
             ipxe_enabled=True, iscsi_boot=True, ramdisk_boot=False)
         set_boot_device_mock.assert_called_once_with(task,
                                                      boot_devices.PXE,
                                                      persistent=True)
Ejemplo n.º 47
0
 def test_prepare_instance_netboot_ramdisk(
         self, get_image_info_mock, cache_mock,
         dhcp_factory_mock, switch_pxe_config_mock,
         set_boot_device_mock, create_pxe_config_mock):
     http_url = 'http://192.1.2.3:1234'
     self.config(http_url=http_url, group='deploy')
     provider_mock = mock.MagicMock()
     dhcp_factory_mock.return_value = provider_mock
     self.node.instance_info = {'boot_iso': 'http://1.2.3.4:1234/boot.iso',
                                'capabilities': {'boot_option': 'ramdisk'}}
     image_info = {'kernel': ('', '/path/to/kernel'),
                   'deploy_kernel': ('', '/path/to/kernel'),
                   'ramdisk': ('', '/path/to/ramdisk'),
                   'deploy_ramdisk': ('', '/path/to/ramdisk')}
     get_image_info_mock.return_value = image_info
     self.node.provision_state = states.DEPLOYING
     self.node.save()
     with task_manager.acquire(self.context, self.node.uuid) as task:
         print(task.node)
         dhcp_opts = pxe_utils.dhcp_options_for_instance(task,
                                                         ipxe_enabled=True)
         dhcp_opts += pxe_utils.dhcp_options_for_instance(
             task, ipxe_enabled=True, ip_version=6)
         pxe_config_path = pxe_utils.get_pxe_config_file_path(
             task.node.uuid, ipxe_enabled=True)
         task.driver.boot.prepare_instance(task)
         self.assertTrue(get_image_info_mock.called)
         self.assertTrue(cache_mock.called)
         provider_mock.update_dhcp.assert_called_once_with(task, dhcp_opts)
         create_pxe_config_mock.assert_called_once_with(
             task, mock.ANY, CONF.pxe.ipxe_config_template,
             ipxe_enabled=True)
         switch_pxe_config_mock.assert_called_once_with(
             pxe_config_path, None, boot_modes.LEGACY_BIOS, False,
             ipxe_enabled=True, iscsi_boot=False, ramdisk_boot=True)
         set_boot_device_mock.assert_called_once_with(task,
                                                      boot_devices.PXE,
                                                      persistent=True)
Ejemplo n.º 48
0
 def test_get_pxe_config_file_path(self):
     self.assertEqual(
         os.path.join(CONF.pxe.tftp_root, self.node.uuid, 'config'),
         pxe_utils.get_pxe_config_file_path(self.node.uuid))
Ejemplo n.º 49
0
    def prepare_instance(self, task):
        """Prepares the boot of instance.

        This method prepares the boot of the instance after reading
        relevant information from the node's instance_info. In case of netboot,
        it updates the dhcp entries and switches the PXE config. In case of
        localboot, it cleans up the PXE config.

        :param task: a task from TaskManager.
        :returns: None
        """
        node = task.node
        boot_option = deploy_utils.get_boot_option(node)
        boot_device = None

        if deploy_utils.is_iscsi_boot(task):
            dhcp_opts = pxe_utils.dhcp_options_for_instance(task)
            provider = dhcp_factory.DHCPFactory()
            provider.update_dhcp(task, dhcp_opts)

            # configure iPXE for iscsi boot
            pxe_config_path = pxe_utils.get_pxe_config_file_path(
                task.node.uuid)
            if not os.path.isfile(pxe_config_path):
                pxe_options = _build_pxe_config_options(task, {})
                pxe_config_template = (
                    deploy_utils.get_pxe_config_template(node))
                pxe_utils.create_pxe_config(
                    task, pxe_options, pxe_config_template)
            deploy_utils.switch_pxe_config(
                pxe_config_path, None,
                deploy_utils.get_boot_mode_for_deploy(node), False,
                iscsi_boot=True)
            boot_device = boot_devices.PXE

        elif boot_option != "local":
            if task.driver.storage.should_write_image(task):
                # Make sure that the instance kernel/ramdisk is cached.
                # This is for the takeover scenario for active nodes.
                instance_image_info = _get_instance_image_info(
                    task.node, task.context)
                _cache_ramdisk_kernel(task.context, task.node,
                                      instance_image_info)

            # If it's going to PXE boot we need to update the DHCP server
            dhcp_opts = pxe_utils.dhcp_options_for_instance(task)
            provider = dhcp_factory.DHCPFactory()
            provider.update_dhcp(task, dhcp_opts)

            iwdi = task.node.driver_internal_info.get('is_whole_disk_image')
            try:
                root_uuid_or_disk_id = task.node.driver_internal_info[
                    'root_uuid_or_disk_id'
                ]
            except KeyError:
                if not task.driver.storage.should_write_image(task):
                    pass
                elif not iwdi:
                    LOG.warning("The UUID for the root partition can't be "
                                "found, unable to switch the pxe config from "
                                "deployment mode to service (boot) mode for "
                                "node %(node)s", {"node": task.node.uuid})
                else:
                    LOG.warning("The disk id for the whole disk image can't "
                                "be found, unable to switch the pxe config "
                                "from deployment mode to service (boot) mode "
                                "for node %(node)s", {"node": task.node.uuid})
            else:
                _build_service_pxe_config(task, instance_image_info,
                                          root_uuid_or_disk_id)
                boot_device = boot_devices.PXE
        else:
            # If it's going to boot from the local disk, we don't need
            # PXE config files. They still need to be generated as part
            # of the prepare() because the deployment does PXE boot the
            # deploy ramdisk
            pxe_utils.clean_up_pxe_config(task)
            boot_device = boot_devices.DISK

        # NOTE(pas-ha) do not re-set boot device on ACTIVE nodes
        # during takeover
        if boot_device and task.node.provision_state != states.ACTIVE:
            manager_utils.node_set_boot_device(task, boot_device,
                                               persistent=True)
Ejemplo n.º 50
0
    def setUp(self):
        super(CleanUpFullFlowTestCase, self).setUp()
        self.config(image_cache_size=0, group='pxe')

        # Configure node
        mgr_utils.mock_the_extension_manager(driver="fake_pxe")
        instance_info = INST_INFO_DICT
        instance_info['deploy_key'] = 'fake-56789'
        self.node = obj_utils.create_test_node(self.context,
                                               driver='fake_pxe',
                                               instance_info=instance_info,
                                               driver_info=DRV_INFO_DICT)
        self.port = obj_utils.create_test_port(self.context,
                                               node_id=self.node.id)

        # Configure temporary directories
        pxe_temp_dir = tempfile.mkdtemp()
        self.config(tftp_root=pxe_temp_dir, group='pxe')
        tftp_master_dir = os.path.join(CONF.pxe.tftp_root,
                                       'tftp_master')
        self.config(tftp_master_path=tftp_master_dir, group='pxe')
        os.makedirs(tftp_master_dir)

        instance_temp_dir = tempfile.mkdtemp()
        self.config(images_path=instance_temp_dir,
                    group='pxe')
        instance_master_dir = os.path.join(CONF.pxe.images_path,
                                           'instance_master')
        self.config(instance_master_path=instance_master_dir,
                    group='pxe')
        os.makedirs(instance_master_dir)
        self.pxe_config_dir = os.path.join(CONF.pxe.tftp_root, 'pxelinux.cfg')
        os.makedirs(self.pxe_config_dir)

        # Populate some file names
        self.master_kernel_path = os.path.join(CONF.pxe.tftp_master_path,
                                               'kernel')
        self.master_instance_path = os.path.join(CONF.pxe.instance_master_path,
                                                'image_uuid')
        self.node_tftp_dir = os.path.join(CONF.pxe.tftp_root,
                                          self.node.uuid)
        os.makedirs(self.node_tftp_dir)
        self.kernel_path = os.path.join(self.node_tftp_dir,
                                        'kernel')
        self.node_image_dir = iscsi_deploy._get_image_dir_path(self.node.uuid)
        os.makedirs(self.node_image_dir)
        self.image_path = iscsi_deploy._get_image_file_path(self.node.uuid)
        self.config_path = pxe_utils.get_pxe_config_file_path(self.node.uuid)
        self.mac_path = pxe_utils._get_pxe_mac_path(self.port.address)
        self.token_path = pxe._get_token_file_path(self.node.uuid)

        # Create files
        self.files = [self.config_path, self.master_kernel_path,
                      self.master_instance_path, self.token_path]
        for fname in self.files:
            # NOTE(dtantsur): files with 0 size won't be cleaned up
            with open(fname, 'w') as fp:
                fp.write('test')

        os.link(self.config_path, self.mac_path)
        os.link(self.master_kernel_path, self.kernel_path)
        os.link(self.master_instance_path, self.image_path)
Ejemplo n.º 51
0
    def prepare_instance(self, task):
        """Prepares the boot of instance.

        This method prepares the boot of the instance after reading
        relevant information from the node's instance_info. In case of netboot,
        it updates the dhcp entries and switches the PXE config. In case of
        localboot, it cleans up the PXE config.

        :param task: a task from TaskManager.
        :returns: None
        """
        node = task.node
        boot_option = deploy_utils.get_boot_option(node)
        boot_device = None

        if deploy_utils.is_iscsi_boot(task):
            dhcp_opts = pxe_utils.dhcp_options_for_instance(task)
            provider = dhcp_factory.DHCPFactory()
            provider.update_dhcp(task, dhcp_opts)

            # configure iPXE for iscsi boot
            pxe_config_path = pxe_utils.get_pxe_config_file_path(
                task.node.uuid)
            if not os.path.isfile(pxe_config_path):
                pxe_options = _build_pxe_config_options(task, {})
                pxe_config_template = (
                    deploy_utils.get_pxe_config_template(node))
                pxe_utils.create_pxe_config(
                    task, pxe_options, pxe_config_template)
            deploy_utils.switch_pxe_config(
                pxe_config_path, None,
                deploy_utils.get_boot_mode_for_deploy(node), False,
                iscsi_boot=True)
            boot_device = boot_devices.PXE

        elif boot_option != "local":
            if task.driver.storage.should_write_image(task):
                # Make sure that the instance kernel/ramdisk is cached.
                # This is for the takeover scenario for active nodes.
                instance_image_info = _get_instance_image_info(
                    task.node, task.context)
                _cache_ramdisk_kernel(task.context, task.node,
                                      instance_image_info)

            # If it's going to PXE boot we need to update the DHCP server
            dhcp_opts = pxe_utils.dhcp_options_for_instance(task)
            provider = dhcp_factory.DHCPFactory()
            provider.update_dhcp(task, dhcp_opts)

            iwdi = task.node.driver_internal_info.get('is_whole_disk_image')
            try:
                root_uuid_or_disk_id = task.node.driver_internal_info[
                    'root_uuid_or_disk_id'
                ]
            except KeyError:
                if not task.driver.storage.should_write_image(task):
                    pass
                elif not iwdi:
                    LOG.warning("The UUID for the root partition can't be "
                                "found, unable to switch the pxe config from "
                                "deployment mode to service (boot) mode for "
                                "node %(node)s", {"node": task.node.uuid})
                else:
                    LOG.warning("The disk id for the whole disk image can't "
                                "be found, unable to switch the pxe config "
                                "from deployment mode to service (boot) mode "
                                "for node %(node)s. Booting the instance "
                                "from disk.", {"node": task.node.uuid})
                    pxe_utils.clean_up_pxe_config(task)
                    boot_device = boot_devices.DISK
            else:
                _build_service_pxe_config(task, instance_image_info,
                                          root_uuid_or_disk_id)
                boot_device = boot_devices.PXE
        else:
            # If it's going to boot from the local disk, we don't need
            # PXE config files. They still need to be generated as part
            # of the prepare() because the deployment does PXE boot the
            # deploy ramdisk
            pxe_utils.clean_up_pxe_config(task)
            boot_device = boot_devices.DISK

        # NOTE(pas-ha) do not re-set boot device on ACTIVE nodes
        # during takeover
        if boot_device and task.node.provision_state != states.ACTIVE:
            manager_utils.node_set_boot_device(task, boot_device,
                                               persistent=True)
Ejemplo n.º 52
0
 def test_get_pxe_config_file_path(self):
     self.assertEqual(os.path.join(CONF.pxe.tftp_root,
                                   self.node.uuid,
                                   'config'),
                      pxe_utils.get_pxe_config_file_path(self.node.uuid))