def on_btnLocalize_clicked(self, widget): # Set locale selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) for path in selected: rootPath = "%s/root" % path de = EditDistro(path) script = "setlocale.sh" scriptSource = join(self.scriptDir, "files/{}".format(script)) scriptTarget = join(rootPath, script) if exists(scriptSource): copy(scriptSource, scriptTarget) self.ec.run("chmod a+x '%s'" % scriptTarget) de.openTerminal("/bin/bash %s" % script) silent_remove(scriptTarget) # Copy Grub locale files to ISO boot directory and configure grub.cfg grub_path = "%s/boot/boot/grub/" % path grubcfg_path = "%s/grub.cfg" % grub_path locale_path = "%s/root/boot/grub/locale" % path default_path = "%s/root/etc/default" % path locale = self.ec.run("grep -oP '(?<=LANG=).*?(?=\.)' %s/locale" % default_path)[0] if exists(locale_path) and \ exists(grubcfg_path) and \ locale: self.ec.run("cp -rf %s %s" % (locale_path, grub_path)) self.ec.run("sed -i 's/set lang=.*/set lang=%s/' %s" % (locale, grubcfg_path))
def download_offline_packages(self, path): rootPath = "%s/root" % path arch = getGuestEfiArchitecture(rootPath) de = EditDistro(path) script = "offline.sh" scriptSource = join(self.scriptDir, "files/{}".format(script)) scriptTarget = join(rootPath, script) offlineSource = join(rootPath, "offline") offlineTarget = join(rootPath, "../boot/offline") if exists(scriptSource): try: copy(scriptSource, scriptTarget) self.ec.run("chmod a+x '%s'" % scriptTarget) # Run the script de.openTerminal("/bin/bash {} {}".format(script, arch)) # Remove script silent_remove(scriptTarget) # Move offline directory to boot directory if exists(offlineSource): print(("%s exists" % offlineSource)) if exists(offlineTarget): print((">> Remove %s" % offlineTarget)) silent_remove(offlineTarget) print((">> Move %s to %s" % (offlineSource, offlineTarget))) move(offlineSource, offlineTarget) else: print((">> Cannot find: %s" % offlineSource)) except Exception as detail: self.showError("Error: getting offline packages", detail, self.window) else: print((">> Cannot find: %s" % scriptSource))
def on_btnUpgrade_clicked(self, widget): selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) upgraded = False for path in selected: upgraded = True rootPath = "%s/root" % path force = get_apt_force(rootPath) de = EditDistro(path) de.openTerminal("apt-get update") if exists(join(rootPath, 'etc/apache2/apache2.conf')): de.openTerminal("service apache2 start") if exists(join(rootPath, 'etc/mysql/debian.cnf')): de.openTerminal("service mysql start") de.openTerminal("apt-get -y %s -o Dpkg::Options::=\"--force-confnew\" dist-upgrade" % force) if exists(join(rootPath, 'etc/apache2/apache2.conf')): de.openTerminal("service apache2 stop") if exists(join(rootPath, 'etc/mysql/debian.cnf')): de.openTerminal("service mysql stop") # Cleanup old kernel and headers script = "rmoldkernel.sh" scriptSource = join(self.scriptDir, "files/{}".format(script)) scriptTarget = join(rootPath, script) if exists(scriptSource): copy(scriptSource, scriptTarget) self.ec.run("chmod a+x '%s'" % scriptTarget) de.openTerminal("/bin/bash %s" % script) silent_remove(scriptTarget) # Download offline packages print(">> Start downloading offline packages") self.download_offline_packages(path) if upgraded and exists("/usr/bin/aplay") and exists(self.doneWav): self.ec.run("/usr/bin/aplay '%s'" % self.doneWav, False)
def on_btnLocalize_clicked(self, widget): # Set locale selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) for path in selected: rootPath = "%s/root" % path de = EditDistro(path) script = "setlocale.sh" scriptSource = join(self.scriptDir, "files/{}".format(script)) scriptTarget = join(rootPath, script) if exists(scriptSource): copy(scriptSource, scriptTarget) self.ec.run("chmod a+x %s" % scriptTarget) de.openTerminal("/bin/bash %s" % script) silent_remove(scriptTarget)
def on_btnLocalize_clicked(self, widget): # Set locale selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) for path in selected: rootPath = "%s/root" % path de = EditDistro(path) script = "setlocale.sh" scriptSource = join(self.scriptDir, "files/{}".format(script)) scriptTarget = join(rootPath, script) if exists(scriptSource): copy(scriptSource, scriptTarget) self.ec.run("chmod a+x '%s'" % scriptTarget) de.openTerminal("/bin/bash %s" % script) silent_remove(scriptTarget)
def on_btnUpgrade_clicked(self, widget): selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) upgraded = False for path in selected: upgraded = True rootPath = "%s/root" % path force = get_apt_force(rootPath) de = EditDistro(path) de.openTerminal("apt-get update") if exists(join(rootPath, 'etc/apache2/apache2.conf')): de.openTerminal("service apache2 start") if exists(join(rootPath, 'etc/mysql/debian.cnf')): de.openTerminal("service mysql start") de.openTerminal( "apt-get -y %s -o Dpkg::Options::=\"--force-confnew\" dist-upgrade" % force) if exists(join(rootPath, 'etc/apache2/apache2.conf')): de.openTerminal("service apache2 stop") if exists(join(rootPath, 'etc/mysql/debian.cnf')): de.openTerminal("service mysql stop") # Cleanup old kernel and headers script = "rmoldkernel.sh" scriptSource = join(self.scriptDir, "files/{}".format(script)) scriptTarget = join(rootPath, script) if exists(scriptSource): copy(scriptSource, scriptTarget) self.ec.run("chmod a+x '%s'" % scriptTarget) de.openTerminal("/bin/bash %s" % script) silent_remove(scriptTarget) # Download offline packages print(">> Start downloading offline packages") self.download_offline_packages() if upgraded and exists("/usr/bin/aplay") and exists(self.doneWav): self.ec.run("/usr/bin/aplay '%s'" % self.doneWav, False)
def download_offline_packages(self): selected = self.tvHandlerDistros.getToggledValues(toggleColNr=0, valueColNr=2) for path in selected: rootPath = "%s/root" % path arch = getGuestEfiArchitecture(rootPath) de = EditDistro(path) script = "offline.sh" scriptSource = join(self.scriptDir, "files/{}".format(script)) scriptTarget = join(rootPath, script) offlineSource = join(rootPath, "offline") offlineTarget = join(rootPath, "../boot/offline") if exists(scriptSource): try: copy(scriptSource, scriptTarget) self.ec.run("chmod a+x '%s'" % scriptTarget) # Run the script de.openTerminal("/bin/bash {} {}".format(script, arch)) # Remove script silent_remove(scriptTarget) # Move offline directory to boot directory if exists(offlineSource): print(("%s exists" % offlineSource)) if exists(offlineTarget): print((">> Remove %s" % offlineTarget)) silent_remove(offlineTarget) print((">> Move %s to %s" % (offlineSource, offlineTarget))) move(offlineSource, offlineTarget) else: print((">> Cannot find: %s" % offlineSource)) except Exception as detail: self.showError("Error: getting offline packages", detail, self.window) else: print((">> Cannot find: %s" % scriptSource))
def openTerminal(self, command=""): # Set some paths resolveCnfHost = "/etc/resolv.conf" resolveCnf = join(self.rootPath, "etc/resolv.conf") resolveCnfBak = "%s.bk" % resolveCnf wgetrc = join(self.rootPath, "etc/wgetrc") wgetrcBak = "%s.bk" % wgetrc terminal = "/tmp/constructor-terminal.sh" lockDir = join(self.rootPath, "run/lock/") proc = join(self.rootPath, "proc/") dev = join(self.rootPath, "dev/") pts = join(self.rootPath, "dev/pts/") sys = join(self.rootPath, "sys/") policy = join(self.rootPath, "usr/sbin/policy-rc.d") ischroot = join(self.rootPath, "usr/bin/ischroot") ischrootTmp = join(self.rootPath, "usr/bin/ischroot.tmp") try: # temporary create /run/lock if not exists(lockDir): makedirs(lockDir) # setup environment # copy dns info if exists(resolveCnf): move(resolveCnf, resolveCnfBak) if exists(resolveCnfHost): copy(resolveCnfHost, resolveCnf) # umount /proc /dev /dev/pts /sys self.unmount([pts, dev, proc, sys]) # mount /proc /dev /dev/pts /sys /run /sys self.ec.run("mount --bind /proc '%s'" % proc) self.ec.run("mount --bind /dev '%s'" % dev) self.ec.run("mount --bind /dev/pts '%s'" % pts) self.ec.run("mount --bind /sys '%s'" % sys) # copy wgetrc move(wgetrc, wgetrcBak) copy("/etc/wgetrc", wgetrc) # Let dpkg only start daemons when desired scr = "#!/bin/sh\nexit 101\n" with open(policy, 'w') as f: f.write(scr) self.ec.run("chmod a+x '%s'" % policy) # Temporary fix ischroot if not exists(ischrootTmp): self.ec.run("mv '%s' '%s'" % (ischroot, ischrootTmp)) if not exists(ischroot): self.ec.run("ln -s /bin/true '%s'" % ischroot) # HACK: create temporary script for chrooting silent_remove(terminal) scr = "#!/bin/sh\nchroot '%s' %s\n" % (self.rootPath, command) with open(terminal, 'w') as f: f.write(scr) self.ec.run("chmod a+x '%s'" % terminal) if exists("/usr/bin/xterm"): self.ec.run('export HOME=/root ; xterm -bg black -fg white -rightbar -title \"%s\" -e %s' % (self.description, terminal)) elif self.ec.run('which x-terminal-emulator'): # use x-terminal-emulator if xterm isn't available self.ec.run('export HOME=/root ; x-terminal-emulator -e %s' % terminal) else: print('Error: no valid terminal found') # restore wgetrc move(wgetrcBak, wgetrc) # move dns info if exists(resolveCnfBak): move(resolveCnfBak, resolveCnf) else: silent_remove(resolveCnf) # umount /proc /dev /dev/pts /sys self.unmount([pts, dev, proc, sys]) # remove temp script silent_remove(terminal) # remove policy script silent_remove(policy) # replace ischroot if exists("%s.tmp" % ischroot): self.ec.run("rm '%s'" % ischroot) self.ec.run("mv '%s.tmp' '%s'" % (ischroot, ischroot)) # cleanup /run self.ec.run("rm -rf '%s/run/'*" % self.rootPath) except Exception as detail: # restore wgetrc move(wgetrcBak, wgetrc) # move dns info if exists(resolveCnfBak): move(resolveCnfBak, resolveCnf) else: silent_remove(resolveCnf) # umount /proc /dev /dev/pts /sys self.unmount([pts, dev, proc, sys]) # remove temp script silent_remove(terminal) # remove policy script silent_remove(policy) # replace ischroot if exists("%s.tmp" % ischroot): self.ec.run("rm '%s'" % ischroot) self.ec.run("mv '%s.tmp' '%s'" % (ischroot, ischroot)) # cleanup /run self.ec.run("rm -rf '%s/run/'*" % self.rootPath) errText = 'Error launching terminal: ' print((errText, detail))
def build_efi_image(self, distro_path): hostEfiArchitecture = getHostEfiArchitecture() if hostEfiArchitecture == "": return None # TODO - also 32-bit installs (haven't tested this) modules = "part_gpt part_msdos ntfs ntfscomp hfsplus fat ext2 chain boot configfile linux " \ "multiboot iso9660 gfxmenu gfxterm loadenv efi_gop efi_uga loadbios fixvideo png " \ "loopback search minicmd cat cpuid appleldr elf usb videotest " \ "halt help ls reboot echo test normal sleep memdisk tar font video_fb video " \ "gettext true video_bochs video_cirrus multiboot2 acpi gfxterm_background gfxterm_menu" rootPath = join(distro_path, "root") bootPath = join(distro_path, "boot") efiPath = join(distro_path, "EFI/BOOT") arch = getGuestEfiArchitecture(rootPath) grubEfiName = "bootx64" if arch != "x86_64": arch = "i386" grubEfiName = "bootia32" try: # Clean up old stuff and prepare for a new EFI image if not exists(efiPath): makedirs(efiPath) silent_remove(join(bootPath, "efi")) silent_remove(join(bootPath, "boot/memdisk")) silent_remove(join(bootPath, "boot/grub/x86_64-efi")) silent_remove(join(bootPath, "boot/grub/i386-efi")) silent_remove(join(bootPath, "boot/grub/efi.img")) silent_remove(join(bootPath, "boot/grub/loopback.cfg")) # Create embedded.cfg cont = """search --file --set=root /MD5SUMS if [ -e ($root)/boot/grub/grub.cfg ]; then set prefix=($root)/boot/grub configfile $prefix/grub.cfg else echo "Could not find /boot/grub/grub.cfg!" fi """ with open('embedded.cfg', 'w') as f: f.write(cont) # Create the .efi image with the embedded.cfg file # Prefix is needed but can be left empty: it is set in embedded.cfg self.ec.run("grub-mkimage " "--prefix '' " "--config 'embedded.cfg' " "-O {}-efi " "-o '{}/{}.efi' " "{}".format(arch, efiPath, grubEfiName, modules)) print((">> Finished building EFI files")) return None except Exception as detail: return detail
def run(self): try: if not exists(self.mountDir): print(("Create mount directory: %s" % self.mountDir)) makedirs(self.mountDir) rootDir = join(self.unpackDir, "root") if not exists(rootDir): print(("Create root directory: %s" % rootDir)) makedirs(rootDir) isolinuxDir = join(self.unpackDir, "boot/isolinux") if not exists(isolinuxDir): print(("Create isolinux directory: %s" % isolinuxDir)) makedirs(isolinuxDir) liveDir = join(self.unpackDir, "boot/live") if not exists(liveDir): print(("Create liveDir directory: %s" % liveDir)) makedirs(liveDir) # Mount the ISO system("mount -o loop '%s' '%s'" % (self.unpackIso, self.mountDir)) # Check isolinux directory mountIsolinux = join(self.mountDir, "isolinux") if not exists(mountIsolinux): self.ec.run("umount --force '%s'" % self.mountDir) self.returnMessage = "ERROR: Cannot find isolinux directory in ISO" fixCfgCmd = None dirs = [] mountSquashfs = None if self.returnMessage is None: subdirs = self.getDirectSubDirectories(self.mountDir) for subdir in subdirs: if self.hasSquashFs(join(self.mountDir, subdir)): mountSquashfs = join(self.mountDir, subdir) if subdir != "live": fixCfgCmd = "sed -i 's/\/%s/\/live/g' '%s/isolinux.cfg'" % (subdir, isolinuxDir) elif subdir != "isolinux": dirs.append(join(self.mountDir, subdir)) if mountSquashfs is None: self.ec.run("umount --force '%s'" % self.mountDir) self.returnMessage = "ERROR: Cannot find squashfs directory in ISO" if self.returnMessage is None: # Copy files from ISO to unpack directory for d in dirs: self.ec.run("rsync -at --del '%s' '%s'" % (d, join(self.unpackDir, "boot/"))) self.ec.run("rsync -at --del '%s/' '%s'" % (mountIsolinux, isolinuxDir)) self.ec.run("rsync -at --del '%s/' '%s'" % (mountSquashfs, liveDir)) self.ec.run("umount --force '%s'" % self.mountDir) if fixCfgCmd is not None: self.ec.run(fixCfgCmd) # copy squashfs root squashfs = join(liveDir, "filesystem.squashfs") if exists(squashfs): self.ec.run("mount -t squashfs -o loop '%s' '%s'" % (squashfs, self.mountDir)) self.ec.run("rsync -at --del '%s/' '%s/'" % (self.mountDir, rootDir)) self.ec.run("umount --force '%s'" % self.mountDir) # Cleanup silent_remove(self.mountDir, False) # set proper permissions self.ec.run("chmod 6755 '%s'" % join(rootDir, "usr/bin/sudo")) self.ec.run("chmod 0440 '%s'" % join(rootDir, "etc/sudoers")) self.returnMessage = "DONE - ISO unpacked to: %s" % self.unpackDir self.queue.put(self.returnMessage) except Exception as detail: self.ec.run("umount --force '%s'" % self.mountDir) silent_remove(self.mountDir, False) self.returnMessage = "ERROR: IsoUnpack: %(detail)s" % {"detail": detail} self.queue.put(self.returnMessage)
def run(self): try: if not exists(self.rootPath): self.returnMessage = "ERROR: Cannot find root directory: %s" % self.rootPath if not exists(self.bootPath): self.returnMessage = "ERROR: Cannot find boot directory: %s" % self.bootPath if self.returnMessage is None: print("======================================================") print("INFO: Cleanup and prepare ISO build...") print("======================================================") # Clean-up script = "cleanup.sh" scriptSource = join(self.scriptDir, "files/{}".format(script)) scriptTarget = join(self.rootPath, script) if exists(scriptSource): self.copy_file(scriptSource, scriptTarget) self.ec.run("chmod a+x '%s'" % scriptTarget) self.ed.openTerminal("/bin/bash '%s'" % script) silent_remove(scriptTarget) rootHome = join(self.rootPath, "root") nanoHist = join(rootHome, ".nano_history") silent_remove(nanoHist) bashHist = join(rootHome, ".bash_history") silent_remove(bashHist) # Config naming regExp = "solyd.*(\d{6}|-bit)" d = datetime.now() dateString = d.strftime("%Y%m") nameString = "{} {}".format(self.isoName, dateString) # write iso name to boot/isolinux/isolinux.cfg cfgFile = join(self.bootPath, "isolinux/isolinux.cfg") if exists(cfgFile): content = "" with open(cfgFile, 'r') as f: content = f.read() if content != "": content = re.sub(regExp, nameString, content, flags=re.IGNORECASE) # Make sure that the paths are correct (correcting very old stuff) content = re.sub('.lz', '.img', content) content = re.sub('/solydxk/', '/live/', content) with open(cfgFile, 'w') as f: f.write(content) # Write info for grub (EFI) grubFile = join(self.bootPath, "boot/grub/grub.cfg") if exists(grubFile): content = "" with open(grubFile, 'r') as f: content = f.read() if content != "": content = re.sub(regExp, nameString, content, flags=re.IGNORECASE) with open(grubFile, 'w') as f: f.write(content) # Vmlinuz vmlinuzSymLink = join(self.distroPath, "root/vmlinuz") if lexists(vmlinuzSymLink): vmlinuzFile = self.ec.run("ls -al '%s' | cut -d'>' -f2" % vmlinuzSymLink)[0].strip() else: self.returnMessage = "ERROR: %s not found" % vmlinuzSymLink if self.returnMessage is None: vmlinuzPath = join(self.distroPath, "root/%s" % vmlinuzFile) if exists(vmlinuzPath): print("Copy vmlinuz") self.copy_file(vmlinuzPath, join(self.livePath, "vmlinuz")) else: self.returnMessage = "ERROR: %s not found" % vmlinuzPath if self.returnMessage is None: # Initrd initrdSymLink = join(self.distroPath, "root/initrd.img") if lexists(initrdSymLink): initrdFile = self.ec.run("ls -al '%s' | cut -d'>' -f2" % initrdSymLink)[0].strip() else: self.returnMessage = "ERROR: %s not found" % initrdSymLink if self.returnMessage is None: initrdPath = join(self.distroPath, "root/%s" % initrdFile) if exists(initrdPath): print("Copy initrd") self.copy_file(initrdPath, join(self.livePath, "initrd.img")) else: self.returnMessage = "ERROR: %s not found" % initrdPath if self.returnMessage is None: print("======================================================") print("INFO: Start building ISO...") print("======================================================") # build squash root print("Creating SquashFS root...") print("Updating File lists...") dpkgQuery = ' dpkg -l | awk \'/^ii/ {print $2, $3}\' | sed -e \'s/ /\t/g\' ' self.ec.run('chroot \"' + self.rootPath + '\"' + dpkgQuery + ' > \"' + join(self.livePath, "filesystem.packages") + '\"' ) # check for existing squashfs root print("Removing existing SquashFS root...") silent_remove(join(self.livePath, "filesystem.squashfs")) print("Building SquashFS root...") # check for custom mksquashfs (for multi-threading, new features, etc.) mksquashfs = self.ec.run(cmd="echo $MKSQUASHFS", returnAsList=False).strip() rootPath = join(self.distroPath, "root/") squashfsPath = join(self.livePath, "filesystem.squashfs") if mksquashfs == '' or mksquashfs == 'mksquashfs': try: cpus = int(int(self.ec.run("grep ^cpu\\\s*cores /proc/cpuinfo | grep -o [0-9]* | uniq", False, False)) / 2) if cpus < 1: cpus = 1 except: cpus = 1 # Get excluded dirs/files excludes_lst = join(self.scriptDir, "files/excludes") squash_excl_str = '-wildcards -ef "{0}"'.format(excludes_lst) if exists(excludes_lst) else '' cmd = "mksquashfs \"{0}\" \"{1}\" -comp xz -processors {2} {3}".format(rootPath, squashfsPath, cpus, squash_excl_str) else: cmd = "{0} \"{1}\" \"{2}\"".format(mksquashfs, rootPath, squashfsPath) self.ec.run(cmd) # Update isolinux files syslinuxPath = join(self.rootPath, "usr/lib/syslinux") modulesPath = join(syslinuxPath, "modules/bios") isolinuxPath = join(self.bootPath, "isolinux") self.ec.run("chmod -R +w '%s'" % isolinuxPath) cat = join(isolinuxPath, "boot.cat") silent_remove(cat) self.copy_file(join(modulesPath, "chain.c32"), isolinuxPath) self.copy_file(join(modulesPath, "hdt.c32"), isolinuxPath) self.copy_file(join(modulesPath, "libmenu.c32"), isolinuxPath) self.copy_file(join(modulesPath, "libgpl.c32"), isolinuxPath) self.copy_file(join(modulesPath, "reboot.c32"), isolinuxPath) self.copy_file(join(modulesPath, "vesamenu.c32"), isolinuxPath) self.copy_file(join(modulesPath, "poweroff.c32"), isolinuxPath) self.copy_file(join(modulesPath, "ldlinux.c32"), isolinuxPath) self.copy_file(join(modulesPath, "libcom32.c32"), isolinuxPath) self.copy_file(join(modulesPath, "libutil.c32"), isolinuxPath) self.copy_file(join(self.rootPath, "boot/memtest86+.bin"), join(isolinuxPath, "memtest86")) self.copy_file("/usr/lib/ISOLINUX/isolinux.bin", isolinuxPath) # Build the EFI image efi_error = self.build_efi_image(self.distroPath) if efi_error is not None: self.returnMessage = "ERROR: BuildIso: %(efi_error)s" % {"efi_error": efi_error} # Create efiboot.img efiPath = join(self.distroPath, "EFI") efibootPath = join(isolinuxPath, "efiboot.img") print(("Create %s" % efibootPath)) cmd = "rm '%s' 2>/dev/null;" \ "mkdosfs -F12 -n \"SOLYDXK_EFI\" -C '%s' 2048;" \ "mcopy -s -i '%s' '%s' ::" % (efibootPath, efibootPath, efibootPath, efiPath) self.ec.run(cmd) # Check if the .solydxk file for Grub exists grubChkFile = join(self.bootPath, ".solydxk") if exists(grubChkFile): #system("touch '%s'" % grubChkFile) silent_remove(grubChkFile) # remove existing iso silent_remove(self.isoFileName) # Create an md5sum file for the isolinux/grub integrity check md5sum_fle = 'MD5SUMS' skip_fls = [md5sum_fle, 'isolinux.bin'] md5sum_lst = [] files = [file for file in glob.glob(self.bootPath + '/**', recursive=True)] + \ [file for file in glob.glob(self.bootPath +'/.**', recursive=True)] for file in files: if not isdir(file) and not basename(file) in skip_fls: md5 = self.ec.run("md5sum %s" % file, False, False) if md5: md5sum_lst.append(md5.replace(self.bootPath, '.')) if md5sum_lst: md5_cont = '\n'.join(md5sum_lst) + '\n' with open(join(self.bootPath, md5sum_fle), 'w') as f: f.write(md5_cont) # build iso according to architecture print("Building ISO...") cmd = "xorriso -as mkisofs " \ "-r " \ "-volid '%s' " \ "-o '%s' " \ "-isohybrid-mbr /usr/lib/ISOLINUX/isohdpfx.bin " \ "-partition_offset 16 " \ "-J " \ "-l " \ "-joliet-long " \ "-c isolinux/boot.cat " \ "-b isolinux/isolinux.bin " \ "-no-emul-boot " \ "-boot-load-size 4 " \ "-boot-info-table " \ "-eltorito-alt-boot " \ "-e isolinux/efiboot.img " \ "-no-emul-boot " \ "-isohybrid-gpt-basdat " \ "'%s'" % (self.get_volid(self.isoName), self.isoFileName, self.bootPath) self.ec.run(cmd) print("Insert md5 in ISO") self.ec.run("implantisomd5 '%s'" % self.isoFileName) print("Create sha256 file...") oldmd5 = "%s.md5" % self.isoFileName silent_remove(oldmd5) self.ec.run("echo \"$(sha256sum \"%s\" | cut -d' ' -f 1) %s\" > \"%s.sha256\"" % (self.isoFileName, self.isoBaseName, self.isoFileName)) print("Create Torrent file...") torrentFile = "%s.torrent" % self.isoFileName silent_remove(torrentFile) self.ec.run("mktorrent -a \"%s\" -c \"%s\" -w \"%s\" -o \"%s\" \"%s\"" % (self.trackers, self.isoName, self.webseeds, torrentFile, self.isoFileName)) print("======================================================") if self.returnMessage is None: self.returnMessage = "DONE - ISO Located at: %s" % self.isoFileName print((self.returnMessage)) print("======================================================") self.queue.put(self.returnMessage) except Exception as detail: self.returnMessage = "ERROR: BuildIso: %(detail)s" % {"detail": detail} self.queue.put(self.returnMessage)
def openTerminal(self, command=""): # Set some paths resolveCnfHost = "/etc/resolv.conf" resolveCnf = join(self.rootPath, "etc/resolv.conf") resolveCnfBak = "%s.bak" % resolveCnf wgetrc = join(self.rootPath, "etc/wgetrc") wgetrcBak = "%s.bak" % wgetrc terminal = "/tmp/constructor-terminal.sh" lockDir = join(self.rootPath, "run/lock/") proc = join(self.rootPath, "proc/") dev = join(self.rootPath, "dev/") pts = join(self.rootPath, "dev/pts/") sys = join(self.rootPath, "sys/") policy = join(self.rootPath, "usr/sbin/policy-rc.d") ischroot = join(self.rootPath, "usr/bin/ischroot") ischrootTmp = join(self.rootPath, "usr/bin/ischroot.tmp") try: # temporary create /run/lock if not exists(lockDir): makedirs(lockDir) # setup environment # copy dns info if exists(resolveCnf): move(resolveCnf, resolveCnfBak) if exists(resolveCnfHost): copy(resolveCnfHost, resolveCnf) # umount /proc /dev /dev/pts /sys self.unmount([pts, dev, proc, sys]) # mount /proc /dev /dev/pts /sys /run /sys self.ec.run("mount --bind /proc '%s'" % proc) self.ec.run("mount --bind /dev '%s'" % dev) self.ec.run("mount --bind /dev/pts '%s'" % pts) self.ec.run("mount --bind /sys '%s'" % sys) # copy wgetrc move(wgetrc, wgetrcBak) copy("/etc/wgetrc", wgetrc) # Let dpkg only start daemons when desired scr = "#!/bin/sh\nexit 101\n" with open(policy, 'w') as f: f.write(scr) self.ec.run("chmod a+x '%s'" % policy) # Temporary fix ischroot if not exists(ischrootTmp): self.ec.run("mv '%s' '%s'" % (ischroot, ischrootTmp)) if not exists(ischroot): self.ec.run("ln -s /bin/true '%s'" % ischroot) # HACK: create temporary script for chrooting silent_remove(terminal) scr = "#!/bin/sh\nchroot '%s' %s\n" % (self.rootPath, command) with open(terminal, 'w') as f: f.write(scr) self.ec.run("chmod a+x '%s'" % terminal) if exists("/usr/bin/xterm"): self.ec.run( 'export HOME=/root ; xterm -bg black -fg white -rightbar -title \"%s\" -e %s' % (self.edition, terminal)) elif self.ec.run('which x-terminal-emulator'): # use x-terminal-emulator if xterm isn't available self.ec.run('export HOME=/root ; x-terminal-emulator -e %s' % terminal) else: print('Error: no valid terminal found') # restore wgetrc move(wgetrcBak, wgetrc) # move dns info if exists(resolveCnfBak): move(resolveCnfBak, resolveCnf) else: silent_remove(resolveCnf) # umount /proc /dev /dev/pts /sys self.unmount([pts, dev, proc, sys]) # remove temp script silent_remove(terminal) # remove policy script silent_remove(policy) # replace ischroot if exists("%s.tmp" % ischroot): self.ec.run("rm '%s'" % ischroot) self.ec.run("mv '%s.tmp' '%s'" % (ischroot, ischroot)) # cleanup /run self.ec.run("rm -rf '%s/run/'*" % self.rootPath) except Exception as detail: # restore wgetrc move(wgetrcBak, wgetrc) # move dns info if exists(resolveCnfBak): move(resolveCnfBak, resolveCnf) else: silent_remove(resolveCnf) # umount /proc /dev /dev/pts /sys self.unmount([pts, dev, proc, sys]) # remove temp script silent_remove(terminal) # remove policy script silent_remove(policy) # replace ischroot if exists("%s.tmp" % ischroot): self.ec.run("rm '%s'" % ischroot) self.ec.run("mv '%s.tmp' '%s'" % (ischroot, ischroot)) # cleanup /run self.ec.run("rm -rf '%s/run/'*" % self.rootPath) errText = 'Error launching terminal: ' print((errText, detail))
def build_efi_image(self, distro_path): hostEfiArchitecture = getHostEfiArchitecture() if hostEfiArchitecture == "": return None # TODO - also 32-bit installs (haven't tested this) modules = "part_gpt part_msdos ntfs ntfscomp hfsplus fat ext2 chain boot configfile linux " \ "multiboot iso9660 gfxmenu gfxterm loadenv efi_gop efi_uga loadbios fixvideo png " \ "loopback search minicmd cat cpuid appleldr elf usb videotest " \ "halt help ls reboot echo test normal sleep memdisk tar font video_fb video " \ "gettext true video_bochs video_cirrus multiboot2 acpi gfxterm_background gfxterm_menu" rootPath = join(distro_path, "root") bootPath = join(distro_path, "boot") efiPath = join(distro_path, "EFI/BOOT") arch = getGuestEfiArchitecture(rootPath) grubEfiName = "bootx64" if arch != "x86_64": arch = "i386" grubEfiName = "bootia32" try: # Clean up old stuff and prepare for a new EFI image if not exists(efiPath): makedirs(efiPath) silent_remove(join(bootPath, "efi")) silent_remove(join(bootPath, "boot/memdisk")) silent_remove(join(bootPath, "boot/grub/x86_64-efi")) silent_remove(join(bootPath, "boot/grub/i386-efi")) silent_remove(join(bootPath, "boot/grub/efi.img")) silent_remove(join(bootPath, "boot/grub/loopback.cfg")) # Create embedded.cfg cont = """search --file --set=root /.trail if [ -e ($root)/boot/grub/grub.cfg ]; then set prefix=($root)/boot/grub configfile $prefix/grub.cfg else echo "Could not find /boot/grub/grub.cfg!" fi """ with open('embedded.cfg', 'w') as f: f.write(cont) # Create the .efi image with the embedded.cfg file self.ec.run("grub-mkimage " "--config=embedded.cfg " "-O {}-efi " "-o '{}/{}.efi' " "{}".format(arch, efiPath, grubEfiName, modules)) print((">> Finished building EFI files")) return None except Exception as detail: return detail
def run(self): try: if not exists(self.mountDir): print(("Create mount directory: %s" % self.mountDir)) makedirs(self.mountDir) rootDir = join(self.unpackDir, "root") if not exists(rootDir): print(("Create root directory: %s" % rootDir)) makedirs(rootDir) isolinuxDir = join(self.unpackDir, "boot/isolinux") if not exists(isolinuxDir): print(("Create isolinux directory: %s" % isolinuxDir)) makedirs(isolinuxDir) liveDir = join(self.unpackDir, "boot/live") if not exists(liveDir): print(("Create liveDir directory: %s" % liveDir)) makedirs(liveDir) # Mount the ISO system("mount -o loop '%s' '%s'" % (self.unpackIso, self.mountDir)) # Check isolinux directory mountIsolinux = join(self.mountDir, "isolinux") if not exists(mountIsolinux): self.ec.run("umount --force '%s'" % self.mountDir) self.returnMessage = "ERROR: Cannot find isolinux directory in ISO" fixCfgCmd = None dirs = [] mountSquashfs = None if self.returnMessage is None: subdirs = self.getDirectSubDirectories(self.mountDir) for subdir in subdirs: if self.hasSquashFs(join(self.mountDir, subdir)): mountSquashfs = join(self.mountDir, subdir) if subdir != "live": fixCfgCmd = "sed -i 's/\/%s/\/live/g' '%s/isolinux.cfg'" % ( subdir, isolinuxDir) elif subdir != "isolinux": dirs.append(join(self.mountDir, subdir)) if mountSquashfs is None: self.ec.run("umount --force '%s'" % self.mountDir) self.returnMessage = "ERROR: Cannot find squashfs directory in ISO" if self.returnMessage is None: # Copy files from ISO to unpack directory for d in dirs: self.ec.run("rsync -at --del '%s' '%s'" % (d, join(self.unpackDir, "boot/"))) self.ec.run("rsync -at --del '%s/' '%s'" % (mountIsolinux, isolinuxDir)) self.ec.run("rsync -at --del '%s/' '%s'" % (mountSquashfs, liveDir)) self.ec.run("umount --force '%s'" % self.mountDir) if fixCfgCmd is not None: self.ec.run(fixCfgCmd) # copy squashfs root squashfs = join(liveDir, "filesystem.squashfs") if exists(squashfs): self.ec.run("mount -t squashfs -o loop '%s' '%s'" % (squashfs, self.mountDir)) self.ec.run("rsync -at --del '%s/' '%s/'" % (self.mountDir, rootDir)) self.ec.run("umount --force '%s'" % self.mountDir) # Cleanup silent_remove(self.mountDir, False) # set proper permissions self.ec.run("chmod 6755 '%s'" % join(rootDir, "usr/bin/sudo")) self.ec.run("chmod 0440 '%s'" % join(rootDir, "etc/sudoers")) self.returnMessage = "DONE - ISO unpacked to: %s" % self.unpackDir self.queue.put(self.returnMessage) except Exception as detail: self.ec.run("umount --force '%s'" % self.mountDir) silent_remove(self.mountDir, False) self.returnMessage = "ERROR: IsoUnpack: %(detail)s" % { "detail": detail } self.queue.put(self.returnMessage)
def run(self): try: if not exists(self.rootPath): self.returnMessage = "ERROR: Cannot find root directory: %s" % self.rootPath if not exists(self.bootPath): self.returnMessage = "ERROR: Cannot find boot directory: %s" % self.bootPath if self.returnMessage is None: print("======================================================") print("INFO: Cleanup and prepare ISO build...") print("======================================================") # Clean-up script = "cleanup.sh" scriptSource = join(self.scriptDir, "files/{}".format(script)) scriptTarget = join(self.rootPath, script) if exists(scriptSource): self.copy_file(scriptSource, scriptTarget) self.ec.run("chmod a+x '%s'" % scriptTarget) self.ed.openTerminal("/bin/bash '%s'" % script) silent_remove(scriptTarget) rootHome = join(self.rootPath, "root") nanoHist = join(rootHome, ".nano_history") silent_remove(nanoHist) bashHist = join(rootHome, ".bash_history") silent_remove(bashHist) # Config naming regExp = "trail.*(\d{6}|-bit)" d = datetime.now() dateString = d.strftime("%Y%m") nameString = "{} {}".format(self.isoName, dateString) # write iso name to boot/isolinux/isolinux.cfg cfgFile = join(self.bootPath, "isolinux/isolinux.cfg") if exists(cfgFile): content = "" with open(cfgFile, 'r') as f: content = f.read() if content != "": content = re.sub(regExp, nameString, content, flags=re.IGNORECASE) # Make sure that the paths are correct (correcting very old stuff) content = re.sub('.lz', '.img', content) content = re.sub('/trail/', '/live/', content) with open(cfgFile, 'w') as f: f.write(content) # Write info for grub (EFI) grubFile = join(self.bootPath, "boot/grub/grub.cfg") if exists(grubFile): content = "" with open(grubFile, 'r') as f: content = f.read() if content != "": content = re.sub(regExp, nameString, content, flags=re.IGNORECASE) with open(grubFile, 'w') as f: f.write(content) # Vmlinuz vmlinuzSymLink = join(self.distroPath, "root/vmlinuz") if lexists(vmlinuzSymLink): vmlinuzFile = self.ec.run("ls -al '%s' | cut -d'>' -f2" % vmlinuzSymLink)[0].strip() else: self.returnMessage = "ERROR: %s not found" % vmlinuzSymLink if self.returnMessage is None: vmlinuzPath = join(self.distroPath, "root/%s" % vmlinuzFile) if exists(vmlinuzPath): print("Copy vmlinuz") self.copy_file(vmlinuzPath, join(self.livePath, "vmlinuz")) else: self.returnMessage = "ERROR: %s not found" % vmlinuzPath if self.returnMessage is None: # Initrd initrdSymLink = join(self.distroPath, "root/initrd.img") if lexists(initrdSymLink): initrdFile = self.ec.run("ls -al '%s' | cut -d'>' -f2" % initrdSymLink)[0].strip() else: self.returnMessage = "ERROR: %s not found" % initrdSymLink if self.returnMessage is None: initrdPath = join(self.distroPath, "root/%s" % initrdFile) if exists(initrdPath): print("Copy initrd") self.copy_file(initrdPath, join(self.livePath, "initrd.img")) else: self.returnMessage = "ERROR: %s not found" % initrdPath if self.returnMessage is None: print("======================================================") print("INFO: Start building ISO...") print("======================================================") # build squash root print("Creating SquashFS root...") print("Updating File lists...") dpkgQuery = ' dpkg -l | awk \'/^ii/ {print $2, $3}\' | sed -e \'s/ /\t/g\' ' self.ec.run('chroot \"' + self.rootPath + '\"' + dpkgQuery + ' > \"' + join(self.livePath, "filesystem.packages") + '\"') # check for existing squashfs root print("Removing existing SquashFS root...") silent_remove(join(self.livePath, "filesystem.squashfs")) print("Building SquashFS root...") # check for custom mksquashfs (for multi-threading, new features, etc.) mksquashfs = self.ec.run(cmd="echo $MKSQUASHFS", returnAsList=False).strip() rootPath = join(self.distroPath, "root/") squashfsPath = join(self.livePath, "filesystem.squashfs") if mksquashfs == '' or mksquashfs == 'mksquashfs': try: nrprocessors = int( int(self.ec.run("nproc", False, False)) / 2) if nrprocessors < 1: nrprocessors = 1 except: nrprocessors = 1 cmd = "mksquashfs \"{}\" \"{}\" -comp xz -processors {}".format( rootPath, squashfsPath, nrprocessors) else: cmd = "{} \"{}\" \"{}\"".format(mksquashfs, rootPath, squashfsPath) #print(cmd) self.ec.run(cmd) # Update isolinux files syslinuxPath = join(self.rootPath, "usr/lib/syslinux") modulesPath = join(syslinuxPath, "modules/bios") isolinuxPath = join(self.bootPath, "isolinux") self.ec.run("chmod -R +w '%s'" % isolinuxPath) cat = join(isolinuxPath, "boot.cat") silent_remove(cat) self.copy_file(join(modulesPath, "chain.c32"), isolinuxPath) self.copy_file(join(modulesPath, "hdt.c32"), isolinuxPath) self.copy_file(join(modulesPath, "libmenu.c32"), isolinuxPath) self.copy_file(join(modulesPath, "libgpl.c32"), isolinuxPath) self.copy_file(join(modulesPath, "reboot.c32"), isolinuxPath) self.copy_file(join(modulesPath, "vesamenu.c32"), isolinuxPath) self.copy_file(join(modulesPath, "poweroff.c32"), isolinuxPath) self.copy_file(join(modulesPath, "ldlinux.c32"), isolinuxPath) self.copy_file(join(modulesPath, "libcom32.c32"), isolinuxPath) self.copy_file(join(modulesPath, "libutil.c32"), isolinuxPath) self.copy_file(join(self.rootPath, "boot/memtest86+.bin"), join(isolinuxPath, "memtest86")) self.copy_file("/usr/lib/ISOLINUX/isolinux.bin", isolinuxPath) # Build the EFI image efi_error = self.build_efi_image(self.distroPath) if efi_error is not None: self.returnMessage = "ERROR: BuildIso: %(efi_error)s" % { "efi_error": efi_error } # Create efiboot.img efiPath = join(self.distroPath, "EFI") efibootPath = join(isolinuxPath, "efiboot.img") print(("Create %s" % efibootPath)) cmd = "rm '%s' 2>/dev/null;" \ "mkdosfs -F12 -n \"DEBIAN_EFI\" -C '%s' 2048;" \ "mcopy -s -i '%s' '%s' ::" % (efibootPath, efibootPath, efibootPath, efiPath) self.ec.run(cmd) # Check if the .trail file for Grub exists grubChkFile = join(self.bootPath, ".trail") if not exists(grubChkFile): system("touch '%s'" % grubChkFile) # remove existing iso silent_remove(self.isoFileName) # build iso according to architecture print("Building ISO...") cmd = "xorriso -as mkisofs " \ "-r " \ "-volid '%s' " \ "-o '%s' " \ "-isohybrid-mbr /usr/lib/ISOLINUX/isohdpfx.bin " \ "-partition_offset 16 " \ "-J " \ "-l " \ "-joliet-long " \ "-c isolinux/boot.cat " \ "-b isolinux/isolinux.bin " \ "-no-emul-boot " \ "-boot-load-size 4 " \ "-boot-info-table " \ "-eltorito-alt-boot " \ "-e isolinux/efiboot.img " \ "-no-emul-boot " \ "-isohybrid-gpt-basdat " \ "'%s'" % (self.get_volid(self.isoName), self.isoFileName, self.bootPath) self.ec.run(cmd) print("Insert md5 in ISO") self.ec.run("implantisomd5 '%s'" % self.isoFileName) print("Create sha256 file...") oldmd5 = "%s.md5" % self.isoFileName silent_remove(oldmd5) self.ec.run( "echo \"$(sha256sum \"%s\" | cut -d' ' -f 1) %s\" > \"%s.sha256\"" % (self.isoFileName, self.isoBaseName, self.isoFileName)) print("Create Torrent file...") torrentFile = "%s.torrent" % self.isoFileName silent_remove(torrentFile) self.ec.run( "mktorrent -a \"%s\" -c \"%s\" -w \"%s\" -o \"%s\" \"%s\"" % (self.trackers, self.isoName, self.webseeds, torrentFile, self.isoFileName)) print("======================================================") if self.returnMessage is None: self.returnMessage = "DONE - ISO Located at: %s" % self.isoFileName print((self.returnMessage)) print("======================================================") self.queue.put(self.returnMessage) except Exception as detail: self.returnMessage = "ERROR: BuildIso: %(detail)s" % { "detail": detail } self.queue.put(self.returnMessage)