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