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.'}}}