diff --git a/bdisk/bdisk.xsd b/bdisk/bdisk.xsd
index 2ce20e5..e54c4e1 100644
--- a/bdisk/bdisk.xsd
+++ b/bdisk/bdisk.xsd
@@ -3,9 +3,247 @@
targetNamespace="http://bdisk.square-r00t.net/"
xmlns="http://bdisk.square-r00t.net/"
elementFormDefault="qualified">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -23,8 +261,9 @@
-
+
+
+
@@ -33,8 +272,12 @@
-
+
+
+
+
+
+
@@ -43,6 +286,7 @@
+
@@ -57,10 +301,30 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -114,29 +378,427 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bdisk/confgen.py b/bdisk/confgen.py
index 5b10e2e..c6e8ed0 100755
--- a/bdisk/confgen.py
+++ b/bdisk/confgen.py
@@ -4,7 +4,7 @@
# Go figure.
import confparse
-import crypt
+import datetime
import getpass
import os
import utils
@@ -134,7 +134,12 @@ class ConfGenerator(object):
self.cfg = c.xml
self.append = True
else:
- self.cfg = lxml.etree.Element('bdisk')
+ _ns = {None: 'http://bdisk.square-r00t.net/',
+ 'xsi': 'http://www.w3.org/2001/XMLSchema-instance'}
+ _xsi = {
+ '{http://www.w3.org/2001/XMLSchema-instance}schemaLocation':
+ 'http://bdisk.square-r00t.net bdisk.xsd'}
+ self.cfg = lxml.etree.Element('bdisk', nsmap = _ns, attrib = _xsi)
self.append = False
self.profile = lxml.etree.Element('profile')
self.cfg.append(self.profile)
@@ -155,6 +160,13 @@ class ConfGenerator(object):
self.get_pki()
self.get_gpg()
self.get_sync()
+ # TODO: make this more specific (script? gui? web? etc.)
+ # and append comment to bdisk element
+ _comment = lxml.etree.Comment(
+ 'Generated {0} by BDisk configuration generator'.format(
+ str(datetime.datetime.now())
+ )
+ )
except KeyboardInterrupt:
exit('\n\nCaught KeyboardInterrupt; quitting...')
return()
@@ -472,7 +484,7 @@ class ConfGenerator(object):
print('Invalid selection. Starting over.')
continue
chksum.attrib['hash_algo'] = checksum_type
- chksum.attrib['explicit'] = "no"
+ chksum.attrib['explicit'] = "false"
chksum.text = checksum['full_url']
else:
# Maybe it's a digest string.
@@ -505,7 +517,7 @@ class ConfGenerator(object):
continue
else:
checksum_type = checksum_type[0]
- chksum.attrib['explicit'] = "yes"
+ chksum.attrib['explicit'] = "true"
chksum.text = checksum
chksum.attrib['hash_algo'] = checksum_type
print('\n++ SOURCES || {0} || GPG ++'.format(arch.upper()))
@@ -597,7 +609,7 @@ class ConfGenerator(object):
usage = (
'{0} for yes, {1} for no...\n'))
if _chk_optimizations:
- build.attrib['its_full_of_stars'] = 'yes'
+ build.attrib['its_full_of_stars'] = 'true'
print('\n++ BUILD || PATHS ++')
# Thankfully, we can simplify a lot of this.
_dir_strings = {'base': ('the base directory (used for files that are '
@@ -678,9 +690,9 @@ class ConfGenerator(object):
self.profile.append(iso)
# We have more than one arch, so we need to ask how they want to handle
# it.
- _ma_strings = {'yes': ('a multi-arch ISO (both architectures on one '
+ _ma_strings = {'true': ('a multi-arch ISO (both architectures on one '
'ISO)'),
- 'no': ('separate image files for '
+ 'false': ('separate image files for '
'{0}').format(' and '.join(_arches))}
for a in _arches:
_ma_strings[a] = 'only build an image file for {0}'.format(a)
@@ -712,7 +724,7 @@ class ConfGenerator(object):
'option to configure it a bit later).\nWould you like to sign '
'the ISO/USB image files with GPG?\n'), usage = (
'{0} for yes, {1} for no...\n'))
- _gpg_sign = ('yes' if _gpg_input else 'no')
+ _gpg_sign = ('true' if _gpg_input else 'false')
iso.attrib['sign'] = _gpg_sign
self.profile.append(iso)
return()
@@ -727,21 +739,21 @@ class ConfGenerator(object):
'see the manual for more information). Would you like to '
'build iPXE support?\n'), usage = (
'{0} for yes, {1} for no...\n'))
- _ipxe = ('yes' if _ipxe else 'no')
- if _ipxe == 'yes':
+ _ipxe = ('true' if _ipxe else 'true')
+ if _ipxe == 'true':
print('\n++ iPXE || MINI-ISO ++')
_iso = prompt.confirm_or_no(prompt = (
'\nWould you like to build a "mini-ISO" (see the manual) for '
'bootstrapping iPXE booting from USB or optical media?\n'),
usage = ('{0} for yes, {1} for no...\n'))
- ipxe.attrib['iso'] = ('yes' if _iso else 'no')
+ ipxe.attrib['iso'] = ('true' if _iso else 'false')
print('\n++ iPXE || SIGNING ++')
_sign = prompt.confirm_or_no(prompt = (
'\nBDisk can sign the mini-ISO and other relevant files for '
'iPXE builds using GPG. Would you like to sign the iPXE build '
'distributables? (You\'ll have the chance to configure GPG '
'later).\n'), usage = ('{0} for yes, {1} for no...\n'))
- ipxe.attrib['sign'] = ('yes' if _sign else 'no')
+ ipxe.attrib['sign'] = ('true' if _sign else 'false')
_uri = None
while not _uri:
print('\n++ iPXE || URL ++')
@@ -756,7 +768,7 @@ class ConfGenerator(object):
else:
uri = lxml.etree.SubElement(ipxe, 'uri')
uri.text = _uri
- if _ipxe == 'yes':
+ if _ipxe == 'true':
self.profile.append(ipxe)
return()
@@ -782,7 +794,7 @@ class ConfGenerator(object):
'wish to keep persistent keys and certs), you should '
'DEFINITELY answer no here.\n'),
usage = ('{0} for yes, {1} for no...\n'))
- pki.attrib['overwrite'] = ('yes' if _overwrite else 'no')
+ pki.attrib['overwrite'] = ('true' if _overwrite else 'false')
for x in ('ca', 'client'):
print('\n++ SSL/TLS PKI || {0} ++'.format(x.upper()))
_x = None
@@ -806,7 +818,7 @@ class ConfGenerator(object):
for x in _xpaths:
_x = self.profile.xpath(x)
for a in _x:
- if a == 'yes':
+ if a == 'true':
_sigchk = True
break
if _sigchk:
@@ -850,7 +862,7 @@ class ConfGenerator(object):
'\nWould you like to push the key to the SKS keyserver pool '
'(making it much easier for end-users to look it up)?\n'),
usage = ('{0} for yes, {1} for no...\n'))
- gpg.attrib['publish'] = ('yes' if _gpgpublish else 'no')
+ gpg.attrib['publish'] = ('true' if _gpgpublish else 'false')
print('\n++ GPG || PASSWORD HANDLING ++')
_gpgpass_prompt = prompt.confirm_or_no(prompt = (
'\nWould you like BDisk to prompt you for a passphrase? If not, '
@@ -858,7 +870,8 @@ class ConfGenerator(object):
'the configuration (HIGHLY unrecommended) or use a blank '
'passphrase (also HIGHLY unrecommended).\n'),
usage = ('{0} for yes, {1} for no...\n'))
- gpg.attrib['prompt_passphrase'] = ('yes' if _gpgpass_prompt else 'no')
+ gpg.attrib['prompt_passphrase'] = ('true' if _gpgpass_prompt else
+ 'false')
_pass = None
if not _gpgpass_prompt:
while not _pass:
@@ -923,7 +936,7 @@ class ConfGenerator(object):
'\nWould you like to sync {0}?\n'.format(_syncs[s])),
usage = ('{0} for yes, {1} for no...\n'))
elem = lxml.etree.SubElement(sync, s)
- elem.attrib['enabled'] = ('yes' if _item_sync_chk else 'no')
+ elem.attrib['enabled'] = ('true' if _item_sync_chk else 'false')
if not _item_sync_chk:
continue
if s == 'gpg':
diff --git a/bdisk/confparse.py b/bdisk/confparse.py
index a551e0a..ab3c608 100644
--- a/bdisk/confparse.py
+++ b/bdisk/confparse.py
@@ -168,7 +168,7 @@ class Conf(object):
## PROFILE/BUILD(/PATHS)
self.cfg['build'] = {'paths': {}}
build = self.profile.xpath('./build')[0]
- _optimize = build.get('its_full_of_stars', 'no')
+ _optimize = build.get('its_full_of_stars', 'false')
self.cfg['build']['optimize'] = transform.xml2py(_optimize)
for path in build.xpath('./paths/*'):
self.cfg['build']['paths'][path.tag] = path.text
@@ -185,7 +185,7 @@ class Conf(object):
# We enable all features by default.
elem = self.profile.xpath('./{0}'.format(x))[0]
for a in self.cfg[x]:
- self.cfg[x][a] = transform.xml2py(elem.get(a, 'yes'))
+ self.cfg[x][a] = transform.xml2py(elem.get(a, 'true'))
if x == 'ipxe':
self.cfg[x]['uri'] = elem.xpath('./uri/text()')[0]
return()
diff --git a/bdisk/utils.py b/bdisk/utils.py
index 4886086..7dab775 100644
--- a/bdisk/utils.py
+++ b/bdisk/utils.py
@@ -15,6 +15,7 @@ import uuid
import validators
import zlib
import lxml.etree
+import lxml.objectify
from bs4 import BeautifulSoup
from collections import OrderedDict
from dns import resolver
@@ -446,12 +447,12 @@ class transform(object):
def py2xml(self, value, attrib = True):
if value in (False, ''):
if attrib:
- return("no")
+ return("false")
else:
return(None)
elif isinstance(value, bool):
# We handle the False case above.
- return("yes")
+ return("true")
elif isinstance(value, str):
return(value)
else:
@@ -469,7 +470,6 @@ class transform(object):
text_out = re.sub('[^\w]', '', text_out)
return(text_out)
- # noinspection PyDictCreation
def url_to_dict(self, orig_url, no_None = False):
def _getuserinfo(uinfo_str):
if len(uinfo_str) == 0:
@@ -659,8 +659,8 @@ class transform(object):
return(acct)
def xml2py(self, value, attrib = True):
- yes = re.compile('^\s*(y(es)?|true|1)\s*$', re.IGNORECASE)
- no = re.compile('^\s*(no?|false|0)\s*$', re.IGNORECASE)
+ yes = re.compile('^\s*(true|1)\s*$', re.IGNORECASE)
+ no = re.compile('^\s*(false|0)\s*$', re.IGNORECASE)
none = re.compile('^\s*(none|)\s*$', re.IGNORECASE)
if no.search(value):
if attrib:
@@ -819,12 +819,18 @@ class xml_supplicant(object):
# This is retained so we can "refresh" the profile if needed.
self.orig_profile = profile
try:
- self.xml = lxml.etree.fromstring(raw)
+ self.orig_xml = lxml.etree.fromstring(raw)
+ # We need to strip the naked namespace for XPath to work.
+ self.xml = copy.deepcopy(self.orig_xml)
+ self.roottree = self.xml.getroottree()
+ self.tree = self.roottree.getroot()
+ self.strip_naked_ns()
except lxml.etree.XMLSyntaxError:
raise ValueError('The configuration provided does not seem to be '
'valid')
self.get_profile(profile = profile)
- self.xml = lxml.etree.fromstring(raw)
+ # This is disabled; we set it above.
+ #self.xml = lxml.etree.fromstring(raw)
self.fmt = XPathFmt()
self.max_recurse = int(self.profile.xpath(
'//meta/max_recurse/text()')[0])
@@ -969,6 +975,23 @@ class xml_supplicant(object):
).format(element.text))
return(path)
+ def return_naked_ns(self):
+ # It's so stupid I have to do this.
+ return(self.orig_xml.nsmap)
+
+ def strip_naked_ns(self):
+ # I cannot *believe* that LXML doesn't have this built-in, considering
+ # how common naked namespaces are.
+ # https://stackoverflow.com/a/18160164/733214
+ for elem in self.roottree.getiterator():
+ if not hasattr(elem.tag, 'find'):
+ continue
+ i = elem.tag.find('}')
+ if i >= 0:
+ elem.tag = elem.tag[i + 1:]
+ lxml.objectify.deannotate(self.roottree, cleanup_namespaces = True)
+ return()
+
def substitute(self, element, recurse_count = 0):
if recurse_count >= self.max_recurse:
return(element)
diff --git a/docs/examples/multi_profile.xml b/docs/examples/multi_profile.xml
index d216962..b741664 100644
--- a/docs/examples/multi_profile.xml
+++ b/docs/examples/multi_profile.xml
@@ -1,286 +1,285 @@
-
-
-
-
- BDisk
- bdisk
-
- {xpath%../name/text()}
-
- A rescue/restore live environment.
-
- A. Dev Eloper
- dev@domain.tld
- https://domain.tld/~dev
-
- https://domain.tld/projname
- 1.0.0
-
-
- 5
-
+
+ 5
+
-
- archlinux-bootstrap-[0-9]{4}\.[0-9]{2}\.[0-9]{2}-x86_64\.tar\.gz$
- archlinux-bootstrap-[0-9]{4}\.[0-9]{2}\.[0-9]{2}-x86_64\.tar\.gz\.sig$
- archlinux-bootstrap-[0-9]{4}\.[0-9]{2}\.[0-9]{2}-i686\.tar\.gz$
- archlinux-bootstrap-[0-9]{4}\.[0-9]{2}\.[0-9]{2}-i686\.tar\.gz\.sig$
-
-
-
- /var/tmp/BDisk
-
-
-
-
- $6$7KfIdtHTcXwVrZAC$LZGNeMNz7v5o/cYuA48FAxtZynpIwO5B1CPGXnOW5kCTVpXVt4SypRqfM.AoKkFt/O7MZZ8ySXJmxpELKmdlF1
-
- {xpath%//meta/names/uxname/text()}
-
-
- {xpath%//meta/dev/author/text()}
- testpassword
-
-
- testuser
- Test User
- anothertestpassword
-
-
-
-
-
-
-
-
- {variable%bdisk_root}/base
- {variable%bdisk_root}/cache
- {variable%bdisk_root}/chroots
- {variable%bdisk_root}/overlay
- {variable%bdisk_root}/templates
- /mnt/{xpath%//meta/names/uxname/text()}
- {variable%bdisk_root}/distros
- {variable%bdisk_root}/results
- {variable%bdisk_root}/iso_overlay
- {variable%bdisk_root}/http
- {variable%bdisk_root}/tftp
- {variable%bdisk_root}/pki
-
- archlinux
-
-
-
- {xpath%//meta/dev/website/text()}/ipxe
-
-
-
-
- {xpath%../../../build/paths/pki/text()}/ca.crt
-
+
+ /var/tmp/BDisk
+
+
+
+
+ $6$7KfIdtHTcXwVrZAC$LZGNeMNz7v5o/cYuA48FAxtZynpIwO5B1CPGXnOW5kCTVpXVt4SypRqfM.AoKkFt/O7MZZ8ySXJmxpELKmdlF1
+
+ {xpath%//meta/names/uxname/text()}
+
+
+ {xpath%//meta/dev/author/text()}
+ testpassword
+
+
+ testuser
+ Test User
+ anothertestpassword
+
+
+
+
+
+
+
+
+ {variable%bdisk_root}/base
+ {variable%bdisk_root}/cache
+ {variable%bdisk_root}/chroots
+ {variable%bdisk_root}/overlay
+ {variable%bdisk_root}/templates
+ /mnt/{xpath%//meta/names/uxname/text()}
+ {variable%bdisk_root}/distros
+ {variable%bdisk_root}/results
+ {variable%bdisk_root}/iso_overlay
+ {variable%bdisk_root}/http
+ {variable%bdisk_root}/tftp
+ {variable%bdisk_root}/pki
+
+ archlinux
+
+
+
+ {xpath%//meta/dev/website/text()}/ipxe
+
+
+
+
+ {xpath%../../../build/paths/pki/text()}/ca.crt
+
-
-
-
-
-
- {xpath%../../../build/paths/pki/text()}/index.txt
- {xpath%../../../build/paths/pki/text()}/serial
-
+
+
+
+ {xpath%../../../build/paths/pki/text()}/index.txt
+ {xpath%../../../build/paths/pki/text()}/serial
+
- {xpath%../../../build/paths/pki/text()}/ca.key
-
- domain.tld
- XX
- Some City
- Some State
- Some Org, Inc.
- Department Name
- {xpath%../../../../meta/dev/email/text()}
-
-
-
- {xpath%../../../build/paths/pki/text()}/{xpath%../../../meta/names/uxname/text()}.crt
-
- {xpath%//build/paths/pki/text()}/{xpath%../../../meta/names/uxname/text()}.key
-
- some client name
- XX
- Some City
- Some State
- Some Org, Inc.
- Department Name
- {xpath%../../../../meta/dev/email/text()}
-
-
-
-
-
-
-
- {xpath%../../../meta/dev/author/text()}
- {xpath%../../../meta/dev/email/text()}
- for {xpath%../../../meta/names/pname/text()} [autogenerated] | {xpath%../../../meta/uri/text()} | {xpath%../../../meta/desc/text()}
-
-
-
-
- /srv/http/{xpath%../../meta/names/uxname/text()}
- /tftproot/{xpath%../../meta/names/uxname/text()}
- /srv/http/isos/{xpath%../../meta/names/uxname/text()}
- /srv/http/{xpath%../../meta/names/uxname/text()}/pubkey.asc
-
- root
- mirror.domain.tld
- 22
- ~/.ssh/id_ed25519
-
-
-
-
-
-
- AnotherCD
- bdisk_alt
- {xpath%../name/text()}
-
- Another rescue/restore live environment.
-
- Another Dev Eloper
-
- {xpath%//profile[@name="default"]/meta/dev/email/text()}
- {xpath%//profile[@name="default"]/meta/dev/website/text()}
-
- https://domain.tld/projname
- 0.0.1
- 5
-
- archlinux-bootstrap-[0-9]{4}\.[0-9]{2}\.[0-9]{2}-x86_64\.tar\.gz$
- archlinux-bootstrap-[0-9]{4}\.[0-9]{2}\.[0-9]{2}-x86_64\.tar\.gz\.sig$
- archlinux-bootstrap-[0-9]{4}\.[0-9]{2}\.[0-9]{2}-i686\.tar\.gz$
- archlinux-bootstrap-[0-9]{4}\.[0-9]{2}\.[0-9]{2}-i686\.tar\.gz\.sig$
-
-
- /var/tmp/BDisk
-
-
-
- atotallyinsecurepassword
-
- testuser
- Test User
- atestpassword
-
-
-
-
-
-
-
-
- {variable%bdisk_root}/base
- {variable%bdisk_root}/cache
- {variable%bdisk_root}/chroots
- {variable%bdisk_root}/overlay
- {variable%bdisk_root}/templates
- /mnt/{xpath%//meta/names/uxname/text()}
- {variable%bdisk_root}/distros
- {variable%bdisk_root}/results
- {variable%bdisk_root}/iso_overlay
- {variable%bdisk_root}/http
- {variable%bdisk_root}/tftp
- {variable%bdisk_root}/pki
-
- archlinux
-
-
-
- {xpath%//meta/dev/website/text()}/ipxe
-
-
-
- {xpath%../../../build/paths/pki/text()}/ca.crt
-
- {xpath%../../../build/paths/pki/text()}/index.txt
- {xpath%../../../build/paths/pki/text()}/serial
- {xpath%../../../build/paths/pki/text()}/ca.key
-
- domain.tld
- XX
- Some City
- Some State
- Some Org, Inc.
- Department Name
- {xpath%../../../../meta/dev/email/text()}
-
-
-
- {xpath%../../../build/paths/pki/text()}/{xpath%../../../meta/names/uxname/text()}.crt
-
- {xpath%//build/paths/pki/text()}/{xpath%../../../meta/names/uxname/text()}.key
-
- some client name
- XX
- Some City
- Some State
- Some Org, Inc.
- Department Name
- {xpath%../../../../meta/dev/email/text()}
-
-
-
-
-
- {xpath%../../../meta/dev/author/text()}
- {xpath%../../../meta/dev/email/text()}
- for {xpath%../../../meta/names/pname/text()} [autogenerated] | {xpath%../../../meta/uri/text()} | {xpath%../../../meta/desc/text()}
-
-
-
- /srv/http/{xpath%../../meta/names/uxname/text()}
- /tftproot/{xpath%../../meta/names/uxname/text()}
- /srv/http/isos/{xpath%../../meta/names/uxname/text()}
- /srv/http/{xpath%../../meta/names/uxname/text()}/pubkey.asc
-
- root
- mirror.domain.tld
- 22
- ~/.ssh/id_ed25519
-
-
-
+
+
+
+ {xpath%../../../meta/dev/author/text()}
+ {xpath%../../../meta/dev/email/text()}
+ for {xpath%../../../meta/names/pname/text()} [autogenerated] | {xpath%../../../meta/uri/text()} | {xpath%../../../meta/desc/text()}
+
+
+
+
+ /srv/http/{xpath%../../meta/names/uxname/text()}
+ /tftproot/{xpath%../../meta/names/uxname/text()}
+ /srv/http/isos/{xpath%../../meta/names/uxname/text()}
+ /srv/http/{xpath%../../meta/names/uxname/text()}/pubkey.asc
+
+ root
+ mirror.domain.tld
+ 22
+ ~/.ssh/id_ed25519
+
+
+
+
+
+
+ AnotherCD
+ bdisk_alt
+ {xpath%../name/text()}
+
+ Another rescue/restore live environment.
+
+ Another Dev Eloper
+ {xpath%//profile[@name="default"]/meta/dev/email/text()}
+ {xpath%//profile[@name="default"]/meta/dev/website/text()}
+
+ https://domain.tld/projname
+ 0.0.1
+ 5
+
+ archlinux-bootstrap-[0-9]{4}\.[0-9]{2}\.[0-9]{2}-x86_64\.tar\.gz$
+ archlinux-bootstrap-[0-9]{4}\.[0-9]{2}\.[0-9]{2}-x86_64\.tar\.gz\.sig$
+ archlinux-bootstrap-[0-9]{4}\.[0-9]{2}\.[0-9]{2}-i686\.tar\.gz$
+ archlinux-bootstrap-[0-9]{4}\.[0-9]{2}\.[0-9]{2}-i686\.tar\.gz\.sig$
+
+
+ /var/tmp/BDisk
+
+
+
+ atotallyinsecurepassword
+
+ testuser
+ Test User
+ atestpassword
+
+
+
+
+
+
+
+
+ {variable%bdisk_root}/base
+ {variable%bdisk_root}/cache
+ {variable%bdisk_root}/chroots
+ {variable%bdisk_root}/overlay
+ {variable%bdisk_root}/templates
+ /mnt/{xpath%//meta/names/uxname/text()}
+ {variable%bdisk_root}/distros
+ {variable%bdisk_root}/results
+ {variable%bdisk_root}/iso_overlay
+ {variable%bdisk_root}/http
+ {variable%bdisk_root}/tftp
+ {variable%bdisk_root}/pki
+
+ archlinux
+
+
+
+ {xpath%//meta/dev/website/text()}/ipxe
+
+
+
+ {xpath%../../../build/paths/pki/text()}/ca.crt
+
+ {xpath%../../../build/paths/pki/text()}/index.txt
+ {xpath%../../../build/paths/pki/text()}/serial
+ {xpath%../../../build/paths/pki/text()}/ca.key
+
+ domain.tld
+ XX
+ Some City
+ Some State
+ Some Org, Inc.
+ Department Name
+ {xpath%../../../../meta/dev/email/text()}
+
+
+
+ {xpath%../../../build/paths/pki/text()}/{xpath%../../../meta/names/uxname/text()}.crt
+
+ {xpath%//build/paths/pki/text()}/{xpath%../../../meta/names/uxname/text()}.key
+
+ some client name
+ XX
+ Some City
+ Some State
+ Some Org, Inc.
+ Department Name
+ {xpath%../../../../meta/dev/email/text()}
+
+
+
+
+
+ {xpath%../../../meta/dev/author/text()}
+ {xpath%../../../meta/dev/email/text()}
+ for {xpath%../../../meta/names/pname/text()} [autogenerated] | {xpath%../../../meta/uri/text()} | {xpath%../../../meta/desc/text()}
+
+
+
+ /srv/http/{xpath%../../meta/names/uxname/text()}
+ /tftproot/{xpath%../../meta/names/uxname/text()}
+ /srv/http/isos/{xpath%../../meta/names/uxname/text()}
+ /srv/http/{xpath%../../meta/names/uxname/text()}/pubkey.asc
+
+ root
+ mirror.domain.tld
+ 22
+ ~/.ssh/id_ed25519
+
+
+
diff --git a/docs/examples/regen_multi.py b/docs/examples/regen_multi.py
index 2f92570..bf32799 100755
--- a/docs/examples/regen_multi.py
+++ b/docs/examples/regen_multi.py
@@ -1,13 +1,34 @@
#!/usr/bin/env python3.6
import copy
-from lxml import etree
+from lxml import etree, objectify
-parser = etree.XMLParser(remove_blank_text = True)
+#parser = etree.XMLParser(remove_blank_text = True)
+parser = etree.XMLParser(remove_blank_text = False)
+
+# We need to append to a new root because you can't edit nsmap, and you can't
+# xpath on an element with a naked namespace (e.g. 'xlmns="..."').
+ns = {None: 'http://bdisk.square-r00t.net/',
+ 'xsi': 'http://www.w3.org/2001/XMLSchema-instance'}
+xsi = {'{http://www.w3.org/2001/XMLSchema-instance}schemaLocation':
+ 'http://bdisk.square-r00t.net bdisk.xsd'}
+new_cfg = etree.Element('bdisk', nsmap = ns, attrib = xsi)
+new_cfg.text = '\n '
with open('single_profile.xml', 'rb') as f:
xml = etree.fromstring(f.read(), parser)
+
+roottree = xml.getroottree()
+for elem in roottree.getiterator():
+ if not hasattr(elem.tag, 'find'):
+ continue
+ i = elem.tag.find('}')
+ if i >= 0:
+ elem.tag = elem.tag[i + 1:]
+objectify.deannotate(roottree, cleanup_namespaces = True)
+
+
single_profile = xml.xpath('/bdisk/profile[1]')[0]
alt_profile = copy.deepcopy(single_profile)
for c in alt_profile.xpath('//comment()'):
@@ -42,18 +63,22 @@ for e in accounts.iter():
if e.tag in accounts_tags:
e.text = accounts_tags[e.tag]
if e.tag == 'rootpass':
- e.attrib['hashed'] = 'no'
+ e.attrib['hashed'] = 'false'
elif e.tag == 'user':
- e.attrib['sudo'] = 'no'
+ e.attrib['sudo'] = 'false'
# Delete the second user
accounts.remove(accounts[2])
author = alt_profile.xpath('/profile/meta/dev/author')[0]
author.addnext(etree.Comment(
' You can reference other profiles within the same configuration. '))
-xml.append(alt_profile)
+#xml.append(alt_profile)
+
+for child in xml.xpath('/bdisk/profile'):
+ new_cfg.append(copy.deepcopy(child))
+new_cfg.append(alt_profile)
with open('multi_profile.xml', 'wb') as f:
- f.write(etree.tostring(xml,
+ f.write(etree.tostring(new_cfg,
pretty_print = True,
encoding = 'UTF-8',
xml_declaration = True))
diff --git a/docs/examples/single_profile.xml b/docs/examples/single_profile.xml
index fb159a3..38e05d6 100644
--- a/docs/examples/single_profile.xml
+++ b/docs/examples/single_profile.xml
@@ -1,11 +1,12 @@
-
- BDisk
+ BDISK
+
bdisk
archlinux-bootstrap-[0-9]{4}\.[0-9]{2}\.[0-9]{2}-x86_64\.tar\.gz$
- archlinux-bootstrap-[0-9]{4}\.[0-9]{2}\.[0-9]{2}-x86_64\.tar\.gz\.sig$
-
+ archlinux-bootstrap-[0-9]{4}\.[0-9]{2}\.[0-9]{2}-x86_64\.tar\.gz\.sig$
archlinux-bootstrap-[0-9]{4}\.[0-9]{2}\.[0-9]{2}-i686\.tar\.gz$
archlinux-bootstrap-[0-9]{4}\.[0-9]{2}\.[0-9]{2}-i686\.tar\.gz\.sig$
@@ -41,56 +41,48 @@
-
- $6$7KfIdtHTcXwVrZAC$LZGNeMNz7v5o/cYuA48FAxtZynpIwO5B1CPGXnOW5kCTVpXVt4SypRqfM.AoKkFt/O7MZZ8ySXJmxpELKmdlF1
-
-
+ $6$7KfIdtHTcXwVrZAC$LZGNeMNz7v5o/cYuA48FAxtZynpIwO5B1CPGXnOW5kCTVpXVt4SypRqfM.AoKkFt/O7MZZ8ySXJmxpELKmdlF1
+
{xpath%//meta/names/uxname/text()}
{xpath%//meta/dev/author/text()}
- testpassword
-
+ salt="auto">testpassword
-
+
testuser
- Test User
- Test User
+ anothertestpassword
-
+ salt="auto">anothertestpassword
-
+
{variable%bdisk_root}/base
{variable%bdisk_root}/cache
@@ -107,11 +99,11 @@
archlinux
-
-
+
+
{xpath%//meta/dev/website/text()}/ipxe
-
+
{xpath%../../../build/paths/pki/text()}/ca.crt
@@ -133,8 +125,7 @@
be (securely) prompted for the passphrase to unlock it/add a passphrase to it. -->
{xpath%../../../build/paths/pki/text()}/ca.key
-
+ keysize="4096">{xpath%../../../build/paths/pki/text()}/ca.key
domain.tld
XX
@@ -146,16 +137,13 @@
-
- {xpath%../../../build/paths/pki/text()}/{xpath%../../../meta/names/uxname/text()}.crt
-
+ {xpath%../../../build/paths/pki/text()}/{xpath%../../../meta/names/uxname/text()}.crt
{xpath%//build/paths/pki/text()}/{xpath%../../../meta/names/uxname/text()}.key
-
+ keysize="4096">{xpath%//build/paths/pki/text()}/{xpath%../../../meta/names/uxname/text()}.key
- some client name
+ website.tld
XX
Some City
Some State
@@ -169,26 +157,23 @@
blank passphrase for all operations. -->
+ publish="false"
+ prompt_passphrase="false">
{xpath%../../../meta/dev/author/text()}
{xpath%../../../meta/dev/email/text()}
- for {xpath%../../../meta/names/pname/text()} [autogenerated] | {xpath%../../../meta/uri/text()}
- | {xpath%../../../meta/desc/text()}
-
+ for {xpath%../../../meta/names/pname/text()} [autogenerated] | {xpath%../../../meta/uri/text()} | {xpath%../../../meta/desc/text()}
- /srv/http/{xpath%../../meta/names/uxname/text()}
- /tftproot/{xpath%../../meta/names/uxname/text()}
- /srv/http/isos/{xpath%../../meta/names/uxname/text()}
- /srv/http/{xpath%../../meta/names/uxname/text()}/pubkey.asc
-
-
+ /srv/http/{xpath%../../meta/names/uxname/text()}
+ /tftproot/{xpath%../../meta/names/uxname/text()}
+ /srv/http/isos/{xpath%../../meta/names/uxname/text()}
+ /srv/http/{xpath%../../meta/names/uxname/text()}/pubkey.asc
+
root
mirror.domain.tld
22