Beispiel #1
0
def configure_petitboot(fqdn, ko, basedir):
    """
    Creates bootloader file for petitboot

    basedir/bootloader/<fqdn>petitboot.cfg
    """
    config = """default Beaker scheduled job for %s
label Beaker scheduled job for %s
kernel ::/images/%s/kernel
initrd ::/images/%s/initrd
append %s netboot_method=petitboot
""" % (
        fqdn,
        fqdn,
        fqdn,
        fqdn,
        ko,
    )

    if not basedir:
        basedir = get_tftp_root()
    petitboot_conf_dir = os.path.join(basedir, "bootloader", fqdn)
    makedirs_ignore(petitboot_conf_dir, mode=0755)
    logger.debug("Writing petitboot config for %s as %s", fqdn, os.path.join(petitboot_conf_dir, "petitboot.cfg"))
    with atomically_replaced_file(os.path.join(petitboot_conf_dir, "petitboot.cfg")) as f:
        f.write(config)
Beispiel #2
0
def configure_efigrub(fqdn, kernel_options):
    """
    Creates bootloader file for EFI GRUB

    <get_tftp_root()>/grub/<pxe_basename(fqdn)>

    Also ensures images symlink exists:

    <get_tftp_root()>/grub/images -> <get_tftp_root()>/images
    """
    grub_dir = os.path.join(get_tftp_root(), 'grub')
    makedirs_ignore(grub_dir, mode=0755)
    atomic_symlink('../images', os.path.join(grub_dir, 'images'))

    basename = pxe_basename(fqdn)
    initrd, kernel_options = extract_initrd_arg(kernel_options)
    if initrd:
        initrd = ' '.join(['/images/%s/initrd' % fqdn] + initrd.split(','))
    else:
        initrd = '/images/%s/initrd' % fqdn
    config = '''default 0
timeout 10
title Beaker scheduled job for %s
    root (nd)
    kernel /images/%s/kernel %s netboot_method=efigrub
    initrd %s
''' % (fqdn, fqdn, kernel_options, initrd)
    logger.debug('Writing grub config for %s as %s', fqdn, basename)
    with atomically_replaced_file(os.path.join(grub_dir, basename)) as f:
        f.write(config)
Beispiel #3
0
def configure_efigrub(fqdn, kernel_options, basedir):
    """
    Creates bootloader file for EFI GRUB

    <get_tftp_root()>/grub/<pxe_basename(fqdn)>

    Also ensures images symlink exists:

    <get_tftp_root()>/grub/images -> <get_tftp_root()>/images
    """
    grub_dir = os.path.join(basedir, 'grub')
    makedirs_ignore(grub_dir, mode=0o755)
    atomic_symlink('../images', os.path.join(grub_dir, 'images'))

    basename = pxe_basename(fqdn)
    # Unfortunately the initrd kernel arg needs some special handling. It can be
    # supplied from the Beaker side (e.g. a system-specific driver disk) but we
    # also supply the main initrd here which we have fetched from the distro.
    initrd, kernel_options = extract_arg('initrd=', kernel_options)
    if initrd:
        initrd = ' '.join(['/images/%s/initrd' % fqdn] + initrd.split(','))
    else:
        initrd = '/images/%s/initrd' % fqdn
    config = '''default 0
timeout 10
title Beaker scheduled job for %s
    root (nd)
    kernel /images/%s/kernel %s netboot_method=efigrub
    initrd %s
''' % (fqdn, fqdn, kernel_options, initrd)
    logger.debug('Writing grub config for %s as %s', fqdn, basename)
    with atomically_replaced_file(os.path.join(grub_dir, basename)) as f:
        f.write(config)
Beispiel #4
0
def configure_yaboot(fqdn, kernel_options, basedir, yaboot_symlink=True):
    """
    Creates bootloader files for Yaboot

    <get_tftp_root()>/etc/<pxe_basename(fqdn).lower()>
    <get_tftp_root()>/ppc/<pxe_basename(fqdn).lower()> -> ../yaboot
    """
    yaboot_conf_dir = os.path.join(basedir, 'etc')
    makedirs_ignore(yaboot_conf_dir, mode=0o755)

    basename = pxe_basename(fqdn).lower()
    # XXX I don't think multiple initrds are supported?
    config = '''init-message="Beaker scheduled job for %s"
timeout=80
delay=10
default=linux

image=/images/%s/kernel
    label=linux
    initrd=/images/%s/initrd
    append="%s netboot_method=yaboot"
''' % (fqdn, fqdn, fqdn, kernel_options)
    logger.debug('Writing yaboot config for %s as %s', fqdn, basename)
    with atomically_replaced_file(os.path.join(yaboot_conf_dir,
                                               basename)) as f:
        f.write(config)
    if yaboot_symlink:
        ppc_dir = os.path.join(basedir, 'ppc')
        makedirs_ignore(ppc_dir, mode=0o755)
        logger.debug('Creating yaboot symlink for %s as %s', fqdn, basename)
        atomic_symlink('../yaboot', os.path.join(ppc_dir, basename))
Beispiel #5
0
def fetch_images(distro_tree_id, kernel_url, initrd_url, fqdn):
    """
    Creates references to kernel and initrd files at:

    <get_tftp_root()>/images/<fqdn>/kernel
    <get_tftp_root()>/images/<fqdn>/initrd
    """
    images_dir = os.path.join(get_tftp_root(), 'images', fqdn)
    makedirs_ignore(images_dir, 0755)
    # Only look for fetched images if distro_tree is registered
    if distro_tree_id is not None:
        distrotree_dir = os.path.join(get_tftp_root(), 'distrotrees', str(distro_tree_id))

        # beaker-pxemenu might have already fetched the images, so let's try there
        # before anywhere else.
        try:
            atomic_link(os.path.join(distrotree_dir, 'kernel'),
                    os.path.join(images_dir, 'kernel'))
            atomic_link(os.path.join(distrotree_dir, 'initrd'),
                    os.path.join(images_dir, 'initrd'))
            logger.debug('Using images from distro tree %s for %s', distro_tree_id, fqdn)
            return
        except OSError, e:
            if e.errno != errno.ENOENT:
                raise
Beispiel #6
0
def configure_pxelinux(fqdn, kernel_options, basedir, symlink=False):
    """
    Creates PXE bootloader files for PXE Linux

    <get_tftp_root()>/pxelinux.cfg/<pxe_basename(fqdn)>

    Also ensures default (localboot) config exists:

    <get_tftp_root()>/pxelinux.cfg/default
    """
    pxe_dir = os.path.join(basedir, 'pxelinux.cfg')
    makedirs_ignore(pxe_dir, mode=0o755)

    basename = pxe_basename(fqdn)
    initrd, kernel_options = extract_arg('initrd=', kernel_options)

    config = _configure_pxelinux_config(basedir, fqdn, initrd, kernel_options,
                                        symlink)

    logger.debug('Writing pxelinux config for %s as %s', fqdn, basename)
    with atomically_replaced_file(os.path.join(pxe_dir, basename)) as f:
        f.write(config)
    # We also ensure a default config exists that falls back to local boot
    write_ignore(
        os.path.join(pxe_dir, 'default'), '''default local
prompt 0
timeout 0
label local
    localboot 0
''')
Beispiel #7
0
def configure_zpxe(fqdn, kernel_url, initrd_url, kernel_options, basedir):
    """
    Creates bootloader files for ZPXE

    <get_tftp_root()>/s390x/s_<fqdn>
    <get_tftp_root()>/s390x/s_<fqdn>_parm
    <get_tftp_root()>/s390x/s_<fqdn>_conf
    """
    zpxe_dir = os.path.join(basedir, 's390x')
    makedirs_ignore(zpxe_dir, mode=0755)

    kernel_options = "%s netboot_method=zpxe" % kernel_options
    # The structure of these files is dictated by zpxe.rexx,
    # Cobbler's "pseudo-PXE" for zVM on s390(x).
    # XXX I don't think multiple initrds are supported?
    logger.debug('Writing zpxe index file for %s', fqdn)
    with atomically_replaced_file(os.path.join(zpxe_dir, 's_%s' % fqdn)) as f:
        if get_conf().get('ZPXE_USE_FTP', True):
            if not kernel_url.startswith('ftp://') or not initrd_url.startswith('ftp://'):
                raise ValueError('zPXE only supports FTP for downloading images')
            f.write('%s\n%s\n\n' % (kernel_url, initrd_url))
        else:
            f.write('/images/%s/kernel\n/images/%s/initrd\n\n' % (fqdn, fqdn))
    logger.debug('Writing zpxe parm file for %s', fqdn)
    with atomically_replaced_file(os.path.join(zpxe_dir, 's_%s_parm' % fqdn)) as f:
        # must be wrapped at 80 columns
        rest = kernel_options
        while rest:
            f.write(rest[:80] + '\n')
            rest = rest[80:]
    logger.debug('Writing zpxe conf file for %s', fqdn)
    with atomically_replaced_file(os.path.join(zpxe_dir, 's_%s_conf' % fqdn)) as f:
        pass # unused, but zpxe.rexx fetches it anyway
Beispiel #8
0
def configure_zpxe(fqdn, kernel_options, basedir):
    """
    Creates bootloader files for ZPXE

    <get_tftp_root()>/s390x/s_<fqdn>
    <get_tftp_root()>/s390x/s_<fqdn>_parm
    <get_tftp_root()>/s390x/s_<fqdn>_conf
    """
    zpxe_dir = os.path.join(basedir, 's390x')
    makedirs_ignore(zpxe_dir, mode=0755)

    kernel_options = "%s netboot_method=zpxe" % kernel_options
    # The structure of these files is dictated by zpxe.rexx,
    # Cobbler's "pseudo-PXE" for zVM on s390(x).
    # XXX I don't think multiple initrds are supported?
    logger.debug('Writing zpxe index file for %s', fqdn)
    with atomically_replaced_file(os.path.join(zpxe_dir, 's_%s' % fqdn)) as f:
        f.write('/images/%s/kernel\n/images/%s/initrd\n\n' % (fqdn, fqdn))
    logger.debug('Writing zpxe parm file for %s', fqdn)
    with atomically_replaced_file(os.path.join(zpxe_dir,
                                               's_%s_parm' % fqdn)) as f:
        # must be wrapped at 80 columns
        rest = kernel_options
        while rest:
            f.write(rest[:80] + '\n')
            rest = rest[80:]
    logger.debug('Writing zpxe conf file for %s', fqdn)
    with atomically_replaced_file(os.path.join(zpxe_dir,
                                               's_%s_conf' % fqdn)) as f:
        pass  # unused, but zpxe.rexx fetches it anyway
Beispiel #9
0
 def _link_rpms(self, dst):
     """Hardlink the task rpms into dst"""
     makedirs_ignore(dst, 0755)
     for srcpath, name in self._all_rpms():
         dstpath = os.path.join(dst, name)
         unlink_ignore(dstpath)
         os.link(srcpath, dstpath)
Beispiel #10
0
def configure_efigrub(fqdn, kernel_options, basedir):
    """
    Creates bootloader file for EFI GRUB

    <get_tftp_root()>/grub/<pxe_basename(fqdn)>

    Also ensures images symlink exists:

    <get_tftp_root()>/grub/images -> <get_tftp_root()>/images
    """
    grub_dir = os.path.join(basedir, 'grub')
    makedirs_ignore(grub_dir, mode=0755)
    atomic_symlink('../images', os.path.join(grub_dir, 'images'))

    basename = pxe_basename(fqdn)
    # Unfortunately the initrd kernel arg needs some special handling. It can be
    # supplied from the Beaker side (e.g. a system-specific driver disk) but we
    # also supply the main initrd here which we have fetched from the distro.
    initrd, kernel_options = extract_arg('initrd=', kernel_options)
    if initrd:
        initrd = ' '.join(['/images/%s/initrd' % fqdn] + initrd.split(','))
    else:
        initrd = '/images/%s/initrd' % fqdn
    config = '''default 0
timeout 10
title Beaker scheduled job for %s
    root (nd)
    kernel /images/%s/kernel %s netboot_method=efigrub
    initrd %s
''' % (fqdn, fqdn, kernel_options, initrd)
    logger.debug('Writing grub config for %s as %s', fqdn, basename)
    with atomically_replaced_file(os.path.join(grub_dir, basename)) as f:
        f.write(config)
Beispiel #11
0
def configure_armlinux(fqdn, kernel_options, basedir):
    """
    Creates PXE bootloader files for ARM Linux

    <get_tftp_root()>/arm/pxelinux.cfg/<pxe_basename(fqdn)>

    Also ensures empty config file exists:

    <get_tftp_root()>/arm/empty

    Specify filename "arm/empty"; in your dhcpd.conf file
    This is needed to set a path prefix of arm so that we don't
    conflict with x86 pxelinux.cfg files.
    """
    pxe_base = os.path.join(basedir, 'arm')
    makedirs_ignore(pxe_base, mode=0o755)
    write_ignore(os.path.join(pxe_base, 'empty'), '')
    pxe_dir = os.path.join(pxe_base, 'pxelinux.cfg')
    makedirs_ignore(pxe_dir, mode=0o755)

    basename = pxe_basename(fqdn)
    config = '''default linux
prompt 0
timeout 100
label linux
    kernel ../images/%s/kernel
    initrd ../images/%s/initrd
    append %s netboot_method=armpxe
''' % (fqdn, fqdn, kernel_options)
    logger.debug('Writing armlinux config for %s as %s', fqdn, basename)
    with atomically_replaced_file(os.path.join(pxe_dir, basename)) as f:
        f.write(config)
Beispiel #12
0
def configure_armlinux(fqdn, kernel_options):
    """
    Creates PXE bootloader files for ARM Linux

    <get_tftp_root()>/arm/pxelinux.cfg/<pxe_basename(fqdn)>

    Also ensures empty config file exists:

    <get_tftp_root()>/arm/empty

    Specify filename "arm/empty"; in your dhcpd.conf file
    This is needed to set a path prefix of arm so that we don't
    conflict with x86 pxelinux.cfg files.
    """
    pxe_base = os.path.join(get_tftp_root(), 'arm')
    makedirs_ignore(pxe_base, mode=0755)
    write_ignore(os.path.join(pxe_base, 'empty'), '')
    pxe_dir = os.path.join(pxe_base, 'pxelinux.cfg')
    makedirs_ignore(pxe_dir, mode=0755)

    basename = pxe_basename(fqdn)
    config = '''default linux
prompt 0
timeout 100
label linux
    kernel ../images/%s/kernel
    initrd ../images/%s/initrd
    append %s netboot_method=armpxe
''' % (fqdn, fqdn, kernel_options)
    logger.debug('Writing armlinux config for %s as %s', fqdn, basename)
    with atomically_replaced_file(os.path.join(pxe_dir, basename)) as f:
        f.write(config)
Beispiel #13
0
def configure_x86_64(fqdn, kernel_options, basedir):
    """
    Calls configure_grub2() to create the machine config files to GRUB2
    boot loader.

    <get_tftp_root()>/x86_64/grub.cfg-<pxe_basename(fqdn)>
    <get_tftp_root()>/x86_64/grub.cfg
    <get_tftp_root()>/boot/grub2/grub.cfg-<pxe_basename(fqdn)>
    <get_tftp_root()>/boot/grub2/grub.cfg
    """
    x86_64_dir = os.path.join(basedir, 'x86_64')
    makedirs_ignore(x86_64_dir, mode=0o755)
    grub2_conf = "grub.cfg-%s" % pxe_basename(fqdn)

    grub_cfg_file = os.path.join(x86_64_dir, grub2_conf)
    logger.debug('Writing grub2/x86_64 config for %s as %s', fqdn,
                 grub_cfg_file)
    configure_grub2(fqdn, x86_64_dir, grub_cfg_file, kernel_options)

    # Location can be used as fallback
    # Mostly old GRUB2 relying on this location
    grub2_conf_dir = os.path.join(basedir, 'boot', 'grub2')
    makedirs_ignore(grub2_conf_dir, mode=0o755)
    grub_cfg_file = os.path.join(grub2_conf_dir, grub2_conf)
    logger.debug('Writing grub2/x86_64 config for %s as %s', fqdn,
                 grub_cfg_file)
    configure_grub2(fqdn, grub2_conf_dir, grub_cfg_file, kernel_options)
Beispiel #14
0
def configure_zpxe(fqdn, kernel_options):
    """
    Creates bootloader files for ZPXE

    <get_tftp_root()>/s390x/s_<fqdn>
    <get_tftp_root()>/s390x/s_<fqdn>_parm
    <get_tftp_root()>/s390x/s_<fqdn>_conf
    """
    zpxe_dir = os.path.join(get_tftp_root(), 's390x')
    makedirs_ignore(zpxe_dir, mode=0755)

    kernel_options = "%s netboot_method=zpxe" % kernel_options
    # The structure of these files is dictated by zpxe.rexx,
    # Cobbler's "pseudo-PXE" for zVM on s390(x).
    # XXX I don't think multiple initrds are supported?
    logger.debug('Writing zpxe index file for %s', fqdn)
    with atomically_replaced_file(os.path.join(zpxe_dir, 's_%s' % fqdn)) as f:
        f.write('/images/%s/kernel\n/images/%s/initrd\n\n' % (fqdn, fqdn))
    logger.debug('Writing zpxe parm file for %s', fqdn)
    with atomically_replaced_file(os.path.join(zpxe_dir, 's_%s_parm' % fqdn)) as f:
        # must be wrapped at 80 columns
        rest = kernel_options
        while rest:
            f.write(rest[:80] + '\n')
            rest = rest[80:]
    logger.debug('Writing zpxe conf file for %s', fqdn)
    with atomically_replaced_file(os.path.join(zpxe_dir, 's_%s_conf' % fqdn)) as f:
        pass # unused, but zpxe.rexx fetches it anyway
Beispiel #15
0
def configure_yaboot(fqdn, kernel_options):
    """
    Creates bootloader files for Yaboot

    <get_tftp_root()>/etc/<pxe_basename(fqdn).lower()>
    <get_tftp_root()>/ppc/<pxe_basename(fqdn).lower()> -> ../yaboot
    """
    yaboot_conf_dir = os.path.join(get_tftp_root(), 'etc')
    makedirs_ignore(yaboot_conf_dir, mode=0755)
    ppc_dir = os.path.join(get_tftp_root(), 'ppc')
    makedirs_ignore(ppc_dir, mode=0755)

    basename = pxe_basename(fqdn).lower()
    # XXX I don't think multiple initrds are supported?
    config = '''init-message="Beaker scheduled job for %s"
timeout=80
delay=10
default=linux

image=/images/%s/kernel
    label=linux
    initrd=/images/%s/initrd
    append="%s netboot_method=yaboot"
''' % (fqdn, fqdn, fqdn, kernel_options)
    logger.debug('Writing yaboot config for %s as %s', fqdn, basename)
    with atomically_replaced_file(os.path.join(yaboot_conf_dir, basename)) as f:
        f.write(config)
    logger.debug('Creating yaboot symlink for %s as %s', fqdn, basename)
    atomic_symlink('../yaboot', os.path.join(ppc_dir, basename))
Beispiel #16
0
 def __enter__(self):
     makedirs_ignore(os.path.dirname(self.path), 0755)
     created = False
     if self.create:
         try:
             # stdio does not have any mode string which corresponds to this 
             # combination of flags, so we have to use raw os.open :-(
             fd = os.open(self.path, os.O_RDWR | os.O_CREAT | os.O_EXCL, 0644)
             created = True
         except (OSError, IOError), e:
             if e.errno != errno.EEXIST:
                 raise
             fd = os.open(self.path, os.O_RDWR)
Beispiel #17
0
def _get_images(tftp_root, distro_tree_id, url, images):
    dest_dir = os.path.join(tftp_root, 'distrotrees', str(distro_tree_id))
    makedirs_ignore(dest_dir, mode=0o755)
    for image_type, path in images:
        if image_type in ('kernel', 'initrd'):
            dest_path = os.path.join(dest_dir, image_type)
            if os.path.isfile(dest_path):
                print('Skipping existing %s for distro tree %s' % (image_type, distro_tree_id))
            else:
                image_url = urlparse.urljoin(url, path)
                print('Fetching %s %s for distro tree %s' % (image_type, image_url, distro_tree_id))
                with atomically_replaced_file(dest_path) as dest:
                    siphon(urllib2.urlopen(image_url), dest)
Beispiel #18
0
def _get_images(tftp_root, distro_tree_id, url, images):
    dest_dir = os.path.join(tftp_root, 'distrotrees', str(distro_tree_id))
    makedirs_ignore(dest_dir, mode=0755)
    for image_type, path in images:
        if image_type in ('kernel', 'initrd'):
            dest_path = os.path.join(dest_dir, image_type)
            if os.path.isfile(dest_path):
                print 'Skipping existing %s for distro tree %s' % (image_type, distro_tree_id)
            else:
                image_url = urlparse.urljoin(url, path)
                print 'Fetching %s %s for distro tree %s' % (image_type, image_url, distro_tree_id)
                with atomically_replaced_file(dest_path) as dest:
                    siphon(urllib2.urlopen(image_url), dest)
Beispiel #19
0
    def test_doesnt_overwrite_existing_default_config(self):
        ipxe_dir = os.path.join(self.tftp_root, 'ipxe')
        makedirs_ignore(ipxe_dir, mode=0755)
        ipxe_default_path = os.path.join(ipxe_dir, 'default')
        # in reality it will probably be a menu
        custom = '''#!ipxe
chain /ipxe/beaker_menu
exit 1
'''
        open(ipxe_default_path, 'wx').write(custom)
        netboot.configure_ipxe(TEST_FQDN,
                               'console=ttyS0,115200 ks=http://lol/',
                               self.tftp_root)
        self.assertEquals(open(ipxe_default_path).read(), custom)
Beispiel #20
0
def configure_ppc64(fqdn, kernel_options):
    """
    Calls configure_grub2() to create the machine config files and symlink
    to the grub2 boot loader:

    <get_tftp_root()>/ppc/grub.cfg-<pxe_basename(fqdn)>
    <get_tftp_root()>/ppc/grub.cfg
    <get_tftp_root()>/ppc/<pxe_basename(fqdn).lower()-grub2> -> ../boot/grub2/powerpc-ieee1275/core.elf

    # Hacks, see the note below
    <get_tftp_root()>grub.cfg-<pxe_basename(fqdn)>
    <get_tftp_root()>boot/grub2/grub.cfg-<pxe_basename(fqdn)>


    """
    ppc_dir = os.path.join(get_tftp_root(), 'ppc')
    makedirs_ignore(ppc_dir, mode=0755)

    grub_cfg_file = os.path.join(ppc_dir, "grub.cfg-%s" % pxe_basename(fqdn))
    logger.debug('Writing grub2/ppc64 config for %s as %s', fqdn,
                 grub_cfg_file)
    configure_grub2(fqdn, ppc_dir, grub_cfg_file, kernel_options)

    # The following two hacks are to accommodate the differences in behavior
    # among various power configurations and grub2 versions
    # Remove them once they are sorted out (also see the relevant
    # code in clear_ppc64())
    # Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1144106

    # hack for older grub
    grub2_conf_dir = os.path.join(get_tftp_root(), 'boot', 'grub2')
    makedirs_ignore(grub2_conf_dir, mode=0755)
    grub_cfg_file = os.path.join(grub2_conf_dir,
                                 "grub.cfg-%s" % pxe_basename(fqdn))
    logger.debug('Writing grub2/ppc64 config for %s as %s', fqdn,
                 grub_cfg_file)
    configure_grub2(fqdn, grub2_conf_dir, grub_cfg_file, kernel_options)

    # hack for power VMs
    grub_cfg_file = os.path.join(get_tftp_root(),
                                 "grub.cfg-%s" % pxe_basename(fqdn))
    logger.debug('Writing grub2/ppc64 config for %s as %s', fqdn,
                 grub_cfg_file)
    configure_grub2(fqdn, ppc_dir, grub_cfg_file, kernel_options)

    grub2_symlink = '%s-grub2' % pxe_basename(fqdn).lower()
    logger.debug('Creating grub2 symlink for %s as %s', fqdn, grub2_symlink)
    atomic_symlink('../boot/grub2/powerpc-ieee1275/core.elf',
                   os.path.join(ppc_dir, grub2_symlink))
Beispiel #21
0
def configure_netbootloader_directory(fqdn, kernel_options, netbootloader):
    tftp_root = get_tftp_root()
    if netbootloader:
        fqdn_dir = os.path.join(tftp_root, 'bootloader', fqdn)
        logger.debug('Creating custom netbootloader tree for %s in %s', fqdn, fqdn_dir)
        makedirs_ignore(fqdn_dir, mode=0755)
        grub2_cfg_file = os.path.join(fqdn_dir, 'grub.cfg-%s'%pxe_basename(fqdn))
        configure_grub2(fqdn, fqdn_dir, grub2_cfg_file, kernel_options)
        configure_pxelinux(fqdn, kernel_options, fqdn_dir)
        configure_yaboot(fqdn, kernel_options, fqdn_dir, yaboot_symlink=False)

        # create the symlink to the specified bootloader w.r.t the tftp_root
        if netbootloader.startswith('/'):
            netbootloader = netbootloader.lstrip('/')
        atomic_symlink(os.path.join('../../', netbootloader), os.path.join(fqdn_dir, 'image'))
Beispiel #22
0
def copy_default_loader_images():
    """
    Populates default boot loader images, where possible.

    Ultimately it is up to the administrator to make sure that their desired 
    boot loader images are available and match their DHCP configuration. 
    However we can copy in some common loader images to their default locations 
    as a convenience.
    """
    # We could also copy EFI GRUB, on RHEL6 it's located at /boot/efi/EFI/redhat/grub.efi
    # ... the problem is that is either the ia32 version or the x64 version
    # depending on the architecture of the server, blerg.
    makedirs_ignore(get_tftp_root(), mode=0755)
    copy_path_ignore(os.path.join(get_tftp_root(), "pxelinux.0"), "/usr/share/syslinux/pxelinux.0")
    copy_path_ignore(os.path.join(get_tftp_root(), "menu.c32"), "/usr/share/syslinux/menu.c32")
Beispiel #23
0
    def test_doesnt_overwrite_existing_default_config(self):
        pxelinux_dir = os.path.join(self.tftp_root, "pxelinux.cfg")
        makedirs_ignore(pxelinux_dir, mode=0755)
        pxelinux_default_path = os.path.join(pxelinux_dir, "default")
        # in reality it will probably be a menu
        custom = """
default local
prompt 10
timeout 200
label local
    localboot 0
label jabberwocky
    boot the thing"""
        open(pxelinux_default_path, "wx").write(custom)
        netboot.configure_pxelinux(TEST_FQDN, "console=ttyS0,115200 ks=http://lol/")
        self.assertEquals(open(pxelinux_default_path).read(), custom)
Beispiel #24
0
def configure_pxelinux(fqdn, kernel_options, basedir):
    """
    Creates PXE bootloader files for PXE Linux

    <get_tftp_root()>/pxelinux.cfg/<pxe_basename(fqdn)>

    Also ensures default (localboot) config exists:

    <get_tftp_root()>/pxelinux.cfg/default
    """
    pxe_dir = os.path.join(basedir, "pxelinux.cfg")
    makedirs_ignore(pxe_dir, mode=0755)

    basename = pxe_basename(fqdn)
    # Unfortunately the initrd kernel arg needs some special handling. It can be
    # supplied from the Beaker side (e.g. a system-specific driver disk) but we
    # also supply the main initrd here which we have fetched from the distro.
    initrd, kernel_options = extract_arg("initrd=", kernel_options)
    if initrd:
        initrd = "/images/%s/initrd,%s" % (fqdn, initrd)
    else:
        initrd = "/images/%s/initrd" % fqdn
    config = """default linux
prompt 0
timeout 100
label linux
    kernel /images/%s/kernel
    ipappend 2
    append initrd=%s %s netboot_method=pxe
""" % (
        fqdn,
        initrd,
        kernel_options,
    )
    logger.debug("Writing pxelinux config for %s as %s", fqdn, basename)
    with atomically_replaced_file(os.path.join(pxe_dir, basename)) as f:
        f.write(config)
    # We also ensure a default config exists that falls back to local boot
    write_ignore(
        os.path.join(pxe_dir, "default"),
        """default local
prompt 0
timeout 0
label local
    localboot 0
""",
    )
Beispiel #25
0
def copy_default_loader_images():
    """
    Populates default boot loader images, where possible.

    Ultimately it is up to the administrator to make sure that their desired
    boot loader images are available and match their DHCP configuration.
    However we can copy in some common loader images to their default locations
    as a convenience.
    """
    # We could also copy EFI GRUB, on RHEL6 it's located at /boot/efi/EFI/redhat/grub.efi
    # ... the problem is that is either the ia32 version or the x64 version
    # depending on the architecture of the server, blerg.
    makedirs_ignore(get_tftp_root(), mode=0o755)
    copy_path_ignore(os.path.join(get_tftp_root(), 'pxelinux.0'),
                     '/usr/share/syslinux/pxelinux.0')
    copy_path_ignore(os.path.join(get_tftp_root(), 'menu.c32'),
                     '/usr/share/syslinux/menu.c32')
Beispiel #26
0
def configure_aarch64(fqdn, kernel_options, basedir):
    """
    Creates PXE bootloader files for aarch64 Linux

    <get_tftp_root()>/aarch64/grub.cfg-<pxe_basename(fqdn)>
    """
    pxe_base = os.path.join(basedir, 'aarch64')
    makedirs_ignore(pxe_base, mode=0755)
    devicetree, kernel_options = extract_arg('devicetree=', kernel_options)
    if devicetree:
        devicetree = 'devicetree %s' % devicetree
    else:
        devicetree = ''
    basename = "grub.cfg-%s" % pxe_basename(fqdn)
    logger.debug('Writing aarch64 config for %s as %s', fqdn, basename)
    grub_cfg_file = os.path.join(pxe_base, basename)
    configure_grub2(fqdn, pxe_base, grub_cfg_file, kernel_options, devicetree)
Beispiel #27
0
def configure_aarch64(fqdn, kernel_options, basedir):
    """
    Creates PXE bootloader files for aarch64 Linux

    <get_tftp_root()>/aarch64/grub.cfg-<pxe_basename(fqdn)>
    """
    pxe_base = os.path.join(basedir, 'aarch64')
    makedirs_ignore(pxe_base, mode=0o755)
    devicetree, kernel_options = extract_arg('devicetree=', kernel_options)
    if devicetree:
        devicetree = 'devicetree %s' % devicetree
    else:
        devicetree = ''
    basename = "grub.cfg-%s" % pxe_basename(fqdn)
    logger.debug('Writing aarch64 config for %s as %s', fqdn, basename)
    grub_cfg_file = os.path.join(pxe_base, basename)
    configure_grub2(fqdn, pxe_base, grub_cfg_file, kernel_options, devicetree)
Beispiel #28
0
    def test_doesnt_overwrite_existing_default_config(self):
        pxelinux_dir = os.path.join(self.tftp_root, 'pxelinux.cfg')
        makedirs_ignore(pxelinux_dir, mode=0755)
        pxelinux_default_path = os.path.join(pxelinux_dir, 'default')
        # in reality it will probably be a menu
        custom = '''
default local
prompt 10
timeout 200
label local
    localboot 0
label jabberwocky
    boot the thing'''
        open(pxelinux_default_path, 'wx').write(custom)
        netboot.configure_pxelinux(TEST_FQDN,
                'console=ttyS0,115200 ks=http://lol/')
        self.assertEquals(open(pxelinux_default_path).read(), custom)
Beispiel #29
0
def configure_netbootloader_directory(fqdn, kernel_options, netbootloader):
    tftp_root = get_tftp_root()
    if netbootloader:
        fqdn_dir = os.path.join(tftp_root, 'bootloader', fqdn)
        logger.debug('Creating custom netbootloader tree for %s in %s', fqdn,
                     fqdn_dir)
        makedirs_ignore(fqdn_dir, mode=0755)
        grub2_cfg_file = os.path.join(fqdn_dir,
                                      'grub.cfg-%s' % pxe_basename(fqdn))
        configure_grub2(fqdn, fqdn_dir, grub2_cfg_file, kernel_options)
        configure_pxelinux(fqdn, kernel_options, fqdn_dir)
        configure_yaboot(fqdn, kernel_options, fqdn_dir, yaboot_symlink=False)

        # create the symlink to the specified bootloader w.r.t the tftp_root
        if netbootloader.startswith('/'):
            netbootloader = netbootloader.lstrip('/')
        atomic_symlink(os.path.join('../../', netbootloader),
                       os.path.join(fqdn_dir, 'image'))
Beispiel #30
0
def configure_ppc64(fqdn, kernel_options, basedir):
    """
    Calls configure_grub2() to create the machine config files and symlink
    to the grub2 boot loader:

    <get_tftp_root()>/ppc/grub.cfg-<pxe_basename(fqdn)>
    <get_tftp_root()>/ppc/grub.cfg
    <get_tftp_root()>/ppc/<pxe_basename(fqdn).lower()-grub2> -> ../boot/grub2/powerpc-ieee1275/core.elf

    # Hacks, see the note below
    <get_tftp_root()>grub.cfg-<pxe_basename(fqdn)>
    <get_tftp_root()>boot/grub2/grub.cfg-<pxe_basename(fqdn)>


    """
    ppc_dir = os.path.join(basedir, 'ppc')
    makedirs_ignore(ppc_dir, mode=0755)

    grub_cfg_file = os.path.join(ppc_dir, "grub.cfg-%s" % pxe_basename(fqdn))
    logger.debug('Writing grub2/ppc64 config for %s as %s', fqdn, grub_cfg_file)
    configure_grub2(fqdn, ppc_dir, grub_cfg_file, kernel_options)

    # The following two hacks are to accommodate the differences in behavior
    # among various power configurations and grub2 versions
    # Remove them once they are sorted out (also see the relevant
    # code in clear_ppc64())
    # Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1144106

    # hack for older grub
    grub2_conf_dir = os.path.join(basedir, 'boot', 'grub2')
    makedirs_ignore(grub2_conf_dir, mode=0755)
    grub_cfg_file = os.path.join(grub2_conf_dir, "grub.cfg-%s" % pxe_basename(fqdn))
    logger.debug('Writing grub2/ppc64 config for %s as %s', fqdn, grub_cfg_file)
    configure_grub2(fqdn, grub2_conf_dir, grub_cfg_file, kernel_options)

    # hack for power VMs
    grub_cfg_file = os.path.join(basedir, "grub.cfg-%s" % pxe_basename(fqdn))
    logger.debug('Writing grub2/ppc64 config for %s as %s', fqdn, grub_cfg_file)
    configure_grub2(fqdn, ppc_dir, grub_cfg_file, kernel_options)

    grub2_symlink = '%s-grub2' % pxe_basename(fqdn).lower()
    logger.debug('Creating grub2 symlink for %s as %s', fqdn, grub2_symlink)
    atomic_symlink('../boot/grub2/powerpc-ieee1275/core.elf',
                   os.path.join(ppc_dir, grub2_symlink))
Beispiel #31
0
def configure_pxelinux(fqdn, kernel_options):
    """
    Creates PXE bootloader files for PXE Linux

    <get_tftp_root()>/pxelinux.cfg/<pxe_basename(fqdn)>

    Also ensures default (localboot) config exists:

    <get_tftp_root()>/pxelinux.cfg/default
    """
    pxe_dir = os.path.join(get_tftp_root(), "pxelinux.cfg")
    makedirs_ignore(pxe_dir, mode=0755)

    basename = pxe_basename(fqdn)
    initrd, kernel_options = extract_initrd_arg(kernel_options)
    if initrd:
        initrd = "/images/%s/initrd,%s" % (fqdn, initrd)
    else:
        initrd = "/images/%s/initrd" % fqdn
    config = """default linux
prompt 0
timeout 100
label linux
    kernel /images/%s/kernel
    ipappend 2
    append initrd=%s %s netboot_method=pxe
""" % (
        fqdn,
        initrd,
        kernel_options,
    )
    logger.debug("Writing pxelinux config for %s as %s", fqdn, basename)
    with atomically_replaced_file(os.path.join(pxe_dir, basename)) as f:
        f.write(config)
    # We also ensure a default config exists that falls back to local boot
    write_ignore(
        os.path.join(pxe_dir, "default"),
        """default local
prompt 0
timeout 0
label local
    localboot 0
""",
    )
Beispiel #32
0
def configure_petitboot(fqdn, ko):
    """
    Creates bootloader file for petitboot

    <get_tftp_root()>/bootloader/<fqdn>petitboot.cfg
    """
    config = '''default Beaker scheduled job for %s
label Beaker scheduled job for %s
kernel ::/images/%s/kernel
initrd ::/images/%s/initrd
append %s netboot_method=petitboot
''' % (fqdn, fqdn, fqdn, fqdn, ko)
    petitboot_conf_dir = os.path.join(get_tftp_root(), 'bootloader', fqdn)
    makedirs_ignore(petitboot_conf_dir, mode=0755)
    logger.debug('Writing petitboot config for %s as %s', fqdn,
                 os.path.join(petitboot_conf_dir, 'petitboot.cfg'))
    with atomically_replaced_file(
            os.path.join(petitboot_conf_dir, 'petitboot.cfg')) as f:
        f.write(config)
Beispiel #33
0
def fetch_images(distro_tree_id, kernel_url, initrd_url, fqdn):
    """
    Creates references to kernel and initrd files at:

    <get_tftp_root()>/images/<fqdn>/kernel
    <get_tftp_root()>/images/<fqdn>/initrd
    """
    images_dir = os.path.join(get_tftp_root(), 'images', fqdn)
    makedirs_ignore(images_dir, 0o755)
    # Only look for fetched images if distro_tree is registered
    if distro_tree_id is not None:
        distrotree_dir = os.path.join(get_tftp_root(), 'distrotrees',
                                      str(distro_tree_id))

        # beaker-pxemenu might have already fetched the images, so let's try there
        # before anywhere else.
        try:
            atomic_link(os.path.join(distrotree_dir, 'kernel'),
                        os.path.join(images_dir, 'kernel'))
            atomic_link(os.path.join(distrotree_dir, 'initrd'),
                        os.path.join(images_dir, 'initrd'))
            logger.debug('Using images from distro tree %s for %s',
                         distro_tree_id, fqdn)
            return
        except OSError as e:
            if e.errno != errno.ENOENT:
                raise
        # No luck there, so try something else...

    timeout = get_conf().get('IMAGE_FETCH_TIMEOUT')
    logger.debug('Fetching kernel %s for %s', kernel_url, fqdn)
    with atomically_replaced_file(os.path.join(images_dir, 'kernel')) as dest:
        try:
            siphon(urllib2.urlopen(kernel_url, timeout=timeout), dest)
        except Exception as e:
            raise ImageFetchingError(kernel_url, distro_tree_id, e)
    logger.debug('Fetching initrd %s for %s', initrd_url, fqdn)
    with atomically_replaced_file(os.path.join(images_dir, 'initrd')) as dest:
        try:
            siphon(urllib2.urlopen(initrd_url, timeout=timeout), dest)
        except Exception as e:
            raise ImageFetchingError(initrd_url, distro_tree_id, e)
Beispiel #34
0
def configure_pxelinux(fqdn, kernel_options, basedir):
    """
    Creates PXE bootloader files for PXE Linux

    <get_tftp_root()>/pxelinux.cfg/<pxe_basename(fqdn)>

    Also ensures default (localboot) config exists:

    <get_tftp_root()>/pxelinux.cfg/default
    """
    pxe_dir = os.path.join(basedir, 'pxelinux.cfg')
    makedirs_ignore(pxe_dir, mode=0755)

    basename = pxe_basename(fqdn)
    # Unfortunately the initrd kernel arg needs some special handling. It can be
    # supplied from the Beaker side (e.g. a system-specific driver disk) but we
    # also supply the main initrd here which we have fetched from the distro.
    initrd, kernel_options = extract_arg('initrd=', kernel_options)
    if initrd:
        initrd = '/images/%s/initrd,%s' % (fqdn, initrd)
    else:
        initrd = '/images/%s/initrd' % fqdn
    config = '''default linux
prompt 0
timeout 100
label linux
    kernel /images/%s/kernel
    ipappend 2
    append initrd=%s %s netboot_method=pxe
''' % (fqdn, initrd, kernel_options)
    logger.debug('Writing pxelinux config for %s as %s', fqdn, basename)
    with atomically_replaced_file(os.path.join(pxe_dir, basename)) as f:
        f.write(config)
    # We also ensure a default config exists that falls back to local boot
    write_ignore(
        os.path.join(pxe_dir, 'default'), '''default local
prompt 0
timeout 0
label local
    localboot 0
''')
Beispiel #35
0
def fetch_images(distro_tree_id, kernel_url, initrd_url, fqdn):
    """
    Creates references to kernel and initrd files at:

    <get_tftp_root()>/images/<fqdn>/kernel
    <get_tftp_root()>/images/<fqdn>/initrd
    """
    images_dir = os.path.join(get_tftp_root(), "images", fqdn)
    makedirs_ignore(images_dir, 0755)
    distrotree_dir = os.path.join(get_tftp_root(), "distrotrees", str(distro_tree_id))

    # beaker-pxemenu might have already fetched the images, so let's try there
    # before anywhere else.
    try:
        atomic_link(os.path.join(distrotree_dir, "kernel"), os.path.join(images_dir, "kernel"))
        atomic_link(os.path.join(distrotree_dir, "initrd"), os.path.join(images_dir, "initrd"))
        logger.debug("Using images from distro tree %s for %s", distro_tree_id, fqdn)
        return
    except OSError, e:
        if e.errno != errno.ENOENT:
            raise
Beispiel #36
0
def configure_zpxe(fqdn, kernel_url, initrd_url, kernel_options, basedir):
    """
    Creates bootloader files for ZPXE

    <get_tftp_root()>/s390x/s_<fqdn>
    <get_tftp_root()>/s390x/s_<fqdn>_parm
    <get_tftp_root()>/s390x/s_<fqdn>_conf
    """
    zpxe_dir = os.path.join(basedir, 's390x')
    makedirs_ignore(zpxe_dir, mode=0o755)

    kernel_options = "%s netboot_method=zpxe" % kernel_options
    # The structure of these files is dictated by zpxe.rexx,
    # Cobbler's "pseudo-PXE" for zVM on s390(x).
    # XXX I don't think multiple initrds are supported?
    logger.debug('Writing zpxe index file for %s', fqdn)
    with atomically_replaced_file(os.path.join(zpxe_dir, 's_%s' % fqdn)) as f:
        if get_conf().get('ZPXE_USE_FTP', True):
            if not kernel_url.startswith(
                    'ftp://') or not initrd_url.startswith('ftp://'):
                raise ValueError(
                    'zPXE only supports FTP for downloading images')
            f.write('%s\n%s\n\n' % (kernel_url, initrd_url))
        else:
            f.write('/images/%s/kernel\n/images/%s/initrd\n\n' % (fqdn, fqdn))
    logger.debug('Writing zpxe parm file for %s', fqdn)
    with atomically_replaced_file(os.path.join(zpxe_dir,
                                               's_%s_parm' % fqdn)) as f:
        # must be wrapped at 80 columns
        rest = kernel_options
        while rest:
            f.write(rest[:80] + '\n')
            rest = rest[80:]
    logger.debug('Writing zpxe conf file for %s', fqdn)
    with atomically_replaced_file(os.path.join(zpxe_dir,
                                               's_%s_conf' % fqdn)) as f:
        pass  # unused, but zpxe.rexx fetches it anyway
Beispiel #37
0
def configure_ipxe(fqdn, kernel_options, basedir):
    """
    Creates iPXE bootloader files

    <get_tftp_root()>/ipxe/<pxe_basename(fqdn).lower()>

    Also ensures default (localboot) config exists:

    <get_tftp_root()>/ipxe/default
    """
    ipxe_dir = os.path.join(basedir, 'ipxe')
    makedirs_ignore(ipxe_dir, mode=0755)

    basename = pxe_basename(fqdn).lower()
    # Unfortunately the initrd kernel arg needs some special handling. It can be
    # supplied from the Beaker side (e.g. a system-specific driver disk) but we
    # also supply the main initrd here which we have fetched from the distro.
    initrd, kernel_options = extract_arg('initrd=', kernel_options)
    if initrd:
        initrd = '/images/%s/initrd\ninitrd %s' % (fqdn, initrd)
    else:
        initrd = '/images/%s/initrd' % fqdn
    config = '''#!ipxe
kernel /images/%s/kernel
initrd %s
imgargs kernel initrd=initrd %s netboot_method=ipxe BOOTIF=01-${netX/mac:hexhyp}
boot || exit 1
''' % (fqdn, initrd, kernel_options)
    logger.debug('Writing ipxe config for %s as %s', fqdn, basename)
    with atomically_replaced_file(os.path.join(ipxe_dir, basename)) as f:
        f.write(config)
    # We also ensure a default config exists that falls back to local boot
    write_ignore(
        os.path.join(ipxe_dir, 'default'), '''#!ipxe
iseq ${builtin/platform} pcbios && sanboot --no-describe --drive 0x80 ||
exit 1
''')
Beispiel #38
0
def configure_aarch64(fqdn, kernel_options):
    """
    Creates PXE bootloader files for aarch64 Linux

    <get_tftp_root()>/pxelinux/grub.cfg-<pxe_basename(fqdn)>

    Also ensures <fqdn>.efi is symlinked to bootaa64.efi

    Specify filename "pxelinux/<fqdn>.efi"; in your dhcpd.conf file
    We remove this when the install is done.  This allows efi
    to fall through to the next boot entry.
    """
    pxe_base = os.path.join(get_tftp_root(), 'pxelinux')
    makedirs_ignore(pxe_base, mode=0755)
    basename = "grub.cfg-%s" % pxe_basename(fqdn)
    config = '''  linux  ../images/%s/kernel %s
  initrd ../images/%s/initrd
  devicetree /pxelinux/apm-mustang.dtb
  boot
''' % (fqdn, kernel_options, fqdn)
    logger.debug('Writing aarch64 config for %s as %s', fqdn, basename)
    with atomically_replaced_file(os.path.join(pxe_base, basename)) as f:
        f.write(config)
    atomic_symlink('bootaa64.efi', os.path.join(pxe_base, "%s.efi" % fqdn))
Beispiel #39
0
 def setUpClass(cls):
     makedirs_ignore(get_conf().get('CONSOLE_LOGS'), 0755)
Beispiel #40
0
    proxy = xmlrpclib.ServerProxy('http://localhost:8000', allow_none=True)
    distrotrees = proxy.get_distro_trees({
        'arch': ['x86_64', 'i386'],
        'tags': opts.tags,
        'xml': opts.xml_filter,
    })

    obsolete_tree_ids = set(existing_tree_ids).difference(
            str(dt['distro_tree_id']) for dt in distrotrees)
    print 'Removing images for %s obsolete distro trees' % len(obsolete_tree_ids)
    for obs in obsolete_tree_ids:
        shutil.rmtree(os.path.join(opts.tftp_root, 'distrotrees', obs), ignore_errors=True)

    print 'Generating menu for %s distro trees' % len(distrotrees)
    osmajors = _group_distro_trees(distrotrees)
    makedirs_ignore(os.path.join(opts.tftp_root, 'pxelinux.cfg'), mode=0755)
    pxe_menu = atomically_replaced_file(os.path.join(opts.tftp_root, 'pxelinux.cfg', 'beaker_menu'))
    makedirs_ignore(os.path.join(opts.tftp_root, 'grub'), mode=0755)
    atomic_symlink('../distrotrees', os.path.join(opts.tftp_root, 'grub', 'distrotrees'))
    efi_menu = atomically_replaced_file(os.path.join(opts.tftp_root, 'grub', 'efidefault'))
    with contextlib.nested(pxe_menu, efi_menu) as (pxe_menu, efi_menu):
        pxe_menu.write('''default menu
prompt 0
timeout 6000
ontimeout local
menu title Beaker
label local
    menu label (local)
    menu default
    localboot 0
''')
Beispiel #41
0
        'xml': xml_filter,
    })
    current_tree_ids = set(str(dt['distro_tree_id'])
            for dt in distro_trees)
    obsolete_tree_ids = set(existing_tree_ids).difference(current_tree_ids)
    print 'Removing images for %s obsolete distro trees' % len(obsolete_tree_ids)
    for obs in obsolete_tree_ids:
        shutil.rmtree(os.path.join(tftp_root, 'distrotrees', obs), ignore_errors=True)

    # Fetch images for all the distro trees first.
    print 'Fetching images for all the distro trees'
    distro_trees = _get_all_images(tftp_root, distro_trees)

    x86_distrotrees = [distro for distro in distro_trees if distro['arch'] in ['x86_64', 'i386']]
    print 'Generating PXELINUX menus for %s distro trees' % len(x86_distrotrees)
    makedirs_ignore(os.path.join(tftp_root, 'pxelinux.cfg'), mode=0755)
    pxe_menu = atomically_replaced_file(os.path.join(tftp_root, 'pxelinux.cfg', 'beaker_menu'))
    write_menu(pxe_menu, u'pxelinux-menu', x86_distrotrees)

    print 'Generating EFI GRUB menus for %s distro trees' % len(x86_distrotrees)
    makedirs_ignore(os.path.join(tftp_root, 'grub'), mode=0755)
    atomic_symlink('../distrotrees', os.path.join(tftp_root, 'grub', 'distrotrees'))
    efi_grub_menu = atomically_replaced_file(os.path.join(tftp_root, 'grub', 'efidefault'))
    write_menu(efi_grub_menu, u'efi-grub-menu', x86_distrotrees)

    print 'Generating GRUB2 menus for x86 EFI for %s distro trees' % len(x86_distrotrees)
    makedirs_ignore(os.path.join(tftp_root, 'boot', 'grub2'), mode=0755)
    x86_grub2_menu = atomically_replaced_file(os.path.join(tftp_root, 'boot', 'grub2',
            'beaker_menu_x86.cfg'))
    write_menu(x86_grub2_menu, u'grub2-menu', x86_distrotrees)
Beispiel #42
0
            return
        except OSError, e:
            if e.errno != errno.ENOENT:
                raise
        # Okay, fall back to fetching...

    logger.debug("Fetching kernel %s for %s", kernel_url, fqdn)
    with atomically_replaced_file(os.path.join(images_dir, "kernel")) as dest:
        siphon(urllib2.urlopen(kernel_url), dest)
    logger.debug("Fetching initrd %s for %s", initrd_url, fqdn)
    with atomically_replaced_file(os.path.join(images_dir, "initrd")) as dest:
        siphon(urllib2.urlopen(initrd_url), dest)

    if get_conf().get("IMAGE_CACHE", False):
        logger.debug("Linking fetched images for %s to cache", fqdn)
        makedirs_ignore(cached_images_dir, 0755)
        try:
            # Do them in the opposite order to above
            atomic_link(
                os.path.join(images_dir, "initrd"), os.path.join(cached_images_dir, cached_filename(initrd_url))
            )
            atomic_link(
                os.path.join(images_dir, "kernel"), os.path.join(cached_images_dir, cached_filename(kernel_url))
            )
        except OSError, e:
            if e.errno != errno.EEXIST:
                raise
        clean_image_cache()


def have_images(fqdn):
Beispiel #43
0
        'xml': xml_filter,
    })
    current_tree_ids = set(str(dt['distro_tree_id'])
            for dt in distro_trees)
    obsolete_tree_ids = set(existing_tree_ids).difference(current_tree_ids)
    print 'Removing images for %s obsolete distro trees' % len(obsolete_tree_ids)
    for obs in obsolete_tree_ids:
        shutil.rmtree(os.path.join(tftp_root, 'distrotrees', obs), ignore_errors=True)

    # Fetch images for all the distro trees first.
    print 'Fetching images for all the distro trees'
    distro_trees = _get_all_images(tftp_root, distro_trees)

    x86_distrotrees = [distro for distro in distro_trees if distro['arch'] in ['x86_64', 'i386']]
    print 'Generating PXELINUX menus for %s distro trees' % len(x86_distrotrees)
    makedirs_ignore(os.path.join(tftp_root, 'pxelinux.cfg'), mode=0755)
    pxe_menu = atomically_replaced_file(os.path.join(tftp_root, 'pxelinux.cfg', 'beaker_menu'))
    write_menu(pxe_menu, u'pxelinux-menu', x86_distrotrees)

    x86_efi_distrotrees = [distro for distro in distro_trees if distro['arch'] == 'x86_64']
    # Regardless of any filtering options selected by the admin, we always 
    # filter out certain distros which are known not to have EFI support. This 
    # is a space saving measure for the EFI GRUB menu, which can't be nested so 
    # we try to keep it as small possible.
    x86_efi_distrotrees = [distro for distro in x86_efi_distrotrees
            if not re.match(conf['EFI_EXCLUDED_OSMAJORS_REGEX'], distro['distro_osmajor'])]

    print 'Generating EFI GRUB menus for %s distro trees' % len(x86_efi_distrotrees)
    makedirs_ignore(os.path.join(tftp_root, 'grub'), mode=0755)
    atomic_symlink('../distrotrees', os.path.join(tftp_root, 'grub', 'distrotrees'))
    efi_grub_menu = atomically_replaced_file(os.path.join(tftp_root, 'grub', 'efidefault'))
Beispiel #44
0
def write_menus(tftp_root, tags, xml_filter):
    conf = get_conf()

    # The order of steps for cleaning images is important,
    # to avoid races and to avoid deleting stuff we shouldn't:
    # first read the directory,
    # then fetch the list of trees,
    # and then remove any which aren't in the list.
    try:
        existing_tree_ids = os.listdir(os.path.join(tftp_root, 'distrotrees'))
    except OSError as e:
        if e.errno != errno.ENOENT:
            raise
        existing_tree_ids = []

    proxy = xmlrpclib.ServerProxy('http://localhost:8000', allow_none=True)
    distro_trees = proxy.get_distro_trees({
        'arch': ['x86_64', 'i386', 'aarch64', 'ppc64', 'ppc64le'],
        'tags': tags,
        'xml': xml_filter,
    })
    current_tree_ids = set(str(dt['distro_tree_id'])
                           for dt in distro_trees)
    obsolete_tree_ids = set(existing_tree_ids).difference(current_tree_ids)
    print('Removing images for %s obsolete distro trees' % len(obsolete_tree_ids))
    for obs in obsolete_tree_ids:
        shutil.rmtree(os.path.join(tftp_root, 'distrotrees', obs), ignore_errors=True)

    # Fetch images for all the distro trees first.
    print('Fetching images for all the distro trees')
    distro_trees = _get_all_images(tftp_root, distro_trees)

    x86_distrotrees = [distro for distro in distro_trees if distro['arch'] in ['x86_64', 'i386']]
    print('Generating PXELINUX menus for %s distro trees' % len(x86_distrotrees))
    makedirs_ignore(os.path.join(tftp_root, 'pxelinux.cfg'), mode=0o755)
    pxe_menu = atomically_replaced_file(os.path.join(tftp_root, 'pxelinux.cfg', 'beaker_menu'))
    write_menu(pxe_menu, u'pxelinux-menu', x86_distrotrees)

    x86_efi_distrotrees = [distro for distro in distro_trees if distro['arch'] == 'x86_64']
    # Regardless of any filtering options selected by the admin, we always
    # filter out certain distros which are known not to have EFI support. This
    # is a space saving measure for the EFI GRUB menu, which can't be nested so
    # we try to keep it as small possible.
    x86_efi_distrotrees = [distro for distro in x86_efi_distrotrees
                           if not re.match(conf['EFI_EXCLUDED_OSMAJORS_REGEX'],
                                           distro['distro_osmajor'])]

    print('Generating EFI GRUB menus for %s distro trees' % len(x86_efi_distrotrees))
    makedirs_ignore(os.path.join(tftp_root, 'grub'), mode=0o755)
    atomic_symlink('../distrotrees', os.path.join(tftp_root, 'grub', 'distrotrees'))
    efi_grub_menu = atomically_replaced_file(os.path.join(tftp_root, 'grub', 'efidefault'))
    write_menu(efi_grub_menu, u'efi-grub-menu', x86_efi_distrotrees)

    print('Generating GRUB2 menus for x86 EFI for %s distro trees' % len(x86_efi_distrotrees))
    makedirs_ignore(os.path.join(tftp_root, 'boot', 'grub2'), mode=0o755)
    x86_grub2_menu = atomically_replaced_file(os.path.join(tftp_root, 'boot', 'grub2',
                                                           'beaker_menu_x86.cfg'))
    write_menu(x86_grub2_menu, u'grub2-menu', x86_efi_distrotrees)

    ppc64_distrotrees = [distro for distro in distro_trees if distro['arch'] == 'ppc64']
    if ppc64_distrotrees:
        print('Generating GRUB2 menus for PPC64 EFI for %s distro trees' % len(ppc64_distrotrees))
        makedirs_ignore(os.path.join(tftp_root, 'boot', 'grub2'), mode=0o755)
        ppc64_grub2_menu = atomically_replaced_file(os.path.join(tftp_root, 'boot', 'grub2',
                                                                 'beaker_menu_ppc64.cfg'))
        write_menu(ppc64_grub2_menu, u'grub2-menu', ppc64_distrotrees)

    ppc64le_distrotrees = [distro for distro in distro_trees if distro['arch'] == 'ppc64le']
    if ppc64le_distrotrees:
        print('Generating GRUB2 menus for PPC64LE EFI for %s distro trees' % len(ppc64_distrotrees))
        makedirs_ignore(os.path.join(tftp_root, 'boot', 'grub2'), mode=0o755)
        ppc64le_grub2_menu = atomically_replaced_file(os.path.join(tftp_root, 'boot', 'grub2',
                                                                   'beaker_menu_ppc64le.cfg'))
        write_menu(ppc64le_grub2_menu, u'grub2-menu', ppc64le_distrotrees)

    # XXX: would be nice if we can find a good time to move this into boot/grub2
    aarch64_distrotrees = [distro for distro in distro_trees if distro['arch'] == 'aarch64']
    if aarch64_distrotrees:
        print('Generating GRUB2 menus for aarch64 for %s distro trees' % len(aarch64_distrotrees))
        makedirs_ignore(os.path.join(tftp_root, 'aarch64'), mode=0o755)
        aarch64_menu = atomically_replaced_file(
            os.path.join(tftp_root, 'aarch64', 'beaker_menu.cfg'))
        write_menu(aarch64_menu, u'grub2-menu', aarch64_distrotrees)
Beispiel #45
0
 def setUpClass(cls):
     makedirs_ignore(get_conf().get('CONSOLE_LOGS'), 0o755)