duck-installer 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +674 -0
- data/README +35 -0
- data/bin/duck +9 -0
- data/duck.yaml +93 -0
- data/files/etc/dhclient-exit-hooks.d/hostname +17 -0
- data/files/etc/fstab +1 -0
- data/files/etc/hostname +1 -0
- data/files/etc/hosts +2 -0
- data/files/etc/inittab +25 -0
- data/files/etc/mtab +1 -0
- data/files/init +9 -0
- data/files/lib/duck.d/00-splash +36 -0
- data/files/lib/duck.d/02-setup-network +30 -0
- data/files/lib/duck.d/40-debootstrap +16 -0
- data/files/lib/duck.d/41-add-policy-rc.d +14 -0
- data/files/lib/duck.d/41-update-hostname +9 -0
- data/files/lib/duck.d/98-remove-policy-rc.d +9 -0
- data/files/lib/duck.d/99-reboot +18 -0
- data/files/lib/libduck.sh +152 -0
- data/files/lib/python-duck/duck/__init__.py +2 -0
- data/files/lib/python-duck/duck/db.py +48 -0
- data/files/lib/python-duck/duck/log.py +5 -0
- data/files/sbin/duckdb +212 -0
- data/files/sbin/duckinstall +21 -0
- data/files/sbin/ducklogin +3 -0
- data/fixes/clear-persistent-udev +10 -0
- data/fixes/kernel-boot-fix +53 -0
- data/fixes/squeeze-fix +14 -0
- data/lib/duck.rb +191 -0
- data/lib/duck/build.rb +395 -0
- data/lib/duck/chroot_utils.rb +51 -0
- data/lib/duck/enter.rb +20 -0
- data/lib/duck/logging.rb +31 -0
- data/lib/duck/module_helper.rb +56 -0
- data/lib/duck/pack.rb +42 -0
- data/lib/duck/qemu.rb +34 -0
- data/lib/duck/spawn_utils.rb +83 -0
- data/lib/duck/version.rb +3 -0
- metadata +103 -0
data/README
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
duck
|
2
|
+
----
|
3
|
+
|
4
|
+
A minimalist installer system generator.
|
5
|
+
|
6
|
+
about
|
7
|
+
-----
|
8
|
+
|
9
|
+
Duck will help you generate installer system images setup as an initrd, similar
|
10
|
+
to how debian-installer works.
|
11
|
+
|
12
|
+
There are however a few goals with duck that are different.
|
13
|
+
|
14
|
+
* No memory restrictions (debian-installer is geared towards 32M)
|
15
|
+
* Less rigorous space restrictions
|
16
|
+
- No special packaging necessary, but encouraged: http://www.emdebian.org/
|
17
|
+
- No library stripping.
|
18
|
+
|
19
|
+
All in all, you get a slightly bigger installer image, but a lot more
|
20
|
+
flexibility.
|
21
|
+
|
22
|
+
usage
|
23
|
+
-----
|
24
|
+
|
25
|
+
Duck has two steps in creating an initrd.
|
26
|
+
|
27
|
+
setup - Setup base configuration.
|
28
|
+
|
29
|
+
build - Build the base system.
|
30
|
+
pack - Pack the resulting initrd.gz
|
31
|
+
|
32
|
+
For testing/tweaking there are two other commands available.
|
33
|
+
|
34
|
+
enter - Enter the chroot that is used to build the initrd.
|
35
|
+
qemu - Run the resulting initrd in a qemu-based virtual environment.
|
data/bin/duck
ADDED
data/duck.yaml
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
---
|
2
|
+
sources:
|
3
|
+
- url: "http://www.emdebian.org/grip"
|
4
|
+
suite: squeeze
|
5
|
+
components:
|
6
|
+
- main
|
7
|
+
- url: "http://ftp.se.debian.org/debian"
|
8
|
+
suite: squeeze
|
9
|
+
components:
|
10
|
+
- main
|
11
|
+
|
12
|
+
packages:
|
13
|
+
- binutils
|
14
|
+
- python-argparse
|
15
|
+
- python
|
16
|
+
- grub2
|
17
|
+
- iproute
|
18
|
+
- bind9-host
|
19
|
+
- isc-dhcp-client
|
20
|
+
- net-tools
|
21
|
+
- openssh-server
|
22
|
+
- pciutils
|
23
|
+
- psutils
|
24
|
+
- syslog-ng
|
25
|
+
- udev
|
26
|
+
- vim-tiny
|
27
|
+
- less
|
28
|
+
- strace
|
29
|
+
|
30
|
+
files:
|
31
|
+
# init file
|
32
|
+
- from: /*
|
33
|
+
to: /
|
34
|
+
- from: /sbin/*
|
35
|
+
to: /sbin/
|
36
|
+
mode: 0755
|
37
|
+
# configuration files
|
38
|
+
- from: /etc/*
|
39
|
+
to: /etc/
|
40
|
+
- from: /etc/dhclient-exit-hooks.d/*
|
41
|
+
to: /etc/dhcp/dhclient-exit-hooks.d/
|
42
|
+
mode: 0755
|
43
|
+
# installer library
|
44
|
+
- from: /lib/libduck.sh
|
45
|
+
to: /lib/
|
46
|
+
- from: /lib/python-duck/duck/*
|
47
|
+
to: /lib/python-duck/duck/
|
48
|
+
# installation steps
|
49
|
+
- from: /lib/duck.d/*
|
50
|
+
to: /lib/duck.d/
|
51
|
+
mode: 0755
|
52
|
+
# hooks
|
53
|
+
- from: /lib/duck-hooks.d/*
|
54
|
+
to: /lib/duck-hooks.d/
|
55
|
+
mode: 0755
|
56
|
+
|
57
|
+
fixes:
|
58
|
+
# file contains scripts that should be run to fix the target environment.
|
59
|
+
# scripts are located under <out>/fixes
|
60
|
+
- squeeze-fix
|
61
|
+
# disable initrd generation and grub setup for installed kernels.
|
62
|
+
- kernel-boot-fix
|
63
|
+
# remove persistent udev rules.
|
64
|
+
- clear-persistent-udev
|
65
|
+
|
66
|
+
services:
|
67
|
+
- name: hostname.sh
|
68
|
+
start: '00 S'
|
69
|
+
- name: mountkernfs.sh
|
70
|
+
start: '00 S'
|
71
|
+
- name: mountdevsubfs.sh
|
72
|
+
start: '00 S'
|
73
|
+
- name: udev
|
74
|
+
start: '00 S'
|
75
|
+
- name: syslog-ng
|
76
|
+
start: '00 2 3 4 5'
|
77
|
+
stop: '00 0 1 6'
|
78
|
+
|
79
|
+
keyring:
|
80
|
+
keyserver: "subkeys.pgp.net"
|
81
|
+
keys:
|
82
|
+
# debian archive keys
|
83
|
+
- "473041FA"
|
84
|
+
- "B98321F9"
|
85
|
+
# puppetlabs
|
86
|
+
- "4BD6EC30"
|
87
|
+
# other debian keys for older archives
|
88
|
+
- "30E974EE"
|
89
|
+
- "46925553"
|
90
|
+
- "55BE302B"
|
91
|
+
- "65FFB764"
|
92
|
+
- "6D849617"
|
93
|
+
- "97BB3B58"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
if [ "$reason" != BOUND ] && [ "$reason" != RENEW ] \
|
4
|
+
&& [ "$reason" != REBIND ] && [ "$reason" != REBOOT ]
|
5
|
+
then
|
6
|
+
return
|
7
|
+
fi
|
8
|
+
|
9
|
+
hostname=$(host $new_ip_address | cut -d ' ' -f 5)
|
10
|
+
hostname=${hostname%*.}
|
11
|
+
echo $hostname > /etc/hostname
|
12
|
+
|
13
|
+
# update the hostname
|
14
|
+
hostname $hostname
|
15
|
+
|
16
|
+
# restart syslog to use the correct hostname.
|
17
|
+
invoke-rc.d syslog-ng restart
|
data/files/etc/fstab
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# empty fstab
|
data/files/etc/hostname
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
duck
|
data/files/etc/hosts
ADDED
data/files/etc/inittab
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# The default runlevel.
|
2
|
+
id:2:initdefault:
|
3
|
+
# Boot-time system configuration/initialization script.
|
4
|
+
# This is run first except when booting in emergency (-b) mode.
|
5
|
+
si::sysinit:/etc/init.d/rcS
|
6
|
+
# What to do in single-user mode.
|
7
|
+
~~:S:wait:/sbin/sulogin
|
8
|
+
|
9
|
+
l0:0:wait:/etc/init.d/rc 0
|
10
|
+
l1:1:wait:/etc/init.d/rc 1
|
11
|
+
l2:2:wait:/etc/init.d/rc 2
|
12
|
+
l6:6:wait:/etc/init.d/rc 6
|
13
|
+
# Normally not reached, but fallthrough in case of emergency.
|
14
|
+
z6:6:respawn:/sbin/sulogin
|
15
|
+
# What to do when CTRL-ALT-DEL is pressed.
|
16
|
+
ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now
|
17
|
+
# What to do when the power fails/returns.
|
18
|
+
pf::powerwait:/etc/init.d/powerfail start
|
19
|
+
pn::powerfailnow:/etc/init.d/powerfail now
|
20
|
+
po::powerokwait:/etc/init.d/powerfail stop
|
21
|
+
|
22
|
+
1:23:respawn:/sbin/agetty -n -l /sbin/duckinstall 38400 tty1
|
23
|
+
2:23:respawn:/sbin/agetty -n -l /sbin/ducklogin 38400 tty2
|
24
|
+
3:23:respawn:/sbin/agetty -n -l /sbin/ducklogin 38400 tty3
|
25
|
+
4:23:respawn:/sbin/agetty -n -l /sbin/ducklogin 38400 tty4
|
data/files/etc/mtab
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# empty mtab
|
data/files/init
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
. /lib/libduck.sh
|
3
|
+
|
4
|
+
cat - <<ENDL
|
5
|
+
_
|
6
|
+
.-' '-.
|
7
|
+
.' '.
|
8
|
+
:-._o) (o_.-:
|
9
|
+
( / \ )
|
10
|
+
'-.' '.-'
|
11
|
+
'. .'
|
12
|
+
i\ /i
|
13
|
+
. : ' : .
|
14
|
+
"\. : : ./"
|
15
|
+
\\| |//
|
16
|
+
.' : : '.
|
17
|
+
.-' : : '-.
|
18
|
+
: i .' '. i :
|
19
|
+
: : : :
|
20
|
+
: .' '. :
|
21
|
+
:/ \:
|
22
|
+
'. .'
|
23
|
+
'-._________.-'
|
24
|
+
|
25
|
+
| You are Ducked! |
|
26
|
+
|
27
|
+
ENDL
|
28
|
+
|
29
|
+
echo "Installation starting in..."
|
30
|
+
echo "3,"
|
31
|
+
sleep 1
|
32
|
+
echo "2,"
|
33
|
+
sleep 1
|
34
|
+
echo "1,"
|
35
|
+
sleep 1
|
36
|
+
echo "NOW"
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
. /lib/libduck.sh
|
3
|
+
|
4
|
+
if [[ "$DUCK_MODE" == "testing" ]]; then
|
5
|
+
warning "Skipping network configuration, duck/mode=testing"
|
6
|
+
exit 0
|
7
|
+
fi
|
8
|
+
|
9
|
+
info "network: Setting up loopback interface"
|
10
|
+
|
11
|
+
info "network: lo: address"
|
12
|
+
ip addr add 127.0.0.1/8 dev lo || true
|
13
|
+
info "network: lo: route"
|
14
|
+
ip route add 127.0.0.0/8 dev lo || true
|
15
|
+
info "network: lo: link up"
|
16
|
+
ip link set lo up
|
17
|
+
|
18
|
+
info "network: eth0: Configuring using dhcp"
|
19
|
+
|
20
|
+
if ! dhclient eth0; then
|
21
|
+
error "Network setup failed"
|
22
|
+
exit 1
|
23
|
+
fi
|
24
|
+
|
25
|
+
info "network: eth0: link up"
|
26
|
+
|
27
|
+
# Set hostname from DHCP
|
28
|
+
a_set hostname $(hostname)
|
29
|
+
|
30
|
+
exit 0
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
. /lib/libduck.sh
|
3
|
+
a_get_into target duck/target
|
4
|
+
a_get_into suite debootstrap/suite
|
5
|
+
a_get_into mirror debootstrap/mirror
|
6
|
+
|
7
|
+
if [[ ! -d $target ]]; then
|
8
|
+
error "Target does not exist: $target"
|
9
|
+
exit 1
|
10
|
+
fi
|
11
|
+
|
12
|
+
debootstrap $suite $target $mirror
|
13
|
+
|
14
|
+
mount --bind /dev $target/dev
|
15
|
+
mount -t proc none $target/proc
|
16
|
+
mount -t sysfs none $target/sys
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
. /lib/libduck.sh
|
3
|
+
a_get_into reboot_enabled "reboot/enabled" "True"
|
4
|
+
|
5
|
+
if [[ "$DUCK_MODE" == "testing" ]]; then
|
6
|
+
warning "Not rebooting, duck/mode=testing"
|
7
|
+
exit 0
|
8
|
+
fi
|
9
|
+
|
10
|
+
info "Installation done, rebooting!"
|
11
|
+
|
12
|
+
if [[ "$reboot_enabled" == "True" ]]; then
|
13
|
+
reboot
|
14
|
+
else
|
15
|
+
info "Not rebooting, reboot/enabled=$reboot_enabled"
|
16
|
+
fi
|
17
|
+
|
18
|
+
exit 0
|
@@ -0,0 +1,152 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
set -e
|
3
|
+
|
4
|
+
# static variables
|
5
|
+
export DUCK_VERSION="0.1"
|
6
|
+
export DUCKDB_CONF="/duckdb.conf"
|
7
|
+
export DUCKDB_JSON="/duckdb.json"
|
8
|
+
# if this file exists, the installation loop should not run.
|
9
|
+
export INSTALLER_STATUS="/.installer_status"
|
10
|
+
# default logging location.
|
11
|
+
export DEFAULT_LOG="/var/log/duckinstall.log"
|
12
|
+
export DUCK_LOGIN="/sbin/ducklogin"
|
13
|
+
export DUCK_HOOKS="/lib/duck-hooks.d"
|
14
|
+
export DUCK_PYTHONLIB="/lib/python-duck"
|
15
|
+
export PYTHONPATH="$DUCK_PYTHONLIB"
|
16
|
+
|
17
|
+
invoke_hook() {
|
18
|
+
name=$1
|
19
|
+
shift
|
20
|
+
path=$DUCK_HOOKS/$name
|
21
|
+
[[ -x $path ]] && ( $path "$@" || true )
|
22
|
+
}
|
23
|
+
|
24
|
+
info() {
|
25
|
+
echo "INFO : $@";
|
26
|
+
invoke_hook log info "$@"
|
27
|
+
}
|
28
|
+
|
29
|
+
warning() {
|
30
|
+
echo "WARNING : $@";
|
31
|
+
invoke_hook log warning "$@"
|
32
|
+
}
|
33
|
+
|
34
|
+
error() {
|
35
|
+
echo "ERROR : $@";
|
36
|
+
invoke_hook log error "$@"
|
37
|
+
}
|
38
|
+
|
39
|
+
setup_duckdb() {
|
40
|
+
info "duckdb: Loading Static Variables"
|
41
|
+
|
42
|
+
if [[ -f $DUCKDB_CONF ]]; then
|
43
|
+
info "duckdb: Loading $DUCKDB_CONF"
|
44
|
+
duckdb url file://$DUCKDB_CONF
|
45
|
+
fi
|
46
|
+
|
47
|
+
if [[ -f $DUCKDB_JSON ]]; then
|
48
|
+
info "duckdb: Loading $DUCKDB_JSON"
|
49
|
+
duckdb url --json file://$DUCKDB_JSON
|
50
|
+
fi
|
51
|
+
|
52
|
+
info "duckdb: Loading /proc/cmdline"
|
53
|
+
|
54
|
+
if ! duckdb url --cmdline file:///proc/cmdline; then
|
55
|
+
error "duckdb: Failed to load kernel arguments"
|
56
|
+
return 1
|
57
|
+
fi
|
58
|
+
|
59
|
+
# Time to enable hooks.
|
60
|
+
duckdb set --json duck/hooks-enabled true
|
61
|
+
duckdb set --json duck/log-hook-enabled true
|
62
|
+
}
|
63
|
+
|
64
|
+
run_installer() {
|
65
|
+
if ! setup_duckdb; then
|
66
|
+
return 1
|
67
|
+
fi
|
68
|
+
|
69
|
+
for script in /lib/duck.d/[0-9][0-9]-*; do
|
70
|
+
[[ ! -x $script ]] && continue
|
71
|
+
|
72
|
+
info "Running: $script"
|
73
|
+
logger -t installer "running: $script"
|
74
|
+
|
75
|
+
if ! $script; then
|
76
|
+
error "Failed: $script"
|
77
|
+
return 1
|
78
|
+
fi
|
79
|
+
done
|
80
|
+
|
81
|
+
return 0
|
82
|
+
}
|
83
|
+
|
84
|
+
# Run a command in the target environment.
|
85
|
+
# required duckdb variables:
|
86
|
+
# - duck/target
|
87
|
+
in_target() {
|
88
|
+
# run chroot invocation inside of a subshell
|
89
|
+
# this allows us to override some useful environment variables
|
90
|
+
# at leisure.
|
91
|
+
|
92
|
+
a_get_into target duck/target
|
93
|
+
|
94
|
+
command="$@"
|
95
|
+
|
96
|
+
info "in-target: $command"
|
97
|
+
|
98
|
+
(
|
99
|
+
export DEBIAN_FRONTEND=noninteractive
|
100
|
+
export DEBCONF_NONINTERACTIVE_SEEN=true
|
101
|
+
export LC_ALL=C
|
102
|
+
export LANGUAGE=C
|
103
|
+
export LANG=C
|
104
|
+
exec chroot $target $command
|
105
|
+
)
|
106
|
+
|
107
|
+
return $?
|
108
|
+
}
|
109
|
+
|
110
|
+
|
111
|
+
# get single duckdb variable
|
112
|
+
# exports the RET variable containing the value of the requested variable
|
113
|
+
# or invokes 'exit 1' if it was unable to fetch the value from duckdb.
|
114
|
+
#
|
115
|
+
# a_get duck/mode
|
116
|
+
# duck_mode="$RET"
|
117
|
+
#
|
118
|
+
# duckdb supprts the notion of default values, in that case, two arguments
|
119
|
+
# should be provided, as follows.
|
120
|
+
#
|
121
|
+
# a_get duck/mode testing
|
122
|
+
# duck_mode="$RET"
|
123
|
+
a_get() {
|
124
|
+
export DUCK_RETURN=""
|
125
|
+
export DUCK_OK="no"
|
126
|
+
|
127
|
+
eval $(duckdb get --sh "$@")
|
128
|
+
|
129
|
+
if [[ "$DUCK_OK" != "yes" ]]; then
|
130
|
+
error "Missing required duckdb variable: $1"
|
131
|
+
exit 1
|
132
|
+
fi
|
133
|
+
|
134
|
+
export RET=$DUCK_RETURN
|
135
|
+
}
|
136
|
+
|
137
|
+
# This function was introduced because the common idiom of assigning RET
|
138
|
+
# resulted in code which was error prone.
|
139
|
+
a_get_into() {
|
140
|
+
name=$1
|
141
|
+
shift
|
142
|
+
a_get "$@"
|
143
|
+
export "$name"="$RET"
|
144
|
+
}
|
145
|
+
|
146
|
+
# set single duckdb variable
|
147
|
+
a_set() {
|
148
|
+
eval $(duckdb set "$@");
|
149
|
+
}
|
150
|
+
|
151
|
+
# Dynamic Variables
|
152
|
+
a_get_into DUCK_MODE duck/mode "testing"
|