holy cats. docs are finally done
and packaging commands/alternate packager reconfigured- though untested. bumping tag out of beta because nothing should(????) break.
This commit is contained in:
parent
fa61ea6400
commit
bad590518a
8
HOWTO
8
HOWTO
@ -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
|
|
10
aif.xsd
10
aif.xsd
@ -108,6 +108,12 @@
|
|||||||
<xs:pattern value="(file|https?)://.*" />
|
<xs:pattern value="(file|https?)://.*" />
|
||||||
</xs:restriction>
|
</xs:restriction>
|
||||||
</xs:simpleType>
|
</xs:simpleType>
|
||||||
|
|
||||||
|
<xs:simpleType name="scripttype">
|
||||||
|
<xs:restriction base="xs:token">
|
||||||
|
<xs:pattern value="(pre|post|pkg)" />
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
|
||||||
<xs:simpleType name="bootloaders">
|
<xs:simpleType name="bootloaders">
|
||||||
<xs:restriction base="xs:token">
|
<xs:restriction base="xs:token">
|
||||||
@ -266,7 +272,6 @@
|
|||||||
<xs:element name="pacman" maxOccurs="1" minOccurs="1">
|
<xs:element name="pacman" maxOccurs="1" minOccurs="1">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
<xs:element name="command" maxOccurs="1" minOccurs="0" />
|
|
||||||
<xs:element name="repos" maxOccurs="1" minOccurs="1">
|
<xs:element name="repos" maxOccurs="1" minOccurs="1">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
@ -305,6 +310,7 @@
|
|||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
|
<xs:attribute name="command" type="xs:string" />
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
<!-- END PACMAN -->
|
<!-- END PACMAN -->
|
||||||
@ -325,7 +331,7 @@
|
|||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:attribute name="uri" type="scripturi" use="required" />
|
<xs:attribute name="uri" type="scripturi" use="required" />
|
||||||
<xs:attribute name="order" type="xs:integer" use="required" />
|
<xs:attribute name="order" type="xs:integer" use="required" />
|
||||||
<xs:attribute name="bootstrap" type="xs:boolean" use="required" />
|
<xs:attribute name="execution" type="xs:scripttype" use="required" />
|
||||||
<xs:attribute name="user" type="xs:string" />
|
<xs:attribute name="user" type="xs:string" />
|
||||||
<xs:attribute name="password" type="xs:string" />
|
<xs:attribute name="password" type="xs:string" />
|
||||||
<xs:attribute name="realm" type="xs:string" />
|
<xs:attribute name="realm" type="xs:string" />
|
||||||
|
41
aifclient.py
41
aifclient.py
@ -306,10 +306,10 @@ class aif(object):
|
|||||||
for i in x:
|
for i in x:
|
||||||
aifdict['software']['mirrors'].append(i.text)
|
aifdict['software']['mirrors'].append(i.text)
|
||||||
# Then the command
|
# Then the command
|
||||||
if xmlobj.find('pacman/command') is None:
|
if 'command' in xmlobj.find('pacman').attrib:
|
||||||
aifdict['software']['command'] = False
|
aifdict['software']['command'] = xmlobj.find('pacman').attrib['command']
|
||||||
else:
|
else:
|
||||||
aifdict['software']['command'] = xmlobj.find('pacman/command').text
|
aifdict['software']['command'] = False
|
||||||
# And then the repo list.
|
# And then the repo list.
|
||||||
for x in xmlobj.findall('pacman/repos/repo'):
|
for x in xmlobj.findall('pacman/repos/repo'):
|
||||||
repo = x.attrib['name']
|
repo = x.attrib['name']
|
||||||
@ -348,11 +348,8 @@ class aif(object):
|
|||||||
scriptcontents = self.webFetch(x.attrib['uri'], auth).decode('utf-8')
|
scriptcontents = self.webFetch(x.attrib['uri'], auth).decode('utf-8')
|
||||||
else:
|
else:
|
||||||
scriptcontents = self.webFetch(x.attrib['uri']).decode('utf-8')
|
scriptcontents = self.webFetch(x.attrib['uri']).decode('utf-8')
|
||||||
if x.attrib['bootstrap'].lower() in ('true', '1'):
|
tempscriptdict[x.attrib['execution']][x.attrib['order']] = scriptcontents
|
||||||
tempscriptdict['pre'][x.attrib['order']] = scriptcontents
|
for d in ('pre', 'post', 'pkg'):
|
||||||
else:
|
|
||||||
tempscriptdict['post'][x.attrib['order']] = scriptcontents
|
|
||||||
for d in ('pre', 'post'):
|
|
||||||
keylst = list(tempscriptdict[d].keys())
|
keylst = list(tempscriptdict[d].keys())
|
||||||
keylst.sort()
|
keylst.sort()
|
||||||
for s in keylst:
|
for s in keylst:
|
||||||
@ -782,7 +779,6 @@ class archInstall(object):
|
|||||||
return(bootcmds)
|
return(bootcmds)
|
||||||
|
|
||||||
def scriptcmds(self, scripttype):
|
def scriptcmds(self, scripttype):
|
||||||
# Pre-run/"booststrap" scripts
|
|
||||||
t = scripttype
|
t = scripttype
|
||||||
if t in self.scripts.keys():
|
if t in self.scripts.keys():
|
||||||
for i, s in enumerate(self.scripts[t]):
|
for i, s in enumerate(self.scripts[t]):
|
||||||
@ -793,11 +789,11 @@ class archInstall(object):
|
|||||||
f.write(s)
|
f.write(s)
|
||||||
os.chmod(filepath, 0o700)
|
os.chmod(filepath, 0o700)
|
||||||
os.chown(filepath, 0, 0) # shouldn't be necessary, but just in case the umask's messed up or something.
|
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.
|
# We want to run these right away.
|
||||||
with open(logfile, 'a') as log:
|
with open(logfile, 'a') as log:
|
||||||
for i, s in enumerate(self.scripts['pre']):
|
for i, s in enumerate(self.scripts[t]):
|
||||||
subprocess.call('/root/scripts/pre/{0}'.format(i),
|
subprocess.call('/root/scripts/{0}/{1}'.format(t, i),
|
||||||
stdout = log,
|
stdout = log,
|
||||||
stderr = subprocess.STDOUT)
|
stderr = subprocess.STDOUT)
|
||||||
return()
|
return()
|
||||||
@ -847,12 +843,9 @@ class archInstall(object):
|
|||||||
# This should be run in the chroot, unless we find a way to pacstrap
|
# This should be run in the chroot, unless we find a way to pacstrap
|
||||||
# packages separate from chrooting
|
# packages separate from chrooting
|
||||||
if self.software['command']:
|
if self.software['command']:
|
||||||
pkgr = self.software['command']
|
pkgr = shlex.split(self.software['command'])
|
||||||
else:
|
else:
|
||||||
pkgr = 'pacman'
|
pkgr = ['pacman', '--needed', '--noconfirm', '-S']
|
||||||
pkgropts = ['--needed', '--noconfirm']
|
|
||||||
if pkgr == 'apacman':
|
|
||||||
pkgropts.extend(['--noedit', '--skipinteg'])
|
|
||||||
if self.software['packages']:
|
if self.software['packages']:
|
||||||
for p in self.software['packages'].keys():
|
for p in self.software['packages'].keys():
|
||||||
if self.software['packages'][p]['repo']:
|
if self.software['packages'][p]['repo']:
|
||||||
@ -860,11 +853,8 @@ class archInstall(object):
|
|||||||
self.software['packages'][p])
|
self.software['packages'][p])
|
||||||
else:
|
else:
|
||||||
pkgname = p
|
pkgname = p
|
||||||
cmd = [pkgr]
|
pkgr.append(pkgname)
|
||||||
for o in pkgropts:
|
pkgcmds.append(pkgr)
|
||||||
cmd.append(o)
|
|
||||||
cmd.extend(['-S', pkgname])
|
|
||||||
pkgcmds.append(cmd)
|
|
||||||
return(pkgcmds)
|
return(pkgcmds)
|
||||||
|
|
||||||
def serviceSetup(self):
|
def serviceSetup(self):
|
||||||
@ -903,6 +893,12 @@ class archInstall(object):
|
|||||||
with open(logfile, 'a') as log:
|
with open(logfile, 'a') as log:
|
||||||
for c in chrootcmds:
|
for c in chrootcmds:
|
||||||
subprocess.call(c, stdout = log, stderr = subprocess.STDOUT)
|
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:
|
for p in pkgcmds:
|
||||||
subprocess.call(p, stdout = log, stderr = subprocess.STDOUT)
|
subprocess.call(p, stdout = log, stderr = subprocess.STDOUT)
|
||||||
for b in bootcmds:
|
for b in bootcmds:
|
||||||
@ -946,6 +942,7 @@ def main():
|
|||||||
with open(logfile, 'a') as log:
|
with open(logfile, 'a') as log:
|
||||||
pprint.pprint(instconf, stream = log)
|
pprint.pprint(instconf, stream = log)
|
||||||
runInstall(instconf)
|
runInstall(instconf)
|
||||||
|
subprocess.call(['reboot'])
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
@ -409,12 +409,22 @@ The `/aif/system/service` element holds information about services that should e
|
|||||||
|======================
|
|======================
|
||||||
|
|
||||||
=== `<pacman>`
|
=== `<pacman>`
|
||||||
The `/aif/pacman` element contains the <<code_repos_code, repos>>, <<code_repo_code, repos/repo>>, <<code_mirrorlist_code, mirrorlist>>, <<code_mirror_code, mirrorlist/mirror>>, <<code_software_code, software>>, <<code_package_code, software/packages>>, and <<code_command_code, command>> elements.
|
The `/aif/pacman` element contains the <<code_repos_code, repos>>, <<code_repo_code, repos/repo>>, <<code_mirrorlist_code, mirrorlist>>, <<code_mirror_code, mirrorlist/mirror>>, <<code_software_code, software>>, and <<code_package_code, software/packages>> elements.
|
||||||
|
|
||||||
==== `<command>`
|
[options="header"]
|
||||||
NOTE: This is currently kind of useless. I need to implement a pre-package-installation <<code_scripts_code, hook script>> first. I promise it's coming.
|
|======================
|
||||||
|
^|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"` <<code_script_code, script>> 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.:
|
||||||
|
|
||||||
|
<aif ... >
|
||||||
|
...
|
||||||
|
<pacman command="apacman --needed --noconfirm --noedit --skipinteg -S">
|
||||||
|
...
|
||||||
|
</aif>
|
||||||
|
|
||||||
==== `<repos>`
|
==== `<repos>`
|
||||||
The `/aif/pacman/repos` element contains one (or more) <<code_repo_code, repo>> element(s).
|
The `/aif/pacman/repos` element contains one (or more) <<code_repo_code, repo>> element(s).
|
||||||
@ -476,7 +486,15 @@ The `/aif/scripts/script` elements specify scripts to be run at different stages
|
|||||||
^m|user |Same behavior as <<starting_an_install, `aif_user`>> but for fetching this script (see also <<aif_url, further notes>> on this)
|
^m|user |Same behavior as <<starting_an_install, `aif_user`>> but for fetching this script (see also <<aif_url, further notes>> on this)
|
||||||
^m|password |Same behavior as <<starting_an_install, `aif_password`>> but for fetching this script (see also <<aif_url, further notes>> on this)
|
^m|password |Same behavior as <<starting_an_install, `aif_password`>> but for fetching this script (see also <<aif_url, further notes>> on this)
|
||||||
^m|realm |Same behavior as <<starting_an_install, `aif_realm`>> but for fetching this script (see also <<aif_url, further notes>> on this)
|
^m|realm |Same behavior as <<starting_an_install, `aif_realm`>> but for fetching this script (see also <<aif_url, further notes>> on this)
|
||||||
^m|bootstrap |A boolean; if `1`/`true` then we will run this script before even formatting <<code_disk_code, disks>>; otherwise if it's `0`/`false` then we would run it *inside* the chroot environment as the very last thing
|
^m|execution |(see <<script_types, below>>)
|
||||||
|======================
|
|======================
|
||||||
|
|
||||||
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 <<code_package_code, packages>> are installed (this allows you to configure an <<command, alternate packager>> 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.
|
||||||
|
77
sampledict
77
sampledict
@ -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.'}}}
|
|
Loading…
Reference in New Issue
Block a user