#!/usr/bin/python3 import sys import os import logging import subprocess import glob import stat import shutil import argparse curdir = os.path.dirname (__file__) sys.path.insert (0, curdir) from boottools import utils, apt, btog os.chdir (curdir) def _logging (lvl='INFO', logfile='/tmp/boot-tools_installation.log'): numeric_level = getattr (logging, lvl.upper(), None) if numeric_level is None: numeric_level = getattr (logging, 'INFO') logging.basicConfig ( format='%(levelname)s %(asctime)s (%(funcName)s) %(message)s', level=numeric_level, handlers = [ logging.FileHandler (logfile), logging.StreamHandler (sys.stdout), ], ) return logging.getLogger ('boottools') def _mount_rootfs(): global btrootfsimg, btrootfsmnt try: utils.mount (btrootfsimg, btrootfsmnt, opts=['-o', 'loop,offset=32256']) except: logger.error ('mount failed') sys.exit (1) def _get_pxepkg(): #grep "http://free.nchc.org.tw/drbl-core" /etc/apt/sources.list || echo "deb http://free.nchc.org.tw/drbl-core drbl stable" >> /etc/apt/sources.list pxepkg = None cache = apt.cache_search (['gpxe', 'ipxe']) if cache['gpxe']: pxepkg = 'gpxe' if cache['ipxe']: pxepkg = 'ipxe' if pxepkg is None: logger.error ('neither gpxe nor ipxe found in apt cache') sys.exit (1) logger.info (f'PXE package is "{pxepkg}"') return pxepkg def _mkrootfs (btrootfsimg, btrootfsmnt, btrootfsimglabel, btvirtualdisksize, bttargetdir, osarch): logger.info ('Stage 1.1 - create, partition and format the rootfs') rc = subprocess.run (f'file "{btrootfsimg}" |grep -q "partition 1 *: ID=0x83"', shell=True).returncode if (rc): ## 'file|grep' failed try: btog.mkrootfs (btrootfsimg, btrootfsimglabel, btrootfsmnt, btvirtualdisksize, bttargetdir, osarch) except Exception as e: logger.error (str (e)) sys.exit (1) ## para hacer schroot --cosas, el mntpt tiene que estar desmontado ## si está montado da un pete tal que 'E: 10mount: mount: /run/schroot/mount/IMGogclient-7fbf51a2-e37e-48e5-8e5d-83f8901fc7ed: wrong fs type, bad option, bad superblock on /dev/loop1, missing codepage or helper program, or other error.' def _debootstrap (btrootfsimg, btrootfsmnt, osarch, oscodename, oshttp): logger.info ('Stage 1.2 - debootstrap system') logger.debug ('Try creation of a file within chroot (this operation may fail with "... etc/resolv.conf: No such file or directory"--that is ok)') logger.debug ('Running \'schroot --chroot IMGogclient -- stat /etc\'') cp = subprocess.run (['schroot', '--chroot', 'IMGogclient', '--', 'stat', '/etc']) if (cp.returncode): logger.debug (f'schroot returned code "{cp.returncode}", calling btog.debootstrap()') _mount_rootfs() try: btog.debootstrap (btrootfsimg, btrootfsmnt, osarch, oscodename, oshttp) except Exception as e: logger.error (str (e)) sys.exit (1) # Incluir revisión. def _initramfs_version (gitrelease, osrelease, curdir): ## FIXME esto la incluye incondicionalmente, y luego terminamos con "OpenGnsys Client 1.2.0-rc1 gitrelease (osrelease) gitrelease (osrelease) gitrelease (osrelease) gitrelease (osrelease) gitrelease (osrelease) gitrelease (osrelease) ..." #sed -i "1 s/$/ $GITRELEASE ($OSRELEASE)/" ${BTDIR}/includes/etc/initramfs-tools/scripts/VERSION.txt utils.run (['sed', '-i', f'1 s/$/ {gitrelease} ({osrelease})/', f'{curdir}/includes/etc/initramfs-tools/scripts/VERSION.txt']) def _copy_og_files (btrootfsmnt, osdistrib, oscodename): _mount_rootfs() builder = '/tmp/opengnsys/oglive_builder' og_shared = '/tmp/opengnsys/shared' og_engine = '/tmp/opengnsys/engine' btog.copy_og_files (builder, og_shared, og_engine, btrootfsmnt, osdistrib, oscodename) utils.umount (btrootfsmnt) def _chroot_tasks (curdir, osrelease, osarch): logger.debug (f'running \'schroot --chroot IMGogclient -- {curdir}/chroot-tasks.py --osrelease "{osrelease}" --osarch "{osarch}"\'') stdout, _ = utils.run (['schroot', '--chroot', 'IMGogclient', '--', f'{curdir}/chroot-tasks.py', '--osrelease', osrelease, '--osarch', osarch, '--config', args.config or 'mkoglive.cfg']) ## esto deja initrd.img-6.8.0-31-generic y vmlinuz-6.8.0-31-generic en /tmp def _ssh_stuff (btrootfsmnt): _mount_rootfs() btog.ssh_server (btrootfsmnt) btog.ssh_client (btrootfsmnt) utils.umount (btrootfsmnt) ## el resultado es: ## - hay un nuevo par de claves en la VM /root/.ssh ## - hay otro nuevo par de claves en el rootfs /var/lib/tftpboot/ogclient/ogclientmount/root/.ssh ## - las dos claves públicas (una de cada par) están autorizadan en el rootfs /var/lib/tftpboot/ogclient/ogclientmount/root/.ssh/authorized_keys def _mkinitrd_squashfs_isofs (bttargetdir, osrelease, btrootfsmnt, pxepkg, isolinux_tpl, nameisoclient): logger.info ('Stage 4.1 - Put initrd in place') _mount_rootfs() btog.move_initrd (bttargetdir, osrelease) logger.info ('Stage 4.2 - make squash filesystem') btog.mksquashfs (bttargetdir, btrootfsmnt) utils.umount (btrootfsmnt) logger.info ('Stage 4.3 - make iso filesystem') btog.mkisofs (pxepkg, isolinux_tpl, bttargetdir, nameisoclient) parser = argparse.ArgumentParser() parser.add_argument ('--loglevel', help='Log level', action='store') parser.add_argument ('--codename', help='OS codename', action='store') parser.add_argument ('--config', help='Path to configuration file', action='store') args = parser.parse_args() config = utils.read_config (args.config or 'mkoglive.cfg') if config is None: sys.exit (1) isolinux_tpl = config['General'].get ('isolinux_template') cfg_loglevel = config['General'].get ('logging_level') btrootfsimglabel = config['General'].get ('rootfs_image_label') logger = _logging (args.loglevel or cfg_loglevel) type_client = args.codename or 'host' if os.getuid(): logger.error ('ERROR: this program must run under root privileges!!') sys.exit (1) ## this is convenient in case the previous run failed and we want to run this program again try: utils.umount (btrootfsmnt) except: pass logger.info ('OpenGnsys CLIENT installation begins') fd = open (f'{curdir}/gitrelease', 'r') ## per the Dockerfile gitrelease = fd.readline().strip() fd.close() osdistrib, oscodename, osrelease, osarch, oshttp = btog.GetOsInfo (type_client) if osdistrib is None: logger.error ('GetOsInfo() failed') sys.exit (1) bttargetdir, btrootfsimg, btrootfsmnt, btvirtualdisksize = btog.GetVar (osarch) logger.info (':'.join ([osdistrib, oscodename, osrelease, osarch, oshttp])) logger.info ('STAGE 1 - create and bootstrap rootfs') _mkrootfs (btrootfsimg, btrootfsmnt, btrootfsimglabel, btvirtualdisksize, bttargetdir, osarch) _debootstrap (btrootfsimg, btrootfsmnt, osarch, oscodename, oshttp) logger.info ('STAGE 2 - copy files to the rootfs') _initramfs_version (gitrelease, osrelease, curdir) _copy_og_files (btrootfsmnt, osdistrib, oscodename) logger.info ('STAGE 3 - perform tasks within the chroot') _chroot_tasks (curdir, osrelease, osarch) _ssh_stuff (btrootfsmnt) logger.info ('STAGE 4 - generate distribution files') pxepkg = _get_pxepkg() nameisoclient = '-'.join (['ogLive', oscodename, osrelease, osarch, gitrelease]) _mkinitrd_squashfs_isofs (bttargetdir, osrelease, btrootfsmnt, pxepkg, isolinux_tpl, nameisoclient) logger.info ('OpenGnsys installation finished')