Support for multiple sample templates

This commit is contained in:
dave 2017-05-28 16:38:17 -07:00
parent 1345d95889
commit 07e99017b1
11 changed files with 308 additions and 41 deletions

View File

@ -1,13 +1,59 @@
pip3 install -r requirements.txt
apt-get update && apt-get install -y genisoimage
kickstart-builder
=================
Automated ISO builder for kickstart-based installation CDs
Setup:
-----
* Clone the repo
* Install requirements:
* `pip3 install -r requirements.txt`
* `apt-get install -y bsdtar genisoimage`
* Prepare at least one ISO (see below)
* Start it
* `python3 main.py`
* In your browser, visit http://127.0.0.1:8087/
Adding ISOs
-----------
For each ISO you want to make available, create a subdirectory under iso_raws with a name matching you want to see in
the UI. Unpack the contents of an ISO into this directory. Some files and directories will need to be chmodded so they
can be written to. Refer to the example commands below:
To unpack ISOs:
apt-get install -y bsdtar
```
cd iso_raws
mkdir ubuntu-16.04.1-server-amd64
cd mkdir ubuntu-16.04.1-server-amd64
bsdtar xfp ../ubuntu-16.04.1-server-amd64.iso
cd ubuntu-16.04.1-server-amd64
bsdtar xfp ~/Downloads/ubuntu-16.04.1-server-amd64.iso
chmod 644 isolinux/txt.cfg isolinux/isolinux.bin
chmod 755 preseed/ .
```
Alternatively, the script `add-iso.sh` can be used to add an ISO:
```
./add-iso.sh ~/Downloads/ubuntu-16.04.1-server-amd64.iso
```
Development Tips
----------------
In normal operation, the application loads templates and configs once on startup. If the `REFRESH` environmental
variable is set, it will reload the templates and configs on every page load:
```
REFRESH=1 python3 main.py
```
Additional config templates can be added under the "samples" directory.
Installing the `system-config-kickstart` provides a tool for generating Kickstart configs:
```
apt-get install system-config-kickstart
system-config-kickstart
```

13
add-iso.sh Executable file
View File

@ -0,0 +1,13 @@
#!/bin/bash -ex
ISO_PATH="$1"
ISO_NAME="$(basename $1 | sed -E 's/\.iso$//' )"
mkdir iso_raws/$ISO_NAME
cd iso_raws/$ISO_NAME
bsdtar xfp $ISO_PATH
chmod 644 isolinux/txt.cfg isolinux/isolinux.bin
chmod 755 preseed/ .

1
iso_raws/.gitignore vendored
View File

@ -0,0 +1 @@
*

View File

@ -9,6 +9,7 @@
}
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.2/css/bootstrap.min.css" type="text/css"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap-grid.min.css" type="text/css"/>
<title>Kickstart Builder</title>
</head>
<body>
@ -19,15 +20,30 @@
<span class="list-group-item list-group-item-danger"> Warning, these default configs will format drives without prompting! </span>
</div>
<br /><br />
<form action="/getIso" method="post">
<fieldset class="form-group">
<legend>Base ISO:</legend>
<select name="base_image" class="c-select">
{% for iso in ISOS: %}
<option value="{{ iso }}">{{ iso }}</option>
{% endfor %}
</select>
</fieldset>
<form action="/process" method="post">
<div class="row">
<div class="col">
<fieldset class="form-group">
<legend>Base ISO:</legend>
<select name="base_image" class="c-select">
{% for iso in ISOS: %}
<option value="{{ iso }}">{{ iso }}</option>
{% endfor %}
</select>
</fieldset>
</div>
<div class="col">
<fieldset class="form-group">
<legend>Sample configs:</legend>
<select name="sample" class="c-select">
{% for sample in SAMPLES: %}
<option value="{{ sample }}"{% if current_sample == sample %} selected{% endif %}>{{ sample }}</option>
{% endfor %}
</select>
<input type="submit" value="Load" name="action" class="btn btn-warning" onclick="return confirm('Warning: loading a new template will abandon changes made below.')">
</fieldset>
</div>
</div>
<br />
<fieldset class="form-group">
<legend>Menu Entries</legend>
@ -47,7 +63,7 @@
<textarea class="form-control" name="kickstart">{{ KS_CONTENT }}</textarea>
</fieldset>
<br />
<input type="submit" value="Download!" class="btn btn-success">
<input type="submit" value="Build" name="action" class="btn btn-success">
<br /><br />
</div>
</form>

48
main.py
View File

@ -12,26 +12,42 @@ class ISOserver(object):
self.data_dir = "./iso_raws"
self.iso_selection = [i for i in os.listdir(self.data_dir) if not i.startswith(".")]
self.builder_semaphores = {i: Semaphore() for i in self.iso_selection}
self._load_template()
self._load_templates()
def _load_template(self):
with open("./main.html") as template_f, \
open("./menu.default") as menu_f, \
open("./seed.default") as seed_f, \
open("./ks.default") as ks_f:
self.template = Environment().from_string(template_f.read()).render(MENU_ENTRIES=menu_f.read(),
SEED_CONTENT=seed_f.read(),
KS_CONTENT=ks_f.read(),
ISOS=self.iso_selection)
def _load_templates(self):
with open("./main.html") as template_f:
self.template = Environment().from_string(template_f.read())
samples = os.listdir("samples")
self.samples = {}
for item in samples:
self.samples[item] = {}
with open(os.path.join("samples", item, "menu.default")) as f:
self.samples[item]["menu"] = f.read()
with open(os.path.join("samples", item, "seed.default")) as f:
self.samples[item]["seed"] = f.read()
with open(os.path.join("samples", item, "ks.default")) as f:
self.samples[item]["ks"] = f.read()
@cherrypy.expose
def index(self, refresh=False):
if refresh:
self._load_template()
yield(self.template)
def index(self, refresh=False, sample="default"):
if refresh or "REFRESH" in os.environ:
self._load_templates()
yield(self.template.render(ISOS=self.iso_selection,
SAMPLES=self.samples.keys(),
MENU_ENTRIES=self.samples[sample]["menu"],
SEED_CONTENT=self.samples[sample]["seed"],
KS_CONTENT=self.samples[sample]["ks"],
current_sample=sample))
@cherrypy.expose
def getIso(self, menu_entries, seed_content, kickstart, base_image):
def process(self, menu_entries, seed_content, kickstart, base_image, action, sample):
if action == "Load":
assert sample in self.samples.keys()
raise cherrypy.HTTPRedirect("/?sample={}".format(sample))
assert base_image in self.iso_selection
cherrypy.response.headers['Content-Type'] = 'application/octet-stream'
@ -40,7 +56,7 @@ class ISOserver(object):
builder = self.isoBuilder(menu_entries, seed_content, kickstart, base_image)
return builder()
getIso._cp_config = {'response.stream': True}
process._cp_config = {'response.stream': True}
def isoBuilder(self, menu_entries, seed_content, kickstart, base_image):
datadir = os.path.join(self.data_dir, base_image)

View File

@ -1,39 +1,57 @@
#System language
lang en_US
#Language modules to install
langsupport en_US
#System keyboard
keyboard us
#System mouse
mouse
#System timezone
timezone America/Los_Angeles
#Root password
rootpw chewy2
rootpw ubuntu
#Initial user
user --disabled
#Reboot after installation
reboot
#Use text mode install
text
#Install OS instead of upgrade
install
#Use CDROM installation media
cdrom
#System bootloader configuration
bootloader --location=mbr
#Clear the Master Boot Record
zerombr yes
#Partition clearing information
clearpart --all --initlabel
#Disk partitioning information
part / --fstype ext4 --size 1 --grow
#System authorization infomation
auth --useshadow --enablemd5
#Network information
network --bootproto=dhcp --device=eth0
#Firewall configuration
firewall --disabled
#Do not configure the X Window System
skipx
@ -41,6 +59,7 @@ skipx
openssh-server
vim
htop
%post
# Add arbitrary shell code to execute in the installer environment below here
@ -61,4 +80,4 @@ if [ -f /etc/firstboot ] ; then
rm /etc/firstboot
reboot
fi
EOT
EOT

View File

@ -4,11 +4,6 @@ label install
kernel /install/vmlinuz
append file=/cdrom/preseed/ubuntu-server.seed vga=788 initrd=/install/initrd.gz quiet --
label webseed
menu label ^Install from web seed
kernel /install/vmlinuz
append initrd=/install/initrd.gz ks=http://ubuntuseed/webseed/webseed/ks.cfg url=http://ubuntuseed/webseed/webseed/ubuntu.seed --
label on_disk_kickstart
menu label ^Install from kickstart + seed
kernel /install/vmlinuz

View File

@ -1,29 +1,40 @@
# Always install the virtual kernel.
d-i base-installer/kernel/override-image string linux-virtual
# Don't even install the standard task.
tasksel tasksel/skip-tasks string standard
# Only install basic language packs. Let tasksel ask about tasks.
d-i pkgsel/language-pack-patterns string
# No language support packages.
d-i pkgsel/install-language-support boolean false
# Only ask the UTC question if there are other operating systems installed.
d-i clock-setup/utc-auto boolean true
# Use UTC time
d-i time/zone string UTC
# Verbose output and no boot splash screen.
d-i debian-installer/quiet boolean false
d-i debian-installer/splash boolean false
# Install the debconf oem-config frontend (if in OEM mode).
d-i oem-config-udeb/frontend string debconf
# Wait for two seconds in grub
d-i grub-installer/timeout string 2
# Add the network and tasks oem-config steps by default.
oem-config oem-config/steps multiselect language, timezone, keyboard, user, network, tasks
# Bypass no swap warning
d-i partman-basicfilesystems/no_swap boolean false
# dont wait a long time for dhcp
d-i netcfg/dhcp_timeout string 8
d-i netcfg/dhcpv6_timeout string 8
# Allow weak passwords in installer
d-i user-setup/allow-password-weak boolean true

86
samples/lvm/ks.default Normal file
View File

@ -0,0 +1,86 @@
#System language
lang en_US
#Language modules to install
langsupport en_US
#System keyboard
keyboard us
#System mouse
mouse
#System timezone
timezone America/Los_Angeles
#Root password
rootpw ubuntu
#Initial user
user --disabled
#Reboot after installation
reboot
#Use text mode install
text
#Install OS instead of upgrade
install
#Use CDROM installation media
cdrom
#System bootloader configuration
bootloader --location=mbr
#Clear the Master Boot Record
zerombr yes
#Partition clearing information
clearpart --all --initlabel
#Disk partitioning information
part /boot --fstype ext2 --size=500
part pv.01 --size=1 --grow
volgroup vg_root pv.01
logvol / --vgname=vg_root --name=lv_root --grow
#System authorization infomation
auth --useshadow --enablemd5
#Network information
network --bootproto=dhcp --device=eth0
#Firewall configuration
firewall --disabled
#Do not configure the X Window System
skipx
%packages
openssh-server
vim
htop
%post
# Add arbitrary shell code to execute in the installer environment below here
# run upgrades at first boot
touch /etc/firstboot
sed -i -e "s/exit\s*0//" /etc/rc.local
cat <<EOT >> /etc/rc.local
# Below this line can be removed after first boot
if [ -f /etc/firstboot ] ; then
set +e
sed -i -E "s/^PermitRootLogin .+/PermitRootLogin yes/" /etc/ssh/sshd_config
apt-get update
apt-get dist-upgrade -y
# Install new kernel on 14.04
#apt-get install -y linux-generic-lts-xenial open-vm-tools
# revert to upstart on 16.04
#apt-get install -y upstart-sysv
rm /etc/firstboot
reboot
fi
EOT

24
samples/lvm/menu.default Normal file
View File

@ -0,0 +1,24 @@
default install
label install
menu label ^Manual install
kernel /install/vmlinuz
append file=/cdrom/preseed/ubuntu-server.seed vga=788 initrd=/install/initrd.gz quiet --
label on_disk_kickstart
menu label ^Install from kickstart + seed
kernel /install/vmlinuz
append initrd=/install/initrd.gz ks=cdrom:/ks.cfg file=/cdrom/preseed/custom.seed --
label custom_seed
menu label ^Custom seed
kernel /install/vmlinuz
append initrd=/install/initrd.gz file=/cdrom/preseed/custom.seed --
label minimap_vm
menu label ^Minimal VM
kernel /install/vmlinuz
append initrd=/install/initrd.gz file=/cdrom/preseed/ubuntu-server-minimalvm.seed --
label memtest
menu label Test ^memory
kernel /install/mt86plus

40
samples/lvm/seed.default Normal file
View File

@ -0,0 +1,40 @@
# Always install the virtual kernel.
d-i base-installer/kernel/override-image string linux-virtual
# Don't even install the standard task.
tasksel tasksel/skip-tasks string standard
# Only install basic language packs. Let tasksel ask about tasks.
d-i pkgsel/language-pack-patterns string
# No language support packages.
d-i pkgsel/install-language-support boolean false
# Only ask the UTC question if there are other operating systems installed.
d-i clock-setup/utc-auto boolean true
# Use UTC time
d-i time/zone string UTC
# Verbose output and no boot splash screen.
d-i debian-installer/quiet boolean false
d-i debian-installer/splash boolean false
# Install the debconf oem-config frontend (if in OEM mode).
d-i oem-config-udeb/frontend string debconf
# Wait for two seconds in grub
d-i grub-installer/timeout string 2
# Add the network and tasks oem-config steps by default.
oem-config oem-config/steps multiselect language, timezone, keyboard, user, network, tasks
# Bypass no swap warning
d-i partman-basicfilesystems/no_swap boolean false
# dont wait a long time for dhcp
d-i netcfg/dhcp_timeout string 8
d-i netcfg/dhcpv6_timeout string 8
# Allow weak passwords in installer
d-i user-setup/allow-password-weak boolean true