okay, some minor changes to the XML stuff. getting there

This commit is contained in:
brent s. 2019-12-10 06:59:47 -05:00
parent c7ce23ff0f
commit 06c99221d2
8 changed files with 103 additions and 1244 deletions

1170
aif.xsd

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,9 @@
import os
##
from . import _common from . import _common
from . import netctl from . import netctl
from . import networkd from . import networkd
from . import networkmanager from . import networkmanager
from . import main


# No longer necessary: # No longer necessary:
# try: # try:
@ -18,3 +19,43 @@ from . import main
# from . import networkd # from . import networkd
# except ImportError: # except ImportError:
# from . import networkd_fallback as networkd # from . import networkd_fallback as networkd


class Net(object):
def __init__(self, chroot_base, network_xml):
self.xml = network_xml
self.chroot_base = chroot_base
self.hostname = self.xml.attrib['hostname'].strip()
self.provider = self.xml.attrib.get('provider', 'networkd').strip()
if self.provider == 'netctl':
self.provider = netctl
elif self.provider == 'nm':
self.provider = networkmanager
elif self.provider == 'networkd':
self.provider = networkd
else:
raise RuntimeError('Could not determine provider')
self.connections = []
self._initConns()

def _initConns(self):
for e in self.xml.xpath('ethernet|wireless'):
conn = None
if e.tag == 'ethernet':
conn = self.provider.Ethernet(e)
elif e.tag == 'wireless':
conn = self.provider.Wireless(e)
self.connections.append(conn)

def apply(self, chroot_base):
cfg = os.path.join(chroot_base, 'etc', 'hostname')
with open(cfg, 'w') as fh:
fh.write('{0}\n'.format(self.hostname))
os.chown(cfg, 0, 0)
os.chmod(cfg, 0o0644)
for iface in self.connections:
for src, dest in iface.services.items():
realdest = os.path.join(chroot_base, dest)
os.symlink(src, realdest)
iface.writeConf(chroot_base)
return ()

View File

@ -1,42 +0,0 @@
import os


class Network(object):
def __init__(self, network_xml):
self.xml = network_xml
self.hostname = self.xml.attrib['hostname'].strip()
self.provider = self.xml.attrib.get('provider', 'networkd').strip()
handler = None
if self.provider == 'netctl':
import aif.network.netctl as handler
elif self.provider == 'nm':
import aif.network.networkmanager as handler
elif self.provider == 'networkd':
import aif.network.networkd as handler
self.provider = handler
if not self.provider:
raise RuntimeError('Could not determine handler')
self.connections = []
self._initConns()

def _initConns(self):
for e in self.xml.xpath('ethernet|wireless'):
conn = None
if e.tag == 'ethernet':
conn = self.provider.Ethernet(e)
elif e.tag == 'wireless':
conn = self.provider.Wireless(e)
self.connections.append(conn)

def apply(self, chroot_base):
cfg = os.path.join(chroot_base, 'etc', 'hostname')
with open(cfg, 'w') as fh:
fh.write('{0}\n'.format(self.hostname))
os.chown(cfg, 0, 0)
os.chmod(cfg, 0o0644)
for iface in self.connections:
for src, dest in iface.services.items():
realdest = os.path.join(chroot_base, dest)
os.symlink(src, realdest)
iface.writeConf(chroot_base)
return()

View File

@ -4,5 +4,18 @@ from . import users
from . import services from . import services




def main(system_xml): class Sys(object):
pass def __init__(self, chroot_base, system_xml):
self.xml = system_xml
self.chroot_base = chroot_base
self.locale = locales.Locale(self.chroot_base, self.xml.find('locales'))
self.tz = locales.Timezone(self.chroot_base, self.xml.attrib.get('timezone', 'UTC'))
self.user = users.UserDB(self.chroot_base, self.xml.find('rootPassword'), self.xml.find('users'))
self.services = services.ServiceDB(self.chroot_base, self.xml.find('services'))

def apply(self):
self.locale.writeConf()
self.tz.apply()
self.user.writeConf()
self.services.apply()
return()

View File

@ -34,8 +34,9 @@ class Font(object):




class Keyboard(object): class Keyboard(object):
def __init__(self, keyboard_xml): def __init__(self, chroot_base, keyboard_xml):
self.xml = keyboard_xml self.xml = keyboard_xml
self.chroot_base = chroot_base
self.settings = {} self.settings = {}
if self.xml: if self.xml:
chk = {'KEYMAP': self.xml.find('map'), chk = {'KEYMAP': self.xml.find('map'),
@ -44,14 +45,14 @@ class Keyboard(object):
if xml: if xml:
self.settings[setting] = xml.text.strip() self.settings[setting] = xml.text.strip()


def verify(self, chroot_base): def verify(self):
kbdnames = [] kbdnames = []
for i in ('KEYMAP', 'KEYMAP_TOGGLE'): for i in ('KEYMAP', 'KEYMAP_TOGGLE'):
if i in self.settings.keys(): if i in self.settings.keys():
kbdnames.append(self.settings[i]) kbdnames.append(self.settings[i])
if not kbdnames: if not kbdnames:
return(None) return(None)
keymapdir = os.path.join(chroot_base, 'usr', 'share', 'kbd', 'keymaps') keymapdir = os.path.join(self.chroot_base, 'usr', 'share', 'kbd', 'keymaps')
kbdmaps = [] kbdmaps = []
for root, dirs, files in os.walk(keymapdir, topdown = True): for root, dirs, files in os.walk(keymapdir, topdown = True):
if root.endswith('/include'): if root.endswith('/include'):
@ -69,8 +70,9 @@ class Keyboard(object):




class Console(object): class Console(object):
def __init__(self, console_xml): def __init__(self, chroot_base, console_xml):
self.xml = console_xml self.xml = console_xml
self.chroot_base = chroot_base
self._cfg = configparser.ConfigParser() self._cfg = configparser.ConfigParser()
self._cfg.optionxform(str) self._cfg.optionxform(str)
self.keyboard = Keyboard(self.xml.find('keyboard')) self.keyboard = Keyboard(self.xml.find('keyboard'))
@ -79,10 +81,10 @@ class Console(object):
for i in (self.keyboard, self.font): for i in (self.keyboard, self.font):
self._cfg['BASE'].update(i.settings) self._cfg['BASE'].update(i.settings)


def writeConf(self, chroot_base): def writeConf(self):
for x in (self.font, self.keyboard): for x in (self.font, self.keyboard):
x.verify(chroot_base) x.verify()
cfg = os.path.join(chroot_base, 'etc', 'vconsole.conf') cfg = os.path.join(self.chroot_base, 'etc', 'vconsole.conf')
# We have to strip out the section from the ini. # We have to strip out the section from the ini.
cfgbuf = io.StringIO() cfgbuf = io.StringIO()
self._cfg.write(cfgbuf, space_around_delimiters = False) self._cfg.write(cfgbuf, space_around_delimiters = False)

View File

@ -11,8 +11,9 @@ _locale_def_re = re.compile(r'([^.]*)[^@]*(.*)')




class Locale(object): class Locale(object):
def __init__(self, locales_xml): def __init__(self, chroot_base, locales_xml):
self.xml = locales_xml self.xml = locales_xml
self.chroot_base = chroot_base
self.syslocales = {} self.syslocales = {}
self.userlocales = [] self.userlocales = []
self.rawlocales = None self.rawlocales = None
@ -31,8 +32,8 @@ class Locale(object):
self.userlocales = ['en_US', 'en_US.UTF-8'] self.userlocales = ['en_US', 'en_US.UTF-8']
return() return()


def _verify(self, chroot_base): def _verify(self):
localegen = os.path.join(chroot_base, 'etc', 'locale.gen') # This *should* be brand new. localegen = os.path.join(self.chroot_base, 'etc', 'locale.gen') # This *should* be brand new.
with open(localegen, 'r') as fh: with open(localegen, 'r') as fh:
self.rawlocales = fh.read().splitlines() self.rawlocales = fh.read().splitlines()
for idx, line in enumerate(self.rawlocales[:]): for idx, line in enumerate(self.rawlocales[:]):
@ -50,12 +51,12 @@ class Locale(object):
raise ValueError('non-existent locale specified') raise ValueError('non-existent locale specified')
return() return()


def writeConf(self, chroot_base): def writeConf(self):
# We basically recreate locale-gen in python here, more or less. # We basically recreate locale-gen in python here, more or less.
self._verify(chroot_base) self._verify()
localegen = os.path.join(chroot_base, 'etc', 'locale.gen') localegen = os.path.join(self.chroot_base, 'etc', 'locale.gen')
localedbdir = os.path.join(chroot_base, 'usr', 'lib', 'locale') localedbdir = os.path.join(self.chroot_base, 'usr', 'lib', 'locale')
localesrcdir = os.path.join(chroot_base, 'usr', 'share', 'i18n') localesrcdir = os.path.join(self.chroot_base, 'usr', 'share', 'i18n')
with open(localegen, 'w') as fh: with open(localegen, 'w') as fh:
fh.write('# Generated by AIF-NG.\n\n') fh.write('# Generated by AIF-NG.\n\n')
fh.write('\n'.join(self.rawlocales)) fh.write('\n'.join(self.rawlocales))
@ -86,12 +87,12 @@ class Locale(object):
# '--charmap={0}'.format(os.path.join(localesrcdir, 'charmaps', charset)), # '--charmap={0}'.format(os.path.join(localesrcdir, 'charmaps', charset)),
'--inputfile={0}'.format(ldef_name), '--inputfile={0}'.format(ldef_name),
'--charmap={0}'.format(charset), '--charmap={0}'.format(charset),
'--alias-file={0}'.format(os.path.join(chroot_base, '--alias-file={0}'.format(os.path.join(self.chroot_base,
'usr', 'share', 'locale', 'locale.alias')), 'usr', 'share', 'locale', 'locale.alias')),
'--prefix={0}'.format(chroot_base), '--prefix={0}'.format(self.chroot_base),
locale], locale],
env = env) env = env)
cfg = os.path.join(chroot_base, 'etc', 'locale.conf') cfg = os.path.join(self.chroot_base, 'etc', 'locale.conf')
# And now we write the variables. # And now we write the variables.
# We have to strip out the section from the ini. # We have to strip out the section from the ini.
cfgbuf = io.StringIO() cfgbuf = io.StringIO()
@ -108,19 +109,20 @@ class Locale(object):




class Timezone(object): class Timezone(object):
def __init__(self, timezone): def __init__(self, chroot_base, timezone):
self.tz = timezone.strip().replace('.', '/') self.tz = timezone.strip().replace('.', '/')
self.chroot_base = chroot_base


def _verify(self, chroot_base): def _verify(self):
tzfilebase = os.path.join('usr', 'share', 'zoneinfo', self.tz) tzfilebase = os.path.join('usr', 'share', 'zoneinfo', self.tz)
tzfile = os.path.join(chroot_base, tzfilebase) tzfile = os.path.join(self.chroot_base, tzfilebase)
if not os.path.isfile(tzfile): if not os.path.isfile(tzfile):
raise ValueError('Invalid timezone') raise ValueError('Invalid timezone')
return(tzfilebase) return(tzfilebase)


def apply(self, chroot_base): def apply(self):
tzsrcfile = os.path.join('/', self._verify(chroot_base)) tzsrcfile = os.path.join('/', self._verify())
tzdestfile = os.path.join(chroot_base, 'etc', 'localtime') tzdestfile = os.path.join(self.chroot_base, 'etc', 'localtime')
if os.path.isfile(tzdestfile): if os.path.isfile(tzdestfile):
os.remove(tzdestfile) os.remove(tzdestfile)
os.symlink(tzsrcfile, tzdestfile) os.symlink(tzsrcfile, tzdestfile)

View File

@ -37,7 +37,7 @@ class Service(object):




class ServiceDB(object): class ServiceDB(object):
def __init__(self, services_xml, chroot_base): def __init__(self, chroot_base, services_xml):
self.xml = services_xml self.xml = services_xml
self.chroot_base = chroot_base self.chroot_base = chroot_base
self.systemd_sys = os.path.join(self.chroot_base, 'usr', 'lib', 'systemd', 'system') self.systemd_sys = os.path.join(self.chroot_base, 'usr', 'lib', 'systemd', 'system')

View File

@ -1,10 +1,23 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<aif xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <aif xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://aif-ng.io/" xmlns="https://aif-ng.io/"
xsi:schemaLocation="http://aif-ng.io/ http://aif-ng.io/aif.xsd" xsi:schemaLocation="https://aif-ng.io/ https://schema.xml.r00t2.io/projects/aif.xsd"
version="v2_rewrite"
chrootPath="/mnt/aif" chrootPath="/mnt/aif"
reboot="false"><!-- When we release, this should match the tagged release (e.g. 0.2.0) --> reboot="false">
<bootstrap>
<tarball>https://arch.mirror.square-r00t.net/iso/latest/archlinux-bootstrap-2019.12.01-x86_64.tar.gz</tarball>
<verify>
<gpg>
<signatureFile>
https://arch.mirror.square-r00t.net/iso/latest/archlinux-bootstrap-2019.12.01-x86_64.tar.gz.sig
</signatureFile>
</gpg>
<hash>
<checksumFile hashType="md5">http://arch.mirror.square-r00t.net/iso/latest/md5sums.txt</checksumFile>
<checksumFile hashType="sha1">http://arch.mirror.square-r00t.net/iso/latest/sha1sums.txt</checksumFile>
</hash>
</verify>
</bootstrap>
<storage> <storage>
<blockDevices> <blockDevices>
<disk id="sda" device="/dev/sda" diskFormat="gpt"> <disk id="sda" device="/dev/sda" diskFormat="gpt">