diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7243ae5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +__pycache__/ +*.swp diff --git a/boottoolsfunctions/__init__.py b/boottoolsfunctions/__init__.py new file mode 100644 index 0000000..ba421fc --- /dev/null +++ b/boottoolsfunctions/__init__.py @@ -0,0 +1,230 @@ + +import platform +import os +import re +import time +import logging +import subprocess + +logging.basicConfig (filename='/tmp/boot-tools_installation.log', filemode='a', format='%(levelname)s %(asctime)s (%(threadName)s) (%(funcName)s) %(message)s', level=logging.INFO) +logger = logging.getLogger ('boottools') + +def btogGetVar(osarch): + btdir = '/tmp/opengnsys_installer/opengnsys/client/boot-tools' + bttargetdir = '/var/lib/tftpboot/ogclient/' + btrootfsimg = os.path.join (bttargetdir, 'ogclient.img') + btrootfsmnt = os.path.join (bttargetdir, 'ogclientmount') + btrootfsimglabel = 'ogClient' + log_file = '/tmp/boot-tools_installation.log' + versionboottools = 'ogLive' + if 'i386' == osarch: + btvirtualdisksize = '2000' # tamaño maximo limitado por schroot 2GB para 32 bits + else: + btvirtualdisksize = '3G' + return btdir, bttargetdir, btrootfsimg, btrootfsmnt, btrootfsimglabel, log_file, versionboottools, btvirtualdisksize + +def btogGetOsInfo1(type_client): + ogclientcfg = '/tmp/ogclient.cfg' + if 'precise' == type_client: # ogLive 1.0.4-rc2 basado en Ubuntu 12.04 LTS. + osdistrib='ubuntu' + oscodename='precise' + osrelease='3.2.0-23-generic' + osarch='i386' + oshttp='http://es.archive.ubuntu.com/ubuntu/' + elif 'wheezy' == type_client: # ogLive basado en Debian 7.3. + osdistrib='debian' + oscodename='wheezy' + osrelease='3.2.0-4-i386' + osarch='i386' + oshttp='http://ftp.es.debian.org/debian/' + elif 'quantal' == type_client: # ogLive 1.0.5-rc2 basado en Ubuntu 12.10 con Kernel descargado. + osdistrib='ubuntu' + oscodename='quantal' + osrelease='3.7.6-030706-generic' + osarch='i386' + oshttp='http://es.archive.ubuntu.com/ubuntu/' + elif 'raring' == type_client: # ogLive 1.0.5-rc3 basado en Ubuntu 13.04. + osdistrib='ubuntu' + oscodename='raring' + osrelease='3.8.0-22-generic' + osarch='i386' + oshttp='http://es.archive.ubuntu.com/ubuntu/' + elif 'trusty' == type_client: # ogLive 1.0.5-rc4 basado en Ubuntu 14.04. + osdistrib='ubuntu' + oscodename='trusty' + osrelease='3.13.0-24-generic' + osarch='i386' + oshttp='http://es.archive.ubuntu.com/ubuntu/' + elif 'vivid' == type_client: # ogLive 1.1.0-rc2 basado en Ubuntu 15.04. + osdistrib='ubuntu' + oscodename='vivid' + osrelease='3.19.0-49-generic' + osarch='i386' + oshttp='http://es.archive.ubuntu.com/ubuntu/' + elif 'wily' == type_client: # ogLive 1.1.0-rc1 basado en Ubuntu 15.10. + osdistrib='ubuntu' + oscodename='wily' + osrelease='4.2.0-35-generic' + osarch='i386' + oshttp='http://es.archive.ubuntu.com/ubuntu/' + elif 'xenial' == type_client or 'xenial-4.4' == type_client: # ogLive 1.1.0-rc4 basado en Ubuntu 16.04 y Kernel 4.4. + osdistrib='ubuntu' + oscodename='xenial' + osrelease='4.4.0-34-generic' + osarch='i386' + oshttp='http://es.archive.ubuntu.com/ubuntu/' + elif 'xenial-4.8' == type_client: # ogLive 1.1.0-rc5 basado en Ubuntu 16.04 y Kernel 4.8. + osdistrib='ubuntu' + oscodename='xenial' + osrelease='4.8.0-39-generic' + osarch='amd64' + oshttp='http://es.archive.ubuntu.com/ubuntu/' + elif 'xenial-4.13' == type_client: # ogLive 1.1.0-rc6 basado en Ubuntu 16.04 y Kernel 4.13. + osdistrib='ubuntu' + oscodename='xenial' + osrelease='4.13.0-17-generic' + osarch='amd64' + oshttp='http://es.archive.ubuntu.com/ubuntu/' + elif 'bionic' == type_client or 'bionic-4.15' == type_client: # ogLive 1.1.1-rc1 basado en Ubuntu 18.04 y Kernel 4.15. + osdistrib='ubuntu' + oscodename='bionic' + osrelease='4.15.0-32-generic' + osarch='amd64' + oshttp='http://es.archive.ubuntu.com/ubuntu/' + elif 'bionic-4.18' == type_client: # ogLive 1.1.1-rc3 basado en Ubuntu 18.04 y Kernel 4.18. + osdistrib='ubuntu' + oscodename='bionic' + osrelease='4.18.0-20-generic' + osarch='amd64' + oshttp='http://es.archive.ubuntu.com/ubuntu/' + elif 'bionic-5.0' == type_client: # ogLive 1.1.1-rc5 basado en Ubuntu 18.04 y Kernel 5.0. + osdistrib='ubuntu' + oscodename='bionic' + osrelease='5.0.0-27-generic' + osarch='amd64' + oshttp='http://es.archive.ubuntu.com/ubuntu/' + elif 'focal' == type_client: # ogLive 1.2.0-rc1 basado en Ubuntu 20.04 y Kernel 5.4. + osdistrib='ubuntu' + oscodename='focal' + osrelease='5.4.0-42-generic' + osarch='amd64' + oshttp='http://es.archive.ubuntu.com/ubuntu/' + elif 'host' == type_client: # ogLive basado en la distribución del servidor. + osdistrib=platform.freedesktop_os_release()['NAME'] + oscodename=platform.freedesktop_os_release()['VERSION_CODENAME'] + osrelease=platform.uname()[2] + osarch=subprocess.run (['dpkg', '--print-architecture'], capture_output=True).stdout.decode ('utf-8').strip() + oshttp='http://es.archive.ubuntu.com/ubuntu/' + else: # Parámetro desconocido + print ('Parámetro no válido.') + os.exit (1) + return ogclientcfg, osdistrib, oscodename, osrelease, osarch, oshttp + +def btogGetOsInfo2(type_client, versionboottools, ogclientcfg, osdistrib, oscodename, osrelease, osarch, oshttp): + branch = 'master' + giturl = 'https://api.github.com/repos/opengnsys/OpenGnsys/commits?sha={}&path=/client'.format (branch) + gitrelease = 'r20240808' ## TODO: are we going to keep the following? $(curl -s "$GITURL" | jq -r '"r" + (.[0].commit.committer.date | split("-") | join("")[:8]) + "." + (.[0].sha[:7])') + nameisoclient ='-'.join ([versionboottools, oscodename, osrelease, osarch, gitrelease]) + namehostclient = '-'.join ([versionboottools, oscodename, gitrelease]) + + ### El fichero de configuración debe sustituir a estos 3 ficheros (borrar las 3 líneas siguientes). + #echo "$NAMEISOCLIENT" > /tmp/opengnsys_info_rootfs + #echo "$NAMEHOSTCLIENT" > /tmp/opengnsys_chroot + + # Generar fichero de configuración. + with open(ogclientcfg, 'w') as f: + print ('TYPECLIENT="{}"'.format (type_client), file=f) + print ('OSDISTRIB="{}"'.format (osdistrib), file=f) + print ('OSCODENAME="{}"'.format (oscodename), file=f) + print ('OSRELEASE="{}"'.format (osrelease), file=f) + print ('OSARCH="{}"'.format (osarch), file=f) + print ('OSHTTP="{}"'.format (oshttp), file=f) + print ('GITRELEASE="{}"'.format (gitrelease, file=f)) + print ('NAMEISOCLIENT="{}"'.format (nameisoclient), file=f) + print ('NAMEHOSTCLIENT="{}"'.format (namehostclient), file=f) + + return gitrelease, nameisoclient, namehostclient + +def _run(args): + cp = subprocess.run (args, capture_output=True) + if cp.returncode: + logger.error ('command "{}" failed with rc "{}"'.format (' '.join(args), cp.returncode)) + raise + stdout = cp.stdout.decode ('utf-8').strip() + stderr = cp.stderr.decode ('utf-8').strip() + return stdout, stderr + +def _grep (regex, file): + with open (file, 'r') as f: + for l in f: + if (re.findall (regex, l)): return 1 + return 0 + +def _is_mounted (mntpt): + return _grep (mntpt, '/proc_mounts') + +def _umount (mntpt): + if (_is_mounted (mntpt)): + subprocess.run (['umount', mntpt]) + +def btogSetFsVirtual(btrootfsimg, btrootfsmnt, btvirtualdisksize, bttargetdir, osarch): + #if not btrootfsimg: btogGetVar() + + logger.info ('Creación y formateo del disco virtual "{}" MB'.format (btvirtualdisksize)) + + try: _umount (btrootfsmnt) + except: return 1 + + if (_is_mounted (btrootfsmnt)): + logger.error ('failed to umount "{}"'.format (btrootfsmnt)) + return 1 + + if (not os.makedirs (btrootfsmnt)): + logger.error ('Creando directorio "{}" : ERROR'.format (btrootfsmnt)) + return 1 + + try: _run (['chown', '-R', 'root:opengnsys', bttargetdir]) + except: return 1 + + if 'i386' == osarch: + try: _run (['dd', 'if=/dev/zero', 'of={}'.format (btrootfsimg), 'bs=1048576', 'count={}'.format (btvirtualdisksize)]) + except: + logger.error ('Creando el disco virtual con tamaño maxima "{}" MB : ERROR'.format (btvirtualdisksize)) + return 2 + else: + try: _run (['qemu-img', 'create', btrootfsimg, btvirtualdisksize]) + except: + logger.error ('Creando el disco virtual con tamaño maxima "{}" MB : ERROR'.format (btvirtualdisksize)) + return 2 + + diskloop, _ = _run (['losetup', '-f']) + if not diskloop: + logger.error ('no diskloop') + return 2 + print (diskloop) + + try: _run (['losetup', diskloop, btrootfsimg]) + except: return 2 + + subprocess.run ("echo -e \"n\np\n1\n\n\nt\n83\nw\" |fdisk {}".format (diskloop), shell=True) + + time.sleep (10) + try: _run (['losetup', '-d', diskloop]) + except: + logger.error ('Liberando disco virtual despues del particionado: ERROR') + return 2 + + partloop, _ = _run (['losetup', '-f']) + _run (['losetup', '-o', '32256', partloop, btrootfsimg]) + try: _run (['mkfs.ext4', '-b', '4096', '-L', btrootfsimglabel, partloop]) + except: + logger.error ('Formateando la particion principal del disco virtual: ERROR') + return 2 + + time.sleep (10) + try: _run (['losetup', '-d', partloop]) + except: + logger.error ('Liberando la particion virtual despues del formateo: ERROR') + return 2 + + logger.info ('"{}" "{}" MB : OK'.format (btrootfsimg, btvirtualdisksize)) diff --git a/boottoolsgenerator.py b/boottoolsgenerator.py new file mode 100755 index 0000000..5325de9 --- /dev/null +++ b/boottoolsgenerator.py @@ -0,0 +1,134 @@ +#!/usr/bin/python3 + +import sys +import os +import logging + +sys.path.insert (0, __file__) +from boottoolsfunctions import btogGetOsInfo1, btogGetOsInfo2, btogGetVar + +logging.basicConfig (filename='/tmp/boot-tools_installation.log', filemode='a', format='%(levelname)s %(asctime)s (%(threadName)s) (%(funcName)s) %(message)s', level=logging.INFO) +logger = logging.getLogger ('boottools') + +#BRANCH = 'branches/master' +#svn export --force https://github.com/opengnsys/OpenGnsys/$BRANCH/client /tmp/opengnsys_installer/opengnsys/client + +type_client = sys.argv[1] if len(sys.argv)>1 else 'host' +#WORKDIR = '/tmp/opengnsys_installer' +#INSTALL_TARGET = '/opt/opengnsys' +#PROGRAMDIR = $(readlink -e $(dirname "$0")) + +if os.getuid(): + logger.error ('ERROR: this program must run under root privileges!!') + os._exit (1) + +os.chdir ('/tmp') + +#for i in `mount | grep IMGogclient | grep /var | cut -f3 -d" "`; do echo $i; umount $i; done +#for i in `mount | grep IMGogclient | grep /var | cut -f3 -d" "`; do echo $i; umount $i; done +#for i in `mount | grep IMGogclient | grep /var | cut -f3 -d" "`; do echo $i; umount $i; done + + + +####################################################################3 +logger.info ('FASE 1 - Asignación de variables') +ogclientcfg, osdistrib, oscodename, osrelease, osarch, oshttp = btogGetOsInfo1(type_client) +print (osarch) +btdir, bttargetdir, btrootfsimg, btrootfsmnt, btrootfsimglabel, log_file, versionboottools, btvirtualdisksize = btogGetVar(osarch) +print (btdir) +gitrelease, nameisoclient, namehostclient = btogGetOsInfo2(type_client, versionboottools, ogclientcfg, osdistrib, oscodename, osrelease, osarch, oshttp) +print (nameisoclient) +logger.info ('OpenGnsys CLIENT installation begins') + + +########################################################################## +logger.info ('FASE 2 - Instalación de software adicional.') +""" +#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 +apt-get update >>/tmp/fase2.out +[ -n "$(apt-cache search gpxe)" ] && PXEPKG="gpxe" +[ -n "$(apt-cache search ipxe)" ] && PXEPKG="ipxe" +apt-get -y install debootstrap subversion schroot squashfs-tools syslinux genisoimage $PXEPKG qemu qemu-utils lsof >>/tmp/fase2.out + + +###################################################################3 +logger.info ('FASE 3 - Creación del Sistema raiz RootFS (Segundo Sistema archivos (img))') +logger.info ('Fase 3.1 Generar y formatear el disco virtual. Generar el dispositivo loop.') +file $BTROOTFSIMG | grep "partition 1: ID=0x83" +if [ $? == 1 ]: + btogSetFsVirtual || exit 2 + echo ================= nati after btogSetFsVirtual; ls -la /opt/opengnsys/tftpboot/ogclient/ + +logger.info ('Fase 3.2 Generar sistema de archivos con debootstrap') +schroot -p -c IMGogclient -- touch /tmp/ogclientOK +if [ -f /tmp/ogclientOK ] +then + rm /tmp/ogclientOK +else + btogSetFsBase >>/tmp/fase3.out +fi +echo ================= nati after fase 3; ls -la /opt/opengnsys/tftpboot/ogclient/ + + +###################################################################3 +logger.info ('FASE 4 - Configurar acceso schroot al Segundo Sistema de archivos (img)') +cat /etc/schroot/schroot.conf | grep $BTROOTFSIMG || btogSetFsAccess + + +########################################################################### +logger.info ('FASE 5 - Incorporando ficheros OpenGnsys al sistema raíz rootfs') +cp -a ${BTDIR}/includes/usr/bin/* /tmp >>/tmp/fase5.out +chmod +x /tmp/boot-tools/*.sh +# Incluir revisión. +sed -i "1 s/$/ $GITRELEASE ($OSRELEASE)/" ${BTDIR}/includes/etc/initramfs-tools/scripts/VERSION.txt +# En Ubuntu 13.04+ es necesario matar proceso de "udev" antes de desmontar. +umount $BTROOTFSMNT 2>/dev/null || (kill -9 $(lsof -t $BTROOTFSMNT); umount $BTROOTFSMNT) 2>/dev/null +schroot -p -c IMGogclient -- /tmp/boot-tools/boottoolsFsOpengnsys.sh >>/tmp/fase5.out + + +############################################################################################ +logger.info ('FASE 6 - Instalar software') +logger.info ('Fase 6.1 instalar paquetes deb con apt-get') +schroot -p -c IMGogclient -- /usr/bin/boot-tools/boottoolsSoftwareInstall.sh >>/tmp/fase6.out +logger.info ('Fase 6.2 compilar software.') +cd / +schroot -p -c IMGogclient -- /usr/bin/boot-tools/boottoolsSoftwareCompile.sh >>/tmp/fase6.out +cd - + + +############################################################################################ +logger.info ('FASE 7 - Personalizar el sistema creado') +logger.info ('Fase 7.1 Incorporar la clave publica del servidor') +cd / +ssh-keygen -q -f /root/.ssh/id_rsa -N "" +cp /root/.ssh/id_rsa.pub /tmp +schroot -p -c IMGogclient -- /usr/bin/boot-tools/boottoolsSshServer.sh +cd - +logger.info ('Fase 7.2. Incorpoar la clave publica del propio cliente') +schroot -p -c IMGogclient -- /usr/bin/boot-tools/boottoolsSshClient.sh + +logger.info ('Fase 7.3. Configurando las locales') +schroot -p -c IMGogclient -- /usr/bin/boot-tools/boottoolsFsLocales.sh + +for i in `mount | grep IMGogclient | grep /var | cut -f3 -d" "`; do echo $i; umount $i; done +for i in `mount | grep IMGogclient | grep /var | cut -f3 -d" "`; do echo $i; umount $i; done +for i in `mount | grep IMGogclient | grep /var | cut -f3 -d" "`; do echo $i; umount $i; done + +echo ================= nati after fase 7; ls -la /opt/opengnsys/tftpboot/ogclient/ + + +######################################################################### +logger.info ('FASE 8 - Generar distribucion') +logger.info ('Fase 8.1 Generar el initrd') +btogFsInitrd >>/tmp/fase8.out +echo ================= nati after fase 8.1; ls -la /opt/opengnsys/tftpboot/ogclient/ +logger.info ('Fase 8.2 Generar fichero sqfs a partir del fichero img') +btogFsSqfs +echo ================= nati after fase 8.2; ls -la /opt/opengnsys/tftpboot/ogclient/ +umount $BTROOTFSMNT 2>/dev/null +logger.info ('Fase 8.3 Generar la ISO') +btogIsoGenerator >>/tmp/fase8.out +echo ================= nati after fase 8.3; ls -la /opt/opengnsys/tftpboot/ogclient/ + +echoAndLog "OpenGnsys installation finished at $(date)" +"""