-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Masahiro Fujiwara
committed
Nov 11, 2015
1 parent
f77b6b3
commit 532de19
Showing
20 changed files
with
682 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
packer/ | ||
packer_cache/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# Building Image | ||
|
||
Run the ``build.sh`` with target OS name that you want. | ||
|
||
``` | ||
$ ./build.sh centos-7.1-x86_64 | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
# qemu-build | ||
|
||
``qemu-build`` is an image building script inspired by packer-qemu driver. | ||
This program run the following tasks. Similar to ``packer`` but it is more simplified. | ||
|
||
1. Download iso image from remote site. | ||
2. Run ``qemu`` with the .iso and FD image and boot installer from the .iso. | ||
3. Send boot command to console then the unattended install is kicked. | ||
Configuration files for the installer are supplied from FD image. | ||
4. Shutdown ``qemu`` from guest once all done. | ||
|
||
## How to use | ||
|
||
Basic usage: | ||
|
||
``` | ||
% qemu-build build.conf | ||
``` | ||
|
||
``build.conf`` has set of shell variables to build new OS image from iso installer. | ||
|
||
``` | ||
target_image=centos7.img | ||
kickstart_file="ks.cfg" | ||
iso_checksum="d07ab3e615c66a8b2e9a50f4852e6a77" | ||
iso_urls=( | ||
http://ftp.riken.jp/Linux/centos/7.1.1503/isos/x86_64/CentOS-7-x86_64-Minimal-1503-01.iso | ||
) | ||
# "<tab>text<space>ks=hd:fd0:/ks.cfg" | ||
boot_commands=(tab t e x t spc k s equal h d shift-semicolon f d 0 shift-semicolon slash k s dot c f g ret) | ||
qemu_args="-m 1G" | ||
post_scripts=(./post-scripts/*.sh) | ||
``` | ||
|
||
``` | ||
# yum install -y $(qemu-build --show-deps) | ||
``` | ||
|
||
## Config Parameters | ||
|
||
Path information is calculated from the location of config file. | ||
|
||
Required: | ||
|
||
``iso_checksum`` | ||
|
||
``iso_urls`` is shell array to supply the list of OS installer image file on remote site. It continues to | ||
try next urls until fetching succeeds. | ||
|
||
``install_iso`` is path string to the installer image which you already have. ``iso_urls`` is skipped if this | ||
parameter is set. | ||
|
||
``target_image`` the path to image file to generate. | ||
|
||
Optional: | ||
|
||
``kickstart_file`` the file is copied to FD image. | ||
|
||
``boot_commands`` are sent to qemu guest over ``sendkey`` monitor interface while the OS installer prompts | ||
and waits for typing keys. ``sendkey`` emulates keyboard so it can only pass one character at a time. See | ||
the sendkey character list pasted from ``qemu``. | ||
|
||
``qemu_args`` extra command options for ``qemu`` if you need. | ||
|
||
``qemu_binary`` path to ``qemu`` binary. | ||
|
||
``post_scripts`` an array of script path(s) to run at post stage in qemu guest. The files are just copied | ||
to FD image. unattended installation must be organized to call them. | ||
|
||
``local_scripts`` an array of command line which run at qemu host. They are called after sending ``boot_commands`` | ||
so helps to handle post process on host side until the installation completes. | ||
|
||
|
||
### Local Script | ||
|
||
Bundled local scripts: | ||
|
||
``screen-watch`` monitors qemu screen updates. It supports | ||
to detect if updates happens within a period time and kill | ||
qemu if the installation process is likely to be stopped. | ||
|
||
``alt-b`` is just sends alt-b key sequence to qemu. It is | ||
useful to signal CentOS graphical installer to proceed. | ||
|
||
|
||
### ``sendkey`` character table | ||
|
||
|
||
``` | ||
# discover the supported keys by doing: | ||
# telnet 127.0.0.1 4567 | ||
# sendkey <tab> | ||
# Here is the result: | ||
(qemu) sendkey | ||
0 1 2 3 4 | ||
5 6 7 8 9 | ||
a again alt alt_r altgr | ||
altgr_r apostrophe asterisk b backslash | ||
backspace bracket_left bracket_right c caps_lock | ||
comma compose copy ctrl ctrl_r | ||
cut d delete dot down | ||
e end equal esc f | ||
f1 f10 f11 f12 f2 | ||
f3 f4 f5 f6 f7 | ||
f8 f9 find front g | ||
grave_accent h help home i | ||
insert j k kp_0 kp_1 | ||
kp_2 kp_3 kp_4 kp_5 kp_6 | ||
kp_7 kp_8 kp_9 kp_add kp_decimal | ||
kp_divide kp_enter kp_multiply kp_subtract l | ||
left less lf m menu | ||
meta_l meta_r minus n num_lock | ||
o open p paste pause | ||
pgdn pgup print props q | ||
r ret right s scroll_lock | ||
semicolon shift shift_r slash spc | ||
stop sysrq t tab u | ||
undo unmapped up v w | ||
x y z | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#!/bin/bash | ||
|
||
# NOTE: Sometimes all the keys above are typed OK and the ks.cfg file | ||
# is read in OK, but the installation does not start until the user | ||
# clicks on the "Begin" button. One possible cause could be the VNC | ||
# windows being open and some UI events being sent to the graphical | ||
# installer, which senses the human there and politely asks for | ||
# confirmation. | ||
|
||
# Update: Nope. Did not work even with no vncviewer connected. Looks like | ||
# alt-B will select that button. Seems to take at least 20 seconds to get | ||
# to that screen so.... | ||
|
||
if [[ $# -eq 1 ]]; | ||
sleep $1 | ||
else | ||
sleep 60 | ||
fi | ||
|
||
echo sendkey alt-b | nc 127.0.0.1 4567 | ||
|
||
echo | ||
echo "Just sent an extra alt-b just in case" | ||
echo "it is stuck on the confirm install screen" | ||
echo | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
#!/bin/bash | ||
|
||
set -e -o pipefail | ||
|
||
# Environment variables | ||
ISO_CACHE_DIR=${ISO_CACHE_DIR:-"."} | ||
|
||
# Configuration parameters in .conf. | ||
install_iso= | ||
kickstart_file= | ||
target_image= | ||
qemu_binary="qemu-kvm" | ||
iso_checksum_type="md5" | ||
iso_checksum= | ||
declare -a iso_urls=() | ||
declare -a boot_commands= | ||
declare -a post_scripts=() | ||
declare -a local_scripts=() | ||
|
||
# option parameters | ||
is_overwrite_image= | ||
|
||
reportfailed() | ||
{ | ||
echo "Script failed...exiting. ($*)" 1>&2 | ||
exit 255 | ||
} | ||
|
||
usage_deps() { | ||
cat <<END | ||
qemu-img qemu-kvm mtools dosfstools nc curl | ||
END | ||
} | ||
|
||
usage() { | ||
cat <<END | ||
$(basename $0) [options] <conf> | ||
Options: | ||
--force,-f : Overwrite existing image file. | ||
Install dependencies: | ||
yum install -y \$($0 --show-deps) | ||
END | ||
} | ||
|
||
while [[ $# -gt 0 ]]; do | ||
case $1 in | ||
--help|-h) | ||
usage | ||
exit | ||
;; | ||
--show-deps) | ||
usage_deps | ||
exit | ||
;; | ||
--force|-f) | ||
is_overwrite_image=1 | ||
shift | ||
;; | ||
*) | ||
break | ||
;; | ||
esac | ||
done | ||
|
||
# Load .conf | ||
if [[ $# -eq 1 && -f $1 ]]; then | ||
CONF_PATH=$1 | ||
shopt -s nullglob | ||
. $CONF_PATH | ||
shopt -u nullglob | ||
else | ||
reportfailed "Unknown conf path: $1" | ||
fi | ||
|
||
cd $(dirname $CONF_PATH) | ||
|
||
# Minimal parameter checking to catch typos: | ||
if [[ -z $install_iso ]]; then | ||
[[ -n $iso_checksum ]] || reportfailed "iso_checksum not found." | ||
[[ -n $iso_checksum_type ]] || reportfailed "iso_checksum_type not found." | ||
|
||
if [[ -f "${ISO_CACHE_DIR}/${iso_checksum}.iso" ]]; then | ||
install_iso="${ISO_CACHE_DIR}/${iso_checksum}.iso" | ||
else | ||
for u in ${iso_urls[@]} | ||
do | ||
curl --show-error -L -o "${ISO_CACHE_DIR}/${iso_checksum}.iso" "$u" | ||
if [[ $? -eq 0 ]]; then | ||
sum_val=$("${iso_checksum_type}sum" "${ISO_CACHE_DIR}/${iso_checksum}.iso" | cut -f 1 -d ' ') | ||
if [[ "${sum_val}" == "${iso_checksum}" ]]; then | ||
install_iso="${ISO_CACHE_DIR}/${iso_checksum}.iso" | ||
break | ||
else | ||
rm -f "${ISO_CACHE_DIR}/${iso_checksum}.iso" | ||
fi | ||
fi | ||
done | ||
fi | ||
fi | ||
[ -f "$install_iso" ] || reportfailed "Iso ($install_iso) not found." | ||
|
||
[ -f "$kickstart_file" ] || reportfailed " ($kickstart_file) not found." | ||
|
||
if [[ -z "$is_overwrite_image" ]]; then | ||
[ -f "$target_image" ] && reportfailed "$target_image already exists" | ||
fi | ||
|
||
# Make sure it is writable | ||
touch "$target_image" || reportfailed "Could not create '$target_image' (the third parameter)" | ||
|
||
TARGET_DIR="$(cd "$(dirname "$(readlink -f "$target_dir")")" && pwd -P)" || reportfailed | ||
|
||
WORK_DIR=$(mktemp -d) | ||
trap "rm -rf $WORK_DIR" EXIT | ||
|
||
# Variables can be referenced from child processes. | ||
export WORK_DIR CONF_PATH TARGET_DIR KVM_PID | ||
|
||
( | ||
rm -f "$target_image" | ||
qemu-img create -f qcow2 "$target_image" 10000M | ||
) || reportfailed "Problem while creating empty qcow2 image" | ||
|
||
KSFPY="$WORK_DIR/kickstart_floppy.img" | ||
|
||
( | ||
dd if=/dev/zero of="$KSFPY" count=1440 bs=1k | ||
/sbin/mkfs.msdos "$KSFPY" | ||
if [[ -f $kickstart_file ]]; then | ||
mcopy -i "$KSFPY" "$kickstart_file" ::/ks.cfg | ||
fi | ||
if [[ ${#post_scripts} -gt 0 ]]; then | ||
for src in ${post_scripts[@]} | ||
do | ||
mcopy -i "$KSFPY" "$src" ::/$(basename $src) | ||
done | ||
fi | ||
mdir -i "$KSFPY" | ||
) || reportfailed "Problem while creating floppy with kickstart file" | ||
|
||
|
||
kvmcmdline=( | ||
$qemu_binary | ||
-name ksvm | ||
|
||
-fda "$KSFPY" | ||
-drive "file=$target_image,if=virtio,cache=writeback,discard=ignore" | ||
|
||
-machine type=pc,accel=kvm | ||
|
||
-netdev user,id=user.0,hostfwd=tcp::2224-:22 | ||
-device virtio-net,netdev=user.0 | ||
-monitor telnet:0.0.0.0:4567,server,nowait | ||
-vnc 0.0.0.0:47 | ||
$qemu_args | ||
) | ||
|
||
#echo "${kvmcmdline[@]}" >runscript.sh | ||
#chmod +x runscript.sh | ||
|
||
echo "${kvmcmdline[@]}" -boot once=d -cdrom "$install_iso" | ||
if ! type $qemu_binary > /dev/null 2>&1; then | ||
reportfailed "Not found $qemu_binary" | ||
fi | ||
"${kvmcmdline[@]}" -boot once=d -cdrom "$install_iso" >"$WORK_DIR/kvm.stdout" 2>"$WORK_DIR/kvm.stderr" & | ||
KVM_PID=$! | ||
echo "$KVM_PID" >"$WORK_DIR/kvm.pid" | ||
echo "Qemu launched ($KVM_PID)" | ||
|
||
sleep 15 | ||
|
||
if [[ ${#boot_commands} -gt 0 ]]; then | ||
echo "Sending boot command..." | ||
echo ${boot_commands[@]} | ||
for k in ${boot_commands[@]} | ||
do | ||
echo sendkey $k | ||
done | nc 127.0.0.1 4567 > $WORK_DIR/boot_command.log | ||
fi | ||
|
||
if [[ ${#local_scripts} -gt 0 ]]; then | ||
for i in "${local_scripts[@]}" | ||
do | ||
echo "Local script: $i" | ||
$i | ||
done | ||
fi | ||
|
||
echo "Now waiting for kvm to exit. (FYI, ^c will kill KVM)" | ||
wait |
Oops, something went wrong.