Support for multiple sample templates
This commit is contained in:
parent
1345d95889
commit
07e99017b1
62
README.md
62
README.md
|
@ -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
|
||||
```
|
||||
|
|
|
@ -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/ .
|
|
@ -0,0 +1 @@
|
|||
*
|
36
main.html
36
main.html
|
@ -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
48
main.py
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue