From bad590518a78e11e7fc90d71522670695369eaee Mon Sep 17 00:00:00 2001 From: brent s Date: Fri, 5 May 2017 01:40:28 -0400 Subject: [PATCH] holy cats. docs are finally done and packaging commands/alternate packager reconfigured- though untested. bumping tag out of beta because nothing should(????) break. --- HOWTO | 8 ----- aif.xsd | 10 +++++-- aifclient.py | 41 ++++++++++++-------------- docs/README.adoc | 30 +++++++++++++++---- sampledict | 77 ------------------------------------------------ 5 files changed, 51 insertions(+), 115 deletions(-) delete mode 100644 HOWTO delete mode 100644 sampledict diff --git a/HOWTO b/HOWTO deleted file mode 100644 index bb5f264..0000000 --- a/HOWTO +++ /dev/null @@ -1,8 +0,0 @@ -The following kernel parameters are supported: - -aif aif=True do the same thing. if aif is False, it behaves as if aif is not specified. Enable AIF. -aif_url path to install XML document. can be e.g.: http://domain.tld/aif.xml https://domain.tld/aif.xml ftp://domain.tld/aif.xml file:///tmp/aif.xml (note that local filesystem references are in relation to the system running the client) (note: HTTPS must be signed by a valid root CA) -aif_username the username to use for HTTP/HTTPS Basic auth, HTTP/HTTPS Digest auth, or FTP/FTPS auth (must be specified to use Basic/Digest auth) -aif_password the password to use for HTTP/HTTPS Basic auth, HTTP/HTTPS Digest auth, or FTP/FTPS auth (must be specified to use Basic/Digest auth) -aif_auth either 'basic' or 'digest', for HTTP/HTTPS auth (ignored for other types). default, if others are specified, is basic. -aif_realm the realm name for HTTP/HTTPS Digest auth (ignored for other types). leave unset to try whatever default realm is presented \ No newline at end of file diff --git a/aif.xsd b/aif.xsd index 241e098..d4b03c8 100644 --- a/aif.xsd +++ b/aif.xsd @@ -108,6 +108,12 @@ + + + + + + @@ -266,7 +272,6 @@ - @@ -305,6 +310,7 @@ + @@ -325,7 +331,7 @@ - + diff --git a/aifclient.py b/aifclient.py index 8cd438a..59abb82 100755 --- a/aifclient.py +++ b/aifclient.py @@ -306,10 +306,10 @@ class aif(object): for i in x: aifdict['software']['mirrors'].append(i.text) # Then the command - if xmlobj.find('pacman/command') is None: - aifdict['software']['command'] = False + if 'command' in xmlobj.find('pacman').attrib: + aifdict['software']['command'] = xmlobj.find('pacman').attrib['command'] else: - aifdict['software']['command'] = xmlobj.find('pacman/command').text + aifdict['software']['command'] = False # And then the repo list. for x in xmlobj.findall('pacman/repos/repo'): repo = x.attrib['name'] @@ -348,11 +348,8 @@ class aif(object): scriptcontents = self.webFetch(x.attrib['uri'], auth).decode('utf-8') else: scriptcontents = self.webFetch(x.attrib['uri']).decode('utf-8') - if x.attrib['bootstrap'].lower() in ('true', '1'): - tempscriptdict['pre'][x.attrib['order']] = scriptcontents - else: - tempscriptdict['post'][x.attrib['order']] = scriptcontents - for d in ('pre', 'post'): + tempscriptdict[x.attrib['execution']][x.attrib['order']] = scriptcontents + for d in ('pre', 'post', 'pkg'): keylst = list(tempscriptdict[d].keys()) keylst.sort() for s in keylst: @@ -782,7 +779,6 @@ class archInstall(object): return(bootcmds) def scriptcmds(self, scripttype): - # Pre-run/"booststrap" scripts t = scripttype if t in self.scripts.keys(): for i, s in enumerate(self.scripts[t]): @@ -793,11 +789,11 @@ class archInstall(object): f.write(s) os.chmod(filepath, 0o700) os.chown(filepath, 0, 0) # shouldn't be necessary, but just in case the umask's messed up or something. - if t == 'pre': + if t in ('pre', 'pkg'): # We want to run these right away. with open(logfile, 'a') as log: - for i, s in enumerate(self.scripts['pre']): - subprocess.call('/root/scripts/pre/{0}'.format(i), + for i, s in enumerate(self.scripts[t]): + subprocess.call('/root/scripts/{0}/{1}'.format(t, i), stdout = log, stderr = subprocess.STDOUT) return() @@ -847,12 +843,9 @@ class archInstall(object): # 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'] + pkgr = shlex.split(self.software['command']) else: - pkgr = 'pacman' - pkgropts = ['--needed', '--noconfirm'] - if pkgr == 'apacman': - pkgropts.extend(['--noedit', '--skipinteg']) + pkgr = ['pacman', '--needed', '--noconfirm', '-S'] if self.software['packages']: for p in self.software['packages'].keys(): if self.software['packages'][p]['repo']: @@ -860,11 +853,8 @@ class archInstall(object): self.software['packages'][p]) else: pkgname = p - cmd = [pkgr] - for o in pkgropts: - cmd.append(o) - cmd.extend(['-S', pkgname]) - pkgcmds.append(cmd) + pkgr.append(pkgname) + pkgcmds.append(pkgr) return(pkgcmds) def serviceSetup(self): @@ -903,6 +893,12 @@ class archInstall(object): with open(logfile, 'a') as log: for c in chrootcmds: subprocess.call(c, stdout = log, stderr = subprocess.STDOUT) + if scripts['pkg']: + self.scriptcmds('pkg') + for i, s in enumerate(scripts['pkg']): + subprocess.call('/root/scripts/pkg/{0}'.format(i), + stdout = log, + stderr = subprocess.STDOUT) for p in pkgcmds: subprocess.call(p, stdout = log, stderr = subprocess.STDOUT) for b in bootcmds: @@ -946,6 +942,7 @@ def main(): with open(logfile, 'a') as log: pprint.pprint(instconf, stream = log) runInstall(instconf) + subprocess.call(['reboot']) if __name__ == "__main__": main() diff --git a/docs/README.adoc b/docs/README.adoc index d2ce5f0..4be56e3 100644 --- a/docs/README.adoc +++ b/docs/README.adoc @@ -409,12 +409,22 @@ The `/aif/system/service` element holds information about services that should e |====================== === `` -The `/aif/pacman` element contains the <>, <>, <>, <>, <>, <>, and <> elements. +The `/aif/pacman` element contains the <>, <>, <>, <>, <>, and <> elements. -==== `` -NOTE: This is currently kind of useless. I need to implement a pre-package-installation <> first. I promise it's coming. +[options="header"] +|====================== +^|Attribute ^|Value +^m|command |The command to use to install a package +|====================== -If you configured an alternate package utility, you can specify the command here. Note that it should be configured/called with necessary options to avoid the necessity of user involvement (since that's the entire point of AIF-NG). +[[command]] +If you configured an alternate package utility (using a `execution="pkg"` <> entry), you can specify the command here. Note that it should be configured/called with necessary options to avoid the necessity of user involvement (since that's the entire point of AIF-NG). e.g.: + + + ... + + ... + ==== `` The `/aif/pacman/repos` element contains one (or more) <> element(s). @@ -476,7 +486,15 @@ The `/aif/scripts/script` elements specify scripts to be run at different stages ^m|user |Same behavior as <> but for fetching this script (see also <> on this) ^m|password |Same behavior as <> but for fetching this script (see also <> on this) ^m|realm |Same behavior as <> but for fetching this script (see also <> on this) -^m|bootstrap |A boolean; if `1`/`true` then we will run this script before even formatting <>; otherwise if it's `0`/`false` then we would run it *inside* the chroot environment as the very last thing +^m|execution |(see <>) |====================== -NOTE: The `bootstrap` attribute is subject to change to something more flexible to allow more flexibility in when the scripts are executed. Expect this to happen soon, so be aware. + +[[script_types]] +There are several script types availabe for `execution`. Currently, these are: + +* pre +* pkg +* post + +*pre* scripts are run (in numerical `order`) before the disks are even formatted. *pkg* scripts are run (in numerical `order`) right before the <> are installed (this allows you to configure an <> such as https://aur.archlinux.org/packages/apacman/[apacman^]) - these are run *inside* the chroot of the new install. *pre* scripts are run inside the chroot like *pkg*, but are executed very last thing, just before the reboot. diff --git a/sampledict b/sampledict deleted file mode 100644 index e576197..0000000 --- a/sampledict +++ /dev/null @@ -1,77 +0,0 @@ -{'disk': {'/dev/sda': {'fmt': 'gpt', - 'parts': {'1': {'fstype': 'ef00', - 'num': '1', - 'size': '10%', - 'start': '0%'}, - '2': {'fstype': '8300', - 'num': '2', - 'size': '80%', - 'start': '10%'}, - '3': {'fstype': '8200', - 'num': '3', - 'size': '10%', - 'start': '80%'}}}}, - 'mount': {'1': {'device': '/dev/sda2', - 'fstype': None, - 'mountpt': '/mnt', - 'opts': None}, - '2': {'device': '/dev/sda1', - 'fstype': None, - 'mountpt': '/mnt/boot', - 'opts': None}, - '3': {'device': '/dev/sda3', - 'fstype': None, - 'mountpt': 'swap', - 'opts': None}}, - 'network': {'hostname': 'aiftest.square-r00t.net', - 'ifaces': {'auto': {'ipv4': {'addresses': ['auto'], - 'gw': False, - 'resolvers': False}, - 'resolvers': []}}}, - 'scripts': {'post': {}, 'pre': {}}, - 'software': {'mirrors': ['http://mirrors.advancedhosters.com/archlinux/$repo/os/$arch', - 'http://mirrors.advancedhosters.com/archlinux/$repo/os/$arch', - 'http://mirror.us.leaseweb.net/archlinux/$repo/os/$arch', - 'http://ftp.osuosl.org/pub/archlinux/$repo/os/$arch', - 'http://arch.mirrors.ionfish.org/$repo/os/$arch', - 'http://mirrors.gigenet.com/archlinux/$repo/os/$arch', - 'http://mirror.jmu.edu/pub/archlinux/$repo/os/$arch'], - 'packages': {'sed': {'repo': 'core'}}, - 'repos': {'archlinuxfr': {'enabled': False, - 'mirror': 'http://repo.archlinux.fr/$arch', - 'siglevel': 'Optional TrustedOnly'}, - 'community': {'enabled': True, - 'mirror': 'file:///etc/pacman.d/mirrorlist', - 'siglevel': 'default'}, - 'core': {'enabled': True, - 'mirror': 'file:///etc/pacman.d/mirrorlist', - 'siglevel': 'default'}, - 'extra': {'enabled': True, - 'mirror': 'file:///etc/pacman.d/mirrorlist', - 'siglevel': 'default'}, - 'multilib': {'enabled': True, - 'mirror': 'file:///etc/pacman.d/mirrorlist', - 'siglevel': 'default'}, - 'multilib-testing': {'enabled': False, - 'mirror': 'file:///etc/pacman.d/mirrorlist', - 'siglevel': 'default'}, - 'testing': {'enabled': False, - 'mirror': 'file:///etc/pacman.d/mirrorlist', - 'siglevel': 'default'}}}, - 'system': {'bootloader': {'efi': 'true', 'target': '/boot', 'type': 'grub'}, - 'chrootpath': '/mnt', - 'kbd': False, - 'locale': 'en_US.UTF-8', - 'services': False, - 'timezone': 'EST5EDT'}, - 'users': {'aifusr': {'comment': 'A test user for AIF.', - 'gid': None, - 'group': None, - 'home': {'create': True, 'path': '/opt/aifusr'}, - 'password': '$6$WtxZKOyaahvvWQRG$TUys60kQhF0ffBdnDSJVTA.PovwCOajjMz8HEHL2H0ZMi0bFpDTQvKA7BqzM3nA.ZMAUxNjpJP1dG/eA78Zgw0', - 'sudo': True, - 'uid': None, - 'xgroup': {'admins': {'create': True, 'gid': False}, - 'users': {'create': False, 'gid': False}, - 'wheel': {'create': False, 'gid': False}}}, - 'root': {'password': '$6$3YPpiS.l3SQC6ELe$NQ4qMvcDpv5j1cCM6AGNc5Hyg.rsvtzCt2VWlSbuZXCGg2GB21CMUN8TMGS35tdUezZ/n9y3UFGlmLRVWXvZR.'}}}