Exemple #1
0
    def test__build_pxe_config(self):
        instance_uuid = 'instance_uuid_123'
        CONF.set_default('pxe_append_params', 'test_param', group='pxe')

        template = 'ironic/tests/drivers/pxe_config.template'
        pxe_config_template = open(template, 'r').read()

        self.mox.StubOutWithMock(utils, 'random_alnum')

        utils.random_alnum(32).AndReturn('0123456789ABCDEFGHIJKLMNOPQRSTUV')

        image_info = {'deploy_kernel': ['deploy_kernel',
                                       CONF.pxe.tftp_root + '/' +
                                        instance_uuid + '/deploy_kernel'],
                     'deploy_ramdisk': ['deploy_ramdisk',
                                         CONF.pxe.tftp_root + '/' +
                                        instance_uuid + '/deploy_ramdisk'],
                     'kernel': ['kernel_id',
                                CONF.pxe.tftp_root + '/' + instance_uuid +
                                '/kernel'],
                     'ramdisk': ['ramdisk_id',
                                 CONF.pxe.tftp_root + '/' + instance_uuid +
                                 '/ramdisk']
        }

        self.mox.ReplayAll()

        pxe_config = pxe._build_pxe_config(self.node, image_info)

        self.assertEqual(pxe_config, pxe_config_template)
Exemple #2
0
def _build_pxe_config(node, pxe_info):
    """Build the PXE config file for a node

    This method builds the PXE boot configuration file for a node,
    given all the required parameters.

    The resulting file has both a "deploy" and "boot" label, which correspond
    to the two phases of booting. This may be extended later.

    :param pxe_options: A dict of values to set on the configuarion file
    :returns: A formated string with the file content.
    """
    LOG.debug(_("Building PXE config for deployment %s.") % node['id'])
    cheetah = Template.Template

    pxe_options = {
            'deployment_id': node['id'],
            'deployment_key': utils.random_alnum(32),
            'deployment_iscsi_iqn': "iqn-%s" % node['instance_uuid'],
            'deployment_aki_path': pxe_info['deploy_kernel'][1],
            'deployment_ari_path': pxe_info['deploy_ramdisk'][1],
            'aki_path': pxe_info['kernel'][1],
            'ari_path': pxe_info['ramdisk'][1],
            'pxe_append_params': CONF.pxe.pxe_append_params,
        }

    pxe_config = str(cheetah(
            open(CONF.pxe.pxe_config_template).read(),
            searchList=[{'pxe_options': pxe_options,
                         'ROOT': '${ROOT}',
            }]))
    return pxe_config
Exemple #3
0
def _build_pxe_config(node, pxe_info):
    """Build the PXE config file for a node

    This method builds the PXE boot configuration file for a node,
    given all the required parameters.

    The resulting file has both a "deploy" and "boot" label, which correspond
    to the two phases of booting. This may be extended later.

    :param pxe_options: A dict of values to set on the configuarion file
    :returns: A formated string with the file content.
    """
    LOG.debug(_("Building PXE config for deployment %s.") % node['id'])

    pxe_options = {
            'deployment_id': node['id'],
            'deployment_key': utils.random_alnum(32),
            'deployment_iscsi_iqn': "iqn-%s" % node['instance_uuid'],
            'deployment_aki_path': pxe_info['deploy_kernel'][1],
            'deployment_ari_path': pxe_info['deploy_ramdisk'][1],
            'aki_path': pxe_info['kernel'][1],
            'ari_path': pxe_info['ramdisk'][1],
            'pxe_append_params': CONF.pxe.pxe_append_params,
        }

    tmpl_path, tmpl_file = os.path.split(CONF.pxe.pxe_config_template)
    env = jinja2.Environment(loader=jinja2.FileSystemLoader(tmpl_path))
    template = env.get_template(tmpl_file)
    return template.render({'pxe_options': pxe_options,
                            'ROOT': '{{ ROOT }}'})
Exemple #4
0
def build_deploy_ramdisk_options(node):
    """Build the ramdisk config options for a node

    This method builds the ramdisk options for a node,
    given all the required parameters for doing iscsi deploy.

    :param node: a single Node.
    :returns: A dictionary of options to be passed to ramdisk for performing
        the deploy.
    """
    # NOTE: we should strip '/' from the end because this is intended for
    # hardcoded ramdisk script
    ironic_api = (CONF.conductor.api_url or
                  keystone.get_service_url()).rstrip('/')

    deploy_key = utils.random_alnum(32)
    i_info = node.instance_info
    i_info['deploy_key'] = deploy_key
    node.instance_info = i_info
    node.save()

    deploy_options = {
        'deployment_id': node['uuid'],
        'deployment_key': deploy_key,
        'iscsi_target_iqn': "iqn-%s" % node.uuid,
        'ironic_api_url': ironic_api,
        'disk': CONF.pxe.disk_devices,
    }
    return deploy_options
Exemple #5
0
    def activate_bootloader(self, context, node, instance):
        """Configure Tilera boot loader for an instance

        Kernel and ramdisk images are downloaded by cache_tftp_images,
        and stored in /tftpboot/{uuid}/

        This method writes the instances config file, and then creates
        symlinks for each MAC address in the instance.

        By default, the complete layout looks like this:

        /tftpboot/
            ./{uuid}/
                 kernel
            ./fs_node_id/
        """
        (root_mb, swap_mb) = get_partition_sizes(instance)
        tilera_nfs_path = get_tilera_nfs_path(node['id'])
        image_file_path = get_image_file_path(instance)

        deployment_key = utils.random_alnum(32)
        db.bm_node_update(context, node['id'],
                {'deploy_key': deployment_key,
                 'image_path': image_file_path,
                 'pxe_config_path': tilera_nfs_path,
                 'root_mb': root_mb,
                 'swap_mb': swap_mb})

        if os.path.exists(image_file_path) and \
           os.path.exists(tilera_nfs_path):
            utils.execute('mount', '-o', 'loop', image_file_path,
                tilera_nfs_path, run_as_root=True)
Exemple #6
0
def build_deploy_ramdisk_options(node):
    """Build the ramdisk config options for a node

    This method builds the ramdisk options for a node,
    given all the required parameters for doing iscsi deploy.

    :param node: a single Node.
    :returns: A dictionary of options to be passed to ramdisk for performing
        the deploy.
    """
    # NOTE: we should strip '/' from the end because this is intended for
    # hardcoded ramdisk script
    ironic_api = (CONF.conductor.api_url or
                  keystone.get_service_url()).rstrip('/')

    deploy_key = utils.random_alnum(32)
    i_info = node.instance_info
    i_info['deploy_key'] = deploy_key
    node.instance_info = i_info
    node.save()

    deploy_options = {
        'deployment_id': node['uuid'],
        'deployment_key': deploy_key,
        'iscsi_target_iqn': "iqn-%s" % node.uuid,
        'ironic_api_url': ironic_api,
        'disk': CONF.pxe.disk_devices,
    }
    return deploy_options
Exemple #7
0
    def activate_bootloader(self, context, node, instance):
        """Configure PXE boot loader for an instance

        Kernel and ramdisk images are downloaded by cache_tftp_images,
        and stored in /tftpboot/{uuid}/

        This method writes the instances config file, and then creates
        symlinks for each MAC address in the instance.

        By default, the complete layout looks like this:

        /tftpboot/
            ./{uuid}/
                 kernel
                 ramdisk
                 deploy_kernel
                 deploy_ramdisk
                 config
            ./pxelinux.cfg/
                 {mac} -> ../{uuid}/config
        """
        instance_type = self.virtapi.instance_type_get(
            context, instance['instance_type_id'])
        image_info = get_tftp_image_info(instance, instance_type)
        (root_mb, swap_mb) = get_partition_sizes(instance)
        pxe_config_file_path = get_pxe_config_file_path(instance)
        image_file_path = get_image_file_path(instance)

        deployment_key = utils.random_alnum(32)
        deployment_iscsi_iqn = "iqn-%s" % instance['uuid']
        db.bm_node_update(
            context, node['id'], {
                'deploy_key': deployment_key,
                'image_path': image_file_path,
                'pxe_config_path': pxe_config_file_path,
                'root_mb': root_mb,
                'swap_mb': swap_mb
            })
        pxe_config = build_pxe_config(
            node['id'],
            deployment_key,
            deployment_iscsi_iqn,
            image_info['deploy_kernel'][1],
            image_info['deploy_ramdisk'][1],
            image_info['kernel'][1],
            image_info['ramdisk'][1],
        )
        utils.write_to_file(pxe_config_file_path, pxe_config)

        macs = self._collect_mac_addresses(context, node)
        for mac in macs:
            mac_path = get_pxe_mac_path(mac)
            utils.unlink_without_raise(mac_path)
            utils.create_link_without_raise(pxe_config_file_path, mac_path)
Exemple #8
0
    def activate_bootloader(self, context, node, instance):
        """Configure PXE boot loader for an instance

        Kernel and ramdisk images are downloaded by cache_tftp_images,
        and stored in /tftpboot/{uuid}/

        This method writes the instances config file, and then creates
        symlinks for each MAC address in the instance.

        By default, the complete layout looks like this:

        /tftpboot/
            ./{uuid}/
                 kernel
                 ramdisk
                 deploy_kernel
                 deploy_ramdisk
                 config
            ./pxelinux.cfg/
                 {mac} -> ../{uuid}/config
        """
        instance_type = self.virtapi.instance_type_get(
            context, instance['instance_type_id'])
        image_info = get_tftp_image_info(instance, instance_type)
        (root_mb, swap_mb) = get_partition_sizes(instance)
        pxe_config_file_path = get_pxe_config_file_path(instance)
        image_file_path = get_image_file_path(instance)

        deployment_key = utils.random_alnum(32)
        deployment_iscsi_iqn = "iqn-%s" % instance['uuid']
        db.bm_node_update(context, node['id'],
                {'deploy_key': deployment_key,
                 'image_path': image_file_path,
                 'pxe_config_path': pxe_config_file_path,
                 'root_mb': root_mb,
                 'swap_mb': swap_mb})
        pxe_config = build_pxe_config(
                    node['id'],
                    deployment_key,
                    deployment_iscsi_iqn,
                    image_info['deploy_kernel'][1],
                    image_info['deploy_ramdisk'][1],
                    image_info['kernel'][1],
                    image_info['ramdisk'][1],
                )
        utils.write_to_file(pxe_config_file_path, pxe_config)

        macs = self._collect_mac_addresses(context, node)
        for mac in macs:
            mac_path = get_pxe_mac_path(mac)
            utils.unlink_without_raise(mac_path)
            utils.create_link_without_raise(pxe_config_file_path, mac_path)
Exemple #9
0
def build_deploy_ramdisk_options(node):
    """Build the ramdisk config options for a node

    This method builds the ramdisk options for a node,
    given all the required parameters for doing iscsi deploy.

    :param node: a single Node.
    :returns: A dictionary of options to be passed to ramdisk for performing
        the deploy.
    """
    # NOTE: we should strip '/' from the end because this is intended for
    # hardcoded ramdisk script
    ironic_api = (CONF.conductor.api_url or
                  keystone.get_service_url()).rstrip('/')

    deploy_key = utils.random_alnum(32)
    i_info = node.instance_info
    i_info['deploy_key'] = deploy_key
    node.instance_info = i_info
    node.save()

    # XXX(jroll) DIB relies on boot_option=local to decide whether or not to
    # lay down a bootloader. Hack this for now; fix it for real in Liberty.
    # See also bug #1441556.
    boot_option = deploy_utils.get_boot_option(node)
    if node.driver_internal_info.get('is_whole_disk_image'):
        boot_option = 'netboot'

    deploy_options = {
        'deployment_id': node['uuid'],
        'deployment_key': deploy_key,
        'iscsi_target_iqn': 'iqn.2008-10.org.openstack:%s' % node.uuid,
        'iscsi_portal_port': CONF.iscsi.portal_port,
        'ironic_api_url': ironic_api,
        'disk': CONF.pxe.disk_devices,
        'boot_option': boot_option,
        'boot_mode': _get_boot_mode(node),
        # NOTE: The below entry is a temporary workaround for bug/1433812
        'coreos.configdrive': 0,
    }

    root_device = deploy_utils.parse_root_device_hints(node)
    if root_device:
        deploy_options['root_device'] = root_device

    return deploy_options
Exemple #10
0
def build_deploy_ramdisk_options(node):
    """Build the ramdisk config options for a node

    This method builds the ramdisk options for a node,
    given all the required parameters for doing iscsi deploy.

    :param node: a single Node.
    :returns: A dictionary of options to be passed to ramdisk for performing
        the deploy.
    """
    # NOTE: we should strip '/' from the end because this is intended for
    # hardcoded ramdisk script
    ironic_api = (CONF.conductor.api_url
                  or keystone.get_service_url()).rstrip('/')

    deploy_key = utils.random_alnum(32)
    i_info = node.instance_info
    i_info['deploy_key'] = deploy_key
    node.instance_info = i_info
    node.save()

    # XXX(jroll) DIB relies on boot_option=local to decide whether or not to
    # lay down a bootloader. Hack this for now; fix it for real in Liberty.
    # See also bug #1441556.
    boot_option = deploy_utils.get_boot_option(node)
    if node.driver_internal_info.get('is_whole_disk_image'):
        boot_option = 'netboot'

    deploy_options = {
        'deployment_id': node['uuid'],
        'deployment_key': deploy_key,
        'iscsi_target_iqn': 'iqn.2008-10.org.openstack:%s' % node.uuid,
        'iscsi_portal_port': CONF.iscsi.portal_port,
        'ironic_api_url': ironic_api,
        'disk': CONF.pxe.disk_devices,
        'boot_option': boot_option,
        'boot_mode': _get_boot_mode(node),
        # NOTE: The below entry is a temporary workaround for bug/1433812
        'coreos.configdrive': 0,
    }

    root_device = deploy_utils.parse_root_device_hints(node)
    if root_device:
        deploy_options['root_device'] = root_device

    return deploy_options
Exemple #11
0
def build_deploy_ramdisk_options(node):
    """Build the ramdisk config options for a node

    This method builds the ramdisk options for a node,
    given all the required parameters for doing iscsi deploy.

    :param node: a single Node.
    :returns: A dictionary of options to be passed to ramdisk for performing
        the deploy.
    """
    # NOTE: we should strip '/' from the end because this is intended for
    # hardcoded ramdisk script
    ironic_api = (CONF.conductor.api_url or keystone.get_service_url()).rstrip("/")

    deploy_key = utils.random_alnum(32)
    i_info = node.instance_info
    i_info["deploy_key"] = deploy_key
    node.instance_info = i_info
    node.save()

    # XXX(jroll) DIB relies on boot_option=local to decide whether or not to
    # lay down a bootloader. Hack this for now; fix it for real in Liberty.
    # See also bug #1441556.
    boot_option = get_boot_option(node)
    if node.driver_internal_info.get("is_whole_disk_image"):
        boot_option = "netboot"

    deploy_options = {
        "deployment_id": node["uuid"],
        "deployment_key": deploy_key,
        "iscsi_target_iqn": "iqn-%s" % node.uuid,
        "ironic_api_url": ironic_api,
        "disk": CONF.pxe.disk_devices,
        "boot_option": boot_option,
        "boot_mode": _get_boot_mode(node),
        # NOTE: The below entry is a temporary workaround for bug/1433812
        "coreos.configdrive": 0,
    }

    root_device = deploy_utils.parse_root_device_hints(node)
    if root_device:
        deploy_options["root_device"] = root_device

    return deploy_options
Exemple #12
0
def _build_pxe_config(node, pxe_info):
    """Build the PXE config file for a node

    This method builds the PXE boot configuration file for a node,
    given all the required parameters.

    The resulting file has both a "deploy" and "boot" label, which correspond
    to the two phases of booting. This may be extended later.

    :param pxe_options: A dict of values to set on the configuarion file
    :returns: A formated string with the file content.
    """
    LOG.debug(_("Building PXE config for deployment %s.") % node['id'])

    # NOTE: we should strip '/' from the end because this is intended for
    # hardcoded ramdisk script
    ironic_api = (CONF.conductor.api_url or
                  keystone.get_service_url()).rstrip('/')

    deploy_key = utils.random_alnum(32)
    ctx = context.get_admin_context()
    driver_info = node['driver_info']
    driver_info['pxe_deploy_key'] = deploy_key
    node['driver_info'] = driver_info
    node.save(ctx)

    pxe_options = {
            'deployment_id': node['uuid'],
            'deployment_key': deploy_key,
            'deployment_iscsi_iqn': "iqn-%s" % node['instance_uuid'],
            'deployment_aki_path': pxe_info['deploy_kernel'][1],
            'deployment_ari_path': pxe_info['deploy_ramdisk'][1],
            'aki_path': pxe_info['kernel'][1],
            'ari_path': pxe_info['ramdisk'][1],
            'ironic_api_url': ironic_api,
            'pxe_append_params': CONF.pxe.pxe_append_params,
        }

    tmpl_path, tmpl_file = os.path.split(CONF.pxe.pxe_config_template)
    env = jinja2.Environment(loader=jinja2.FileSystemLoader(tmpl_path))
    template = env.get_template(tmpl_file)
    return template.render({'pxe_options': pxe_options,
                            'ROOT': '{{ ROOT }}'})
Exemple #13
0
def _build_pxe_config(node, pxe_info, ctx):
    """Build the PXE config file for a node

    This method builds the PXE boot configuration file for a node,
    given all the required parameters.

    The resulting file has both a "deploy" and "boot" label, which correspond
    to the two phases of booting. This may be extended later.

    :param pxe_options: A dict of values to set on the configuarion file
    :returns: A formated string with the file content.
    """
    LOG.debug("Building PXE config for deployment %s." % node.uuid)

    # NOTE: we should strip '/' from the end because this is intended for
    # hardcoded ramdisk script
    ironic_api = (CONF.conductor.api_url
                  or keystone.get_service_url()).rstrip('/')

    deploy_key = utils.random_alnum(32)
    driver_info = node['driver_info']
    driver_info['pxe_deploy_key'] = deploy_key
    node['driver_info'] = driver_info
    node.save(ctx)

    pxe_options = {
        'deployment_id': node['uuid'],
        'deployment_key': deploy_key,
        'deployment_iscsi_iqn': "iqn-%s" % node.uuid,
        'deployment_aki_path': pxe_info['deploy_kernel'][1],
        'deployment_ari_path': pxe_info['deploy_ramdisk'][1],
        'aki_path': pxe_info['kernel'][1],
        'ari_path': pxe_info['ramdisk'][1],
        'ironic_api_url': ironic_api,
        'pxe_append_params': CONF.pxe.pxe_append_params,
    }

    tmpl_path, tmpl_file = os.path.split(CONF.pxe.pxe_config_template)
    env = jinja2.Environment(loader=jinja2.FileSystemLoader(tmpl_path))
    template = env.get_template(tmpl_file)
    return template.render({'pxe_options': pxe_options, 'ROOT': '{{ ROOT }}'})
Exemple #14
0
def _build_pxe_config_options(node, pxe_info, ctx):
    """Build the PXE config options for a node

    This method builds the PXE boot options for a node,
    given all the required parameters.

    The options should then be passed to pxe_utils.create_pxe_config to
    create the actual config files.

    :param node: a single Node.
    :param pxe_info: a dict of values to set on the configuration file
    :param ctx: security context
    :returns: A dictionary of pxe options to be used in the pxe bootfile
        template.
    """
    # NOTE: we should strip '/' from the end because this is intended for
    # hardcoded ramdisk script
    ironic_api = (CONF.conductor.api_url or
                  keystone.get_service_url()).rstrip('/')

    deploy_key = utils.random_alnum(32)
    i_info = node.instance_info
    i_info['deploy_key'] = deploy_key
    node.instance_info = i_info
    node.save(ctx)

    pxe_options = {
        'deployment_id': node['uuid'],
        'deployment_key': deploy_key,
        'deployment_iscsi_iqn': "iqn-%s" % node.uuid,
        'deployment_aki_path': pxe_info['deploy_kernel'][1],
        'deployment_ari_path': pxe_info['deploy_ramdisk'][1],
        'aki_path': pxe_info['kernel'][1],
        'ari_path': pxe_info['ramdisk'][1],
        'ironic_api_url': ironic_api,
        'pxe_append_params': CONF.pxe.pxe_append_params,
    }
    return pxe_options
Exemple #15
0
def build_deploy_ramdisk_options(node):
    """Build the ramdisk config options for a node

    This method builds the ramdisk options for a node,
    given all the required parameters for doing iscsi deploy.

    :param node: a single Node.
    :returns: A dictionary of options to be passed to ramdisk for performing
        the deploy.
    """
    # NOTE: we should strip '/' from the end because this is intended for
    # hardcoded ramdisk script
    ironic_api = (CONF.conductor.api_url or
                  keystone.get_service_url()).rstrip('/')

    deploy_key = utils.random_alnum(32)
    i_info = node.instance_info
    i_info['deploy_key'] = deploy_key
    node.instance_info = i_info
    node.save()

    deploy_options = {
        'deployment_id': node['uuid'],
        'deployment_key': deploy_key,
        'iscsi_target_iqn': "iqn-%s" % node.uuid,
        'ironic_api_url': ironic_api,
        'disk': CONF.pxe.disk_devices,
        'boot_option': get_boot_option(node),
        'boot_mode': _get_boot_mode(node),
        # NOTE: The below entry is a temporary workaround for bug/1433812
        'coreos.configdrive': 0,
    }

    root_device = deploy_utils.parse_root_device_hints(node)
    if root_device:
        deploy_options['root_device'] = root_device

    return deploy_options
Exemple #16
0
def _build_pxe_config_options(node, pxe_info, ctx):
    """Build the PXE config options for a node

    This method builds the PXE boot options for a node,
    given all the required parameters.

    The options should then be passed to pxe_utils.create_pxe_config to
    create the actual config files.

    :param node: a single Node.
    :param pxe_info: a dict of values to set on the configuration file
    :param ctx: security context
    :returns: A dictionary of pxe options to be used in the pxe bootfile
        template.
    """
    # NOTE: we should strip '/' from the end because this is intended for
    # hardcoded ramdisk script
    ironic_api = (CONF.conductor.api_url
                  or keystone.get_service_url()).rstrip('/')

    deploy_key = utils.random_alnum(32)
    i_info = node.instance_info
    i_info['deploy_key'] = deploy_key
    node.instance_info = i_info
    node.save(ctx)

    pxe_options = {
        'deployment_id': node['uuid'],
        'deployment_key': deploy_key,
        'deployment_iscsi_iqn': "iqn-%s" % node.uuid,
        'deployment_aki_path': pxe_info['deploy_kernel'][1],
        'deployment_ari_path': pxe_info['deploy_ramdisk'][1],
        'aki_path': pxe_info.get('kernel', ['', ''])[1],
        'ari_path': pxe_info.get('ramdisk', ['', ''])[1],
        'ironic_api_url': ironic_api,
        'pxe_append_params': CONF.pxe.pxe_append_params,
    }
    return pxe_options
Exemple #17
0
def build_deploy_ramdisk_options(node):
    """Build the ramdisk config options for a node

    This method builds the ramdisk options for a node,
    given all the required parameters for doing iscsi deploy.

    :param node: a single Node.
    :returns: A dictionary of options to be passed to ramdisk for performing
        the deploy.
    """
    # NOTE: we should strip '/' from the end because this is intended for
    # hardcoded ramdisk script
    ironic_api = (CONF.conductor.api_url
                  or keystone.get_service_url()).rstrip('/')

    deploy_key = utils.random_alnum(32)
    i_info = node.instance_info
    i_info['deploy_key'] = deploy_key
    node.instance_info = i_info
    node.save()

    deploy_options = {
        'deployment_id': node['uuid'],
        'deployment_key': deploy_key,
        'iscsi_target_iqn': "iqn-%s" % node.uuid,
        'ironic_api_url': ironic_api,
        'disk': CONF.pxe.disk_devices,
        'boot_option': get_boot_option(node),
        'boot_mode': _get_boot_mode(node),
        # NOTE: The below entry is a temporary workaround for bug/1433812
        'coreos.configdrive': 0,
    }

    root_device = deploy_utils.parse_root_device_hints(node)
    if root_device:
        deploy_options['root_device'] = root_device

    return deploy_options
Exemple #18
0
 def test_random_alnum(self):
     s = utils.random_alnum(10)
     self.assertEqual(10, len(s))
     s = utils.random_alnum(100)
     self.assertEqual(100, len(s))
Exemple #19
0
 def test_random_alnum(self):
     s = utils.random_alnum(10)
     self.assertEqual(10, len(s))
     s = utils.random_alnum(100)
     self.assertEqual(100, len(s))