diff --git a/TODO b/TODO index 031f1d9..055c87b 100644 --- a/TODO +++ b/TODO @@ -24,6 +24,20 @@ need to write docs need to double-check aif.xsd spec for the packaging command- can i specify a single element? finish up software/packages section +can i install packages the way pacstrap does, without a chroot? i still need to do it, unfortunately, for setting up efibootmgr etc. but..: +pacman -r /mnt/aif -Sy base --cachedir=/mnt/aif/var/cache/pacman/pkg --noconfirm +/dev/sda2 on /mnt/aif type ext4 (rw,relatime,data=ordered) +/dev/sda1 on /mnt/aif/boot type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro) +proc on /mnt/aif/proc type proc (rw,nosuid,nodev,noexec,relatime) +sys on /mnt/aif/sys type sysfs (ro,nosuid,nodev,noexec,relatime) +efivarfs on /mnt/aif/sys/firmware/efi/efivars type efivarfs (rw,nosuid,nodev,noexec,relatime) +udev on /mnt/aif/dev type devtmpfs (rw,nosuid,relatime,size=2012384k,nr_inodes=503096,mode=755) +devpts on /mnt/aif/dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000) +shm on /mnt/aif/dev/shm type tmpfs (rw,nosuid,nodev,relatime) +run on /mnt/aif/run type tmpfs (rw,nosuid,nodev,relatime,mode=755) +tmp on /mnt/aif/tmp type tmpfs (rw,nosuid,nodev) + + docs: http://lxml.de/parsing.html https://www.w3.org/2001/XMLSchema.xsd diff --git a/aif.xml b/aif.xml index ddc0ae7..e36424c 100644 --- a/aif.xml +++ b/aif.xml @@ -50,6 +50,8 @@ + + diff --git a/aifclient.py b/aifclient.py index ee2e504..21b18ee 100755 --- a/aifclient.py +++ b/aifclient.py @@ -304,8 +304,13 @@ class aif(object): for x in xmlobj.findall('pacman/mirrorlist'): for i in x: aifdict['software']['mirrors'].append(i.text) + # Then the command + if xmlobj.find('pacman/command') is None: + aifdict['software']['command'] = False + else: + aifdict['software']['command'] = xmlobj.find('pacman/command').text # And then the repo list. - for x in xmlobj.find('pacman/repos'): + for x in xmlobj.findall('pacman/repos/repo'): repo = x.attrib['name'] aifdict['software']['repos'][repo] = {} aifdict['software']['repos'][repo]['enabled'] = x.attrib['enabled'].lower() in ('true', '1') @@ -326,15 +331,6 @@ class aif(object): for x in xmlobj.find('bootloader').attrib: aifdict['system']['bootloader'][x] = xmlobj.find('bootloader').attrib[x] # The script setup... - # We do this later on. -# for x in xmlobj.find('scripts'): -# if x.attrib['bootstrap'].lower() in ('true', '1'): -# scripttype = 'pre' -# else: -# scripttype = 'post' -# if not aifdict['scripts'][scripttype]: -# aifdict['scripts'][scripttype] = {} -# aifdict['scripts'][scripttype][int(x.attrib['order'])] = {} if xmlobj.find('scripts') is not None: aifdict['scripts']['pre'] = [] aifdict['scripts']['post'] = [] @@ -448,7 +444,7 @@ class archInstall(object): usermntidx.sort() # We want to make sure we do this in order. for k in usermntidx: if self.mount[k]['mountpt'] == 'swap': - subprocess.call(['swapon', '-e', self.mount[k]['device']], stdout = log, stderr = subprocess.STDOUT) + subprocess.call(['swapon', self.mount[k]['device']], stdout = log, stderr = subprocess.STDOUT) else: os.makedirs(self.mount[k]['mountpt'], exist_ok = True) os.chown(self.mount[k]['mountpt'], 0, 0) @@ -675,11 +671,12 @@ class archInstall(object): if resolvers: netprofile += 'DNS=(\'{0}\')\n'.format('\' \''.join(resolvers)) filename = '{0}/etc/netctl/{1}'.format(self.system['chrootpath'], ifacedev) + sysdfile = '{0}/etc/systemd/system/netctl@{1}.service'.format(self.system['chrootpath'], ifacedev) # The good news is since it's a clean install, we only have to account for our own data, not pre-existing. with open(filename, 'w') as f: f.write('# Generated by AIF-NG.\n') f.write(netprofile) - with open('{0}/etc/systemd/system/netctl@{1}.service'.format(self.system['chrootpath'], ifacedev)) as f: + with open(sysdfile, 'w') as f: f.write('# Generated by AIF-NG.\n') f.write(('.include /usr/lib/systemd/system/netctl@.service\n\n[Unit]\n' + 'Description=A basic {0} ethernet connection\n' + @@ -747,13 +744,14 @@ class archInstall(object): chrootpath = self.system['chrootpath'] bttarget = self.system['bootloader']['target'] if btldr == 'grub': + bootcmds.append(['pacman', '--needed', '--noconfirm', '-S', 'grub', 'efibootmgr']) bootcmds.append(['grub-install']) if self.system['bootloader']['efi']: - bootcmds[0].extend(['--target=x86_64-efi', '--efi-directory={0}'.format(bttarget), '--bootloader-id="Arch Linux"']) + bootcmds[1].extend(['--target=x86_64-efi', '--efi-directory={0}'.format(bttarget), '--bootloader-id=Arch']) else: - bootcmds[0].extend(['--target=i386-pc', bttarget]) - bootcmds.append(['grub-mkconfig', '-o', '/{0}/grub/grub.cfg'.format(chrootpath, bttarget)]) - if btldr == 'systemd': + bootcmds[1].extend(['--target=i386-pc', bttarget]) + bootcmds.append(['grub-mkconfig', '-o', '{0}/grub/grub.cfg'.format(bttarget)]) + elif btldr == 'systemd': if self.system['bootloader']['target'] != '/boot': shutil.copy2('{0}/boot/vmlinuz-linux'.format(chrootpath), '{0}/{1}/vmlinuz-linux'.format(chrootpath, bttarget)) @@ -787,10 +785,7 @@ class archInstall(object): t = scripttype if t in self.scripts.keys(): for i, s in enumerate(self.scripts[t]): - if t == 'post': - dirpath = '{0}/scripts/{1}'.format(self.system['chrootpath'], t) - else: - dirpath = '/root/scripts/{0}'.format(t) + dirpath = '/root/scripts/{0}'.format(t) os.makedirs(dirpath, exist_ok = True) filepath = '{0}/{1}'.format(dirpath, i) with open(filepath, 'w') as f: @@ -807,15 +802,44 @@ class archInstall(object): return() def packagecmds(self): - pass + pkgcmds = [] + # This should be run in the chroot, unless we find a way to pacstrap + # packages separate from chrooting + if self.software['command']: + pkgr = self.software['command'] + else: + pkgr = 'pacman' + pkgropts = ['--needed', '--noconfirm'] + if pkgr == 'apacman': + pkgropts.extend(['--noedit', '--skipinteg']) + if self.software['mirrors']: + # TODO: file vs. server? + with open('/etc/pacman.d/mirrorlist', 'w') as f: + for m in self.software['mirrors']: + f.write('Server = {0}\n'.format(m)) + if self.software['packages']: + for p in self.software['packages'].keys(): + if self.software['packages'][p]['repo']: + pkgname = '{0}/{1}'.format(self.software['packages'][p]['repo'], + self.software['packages'][p]) + else: + pkgname = p + cmd = [pkgr] + for o in pkgropts: + cmd.append(o) + cmd.extend(['-S', pkgname]) + pkgcmds.append(cmd) + return(pkgcmds) - def chroot(self, chrootcmds = False, bootcmds = False, scriptcmds = False): + def chroot(self, chrootcmds = False, bootcmds = False, scriptcmds = False, pkgcmds = False): if not chrootcmds: chrootcmds = self.setup() if not bootcmds: bootcmds = self.bootloader() if not scriptcmds: - scriptcmds = self.scripts + scripts = self.scripts + if not pkgcmds: + pkgcmds = self.packagecmds() # We don't need this currently, but we might down the road. #chrootscript = '#!/bin/bash\n# https://aif.square-r00t.net/\n\n' #with open('{0}/root/aif.sh'.format(self.system['chrootpath']), 'w') as f: @@ -827,32 +851,37 @@ class archInstall(object): with open(logfile, 'a') as log: for c in chrootcmds: subprocess.call(c, stdout = log, stderr = subprocess.STDOUT) + for p in pkgcmds: + subprocess.call(p, stdout = log, stderr = subprocess.STDOUT) for b in bootcmds: subprocess.call(b, stdout = log, stderr = subprocess.STDOUT) - if scriptcmds['post']: - for i, s in enumerate(scriptcmds['post']): + if scripts['post']: + self.scriptcmds('post') + for i, s in enumerate(scripts['post']): subprocess.call('/root/scripts/post/{0}'.format(i), stdout = log, - stderr = subproces.STDOUT) + stderr = subprocess.STDOUT) #os.system('{0}/root/aif-pre.sh'.format(self.system['chrootpath'])) #os.system('{0}/root/aif-post.sh'.format(self.system['chrootpath'])) os.fchdir(real_root) os.chroot('.') os.close(real_root) - if not os.path.isfile('{0}/sbin/init'.format(chrootdir)): - os.symlink('../lib/systemd/systemd', '{0}/sbin/init'.format(chrootdir)) + if not os.path.isfile('{0}/sbin/init'.format(self.system['chrootpath'])): + os.symlink('../lib/systemd/systemd', '{0}/sbin/init'.format(self.system['chrootpath'])) + return() def unmount(self): with open(logfile, 'a') as log: - subprocess.call(['unmount', '-lR', self.system['chrootpath']], stdout = log, stderr = subprocess.STDOUT) + subprocess.call(['umount', '-lR', self.system['chrootpath']], stdout = log, stderr = subprocess.STDOUT) + return() def runInstall(confdict): install = archInstall(confdict) install.scriptcmds('pre') install.format() install.chroot() - install.scriptcmds('post') install.unmount() + return() def main(): if os.getuid() != 0: