Introduction
This blog post describes one option for automating the build of a KVM guest.
There are alternative ways to automate the build but the method that is described here uses the ability to pass a kickstart file to the virt-install command when creating a new VM. Kickstart is a file contains the answers to all the normal questions that an interactive installer would ask during installation. The kickstart script installs software packages, configures SELinux, auditd, rsyslog etc.
Using virt-install with a kickstart file
The virt-install command is used to create new virtual machines / guests; it supports a
1
|
--initrd-inject
|
parameter allows you specify the path to an Anaconda Kickstart file.
An example virt-install command is provided below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
virt-install --connect=qemu:///system \
--name ${GUEST} \
--description "${GUEST_DESC}" \
--os-type=Linux \
--os-variant=rhel7 \
--ram=${GUEST_RAM} \
--vcpus=${GUEST_CPU} \
--check-cpu \
--autostart \
--memballoon virtio \
--network ${NETWORK} \
--location "$ISO_DIR/$CENTOS_7_MIN_ISO" \
--disk "$VHD_DIR/$GUEST-osdisk.img,size=$os_disk_size" \
--nographics \
--initrd-inject=/root/scripts/centos-7-min.ks \
--extra-args="ks=file:/centos-7-min.ks \
console=tty0 console=ttyS0,115200" \
--noautoconsole
|
The key parameters as it pertains to automating the install are:
- The
1--initrd-inject
parameter specifies the path to the kickstart file on the host machine - The
1--extra-args
parameter then specifies where the kickstart file is on the VM. - The
1--noautoconsole
parameter specifies to not enter into a console – which is the default behaviour. The reason we disable this is because if we enter into a console it requires manual intervention to exit from the console after the kickstart installation completes in order to continue with the rest of the script for building a encrypted VM.
The Kickstart file
-
1text
specifies that a text based installation should be performed -
1shutdown
specifies that the VM should be shutdown after the kickstart installation completes – this is important as we use this to detect when the installation and configuration is complete before we move on to encrypting the VM operating system disk. -
1url --url=http://mirror.centos.org/centos/7/os/x86_64/ --proxy http://192.168.0.20:8080/
specifies the URL for the package repository and that it can be reached via the proxy 192.168.0.20 (if you have direct internet access then this line is not required, also if you are using an internal repo then the URL should be modified accordingly) -
1repo --name=epel --baseurl=http://download.fedoraproject.org/pub/epel/7/x86_64/ --proxy http://192.168.0.20:8080
specifies the location of an additional repo, in this case, the EPEL repo and that it can be accessed via the proxy - The line below sets the password for the root user
1rootpw --iscrypted $6$EaWILovy2GSnzYpr$jqFnyZn89hahnsdfh89y80gan08f90a78hhb. - It is stored in hashed form you can generate this by running the command below:
-
1echo 'import crypt,getpass; print crypt.crypt(getpass.getpass(), "$6$16_CHARACTER_SALT_HERE")' | python -
There was also a requirement to configure auditing and logging. Some of these files were quite long and so it was too unweildly to simply hardcode the entire contents of the files into the kickstart file and using heredocs to write them out to a file on the guest. In light of this I used base64 encoding and gunzip to encode the file.
The Kickstart file includes blocks of code such as the example below:
1
2
3
4
5
|
echo 'H4sIANJpLVgAA61WX3MaNxB/7n2Kjek0qSd3GP+B1kkzQwA71Nh0wG6baTseodMdKjrpKumwmclD
3/st+0m60gHG4LSB5h7gTtr9aX+7q92tPKuOuKyOiBkHlc/8BBU4PKjVawcHDbjgejT7/CdAgIdc
LCQcPeMsR+/hERt+p7mLc5VZWp0fGVF0/uZKlGt2G49v5zYGlFg0Z0Pv9etO/8xfHbjst296nSH4
vVb/tt45PDipHTVPDusn9cZDGXHZY8tfV03gA44xsfLJZw/9GAHh5XKQOzmpHYeW5iGOc5gxWFKw
gUHInxSI8txPZ58/s9YRXa8tzApAubDcD0XwD3/sBlN2DQAA' | base64 -d | gunzip > configure-rsyslog.sh
|
This command decodes a base64 encoded string and then decompresses it and dumps it to a file; the string contains the code for a shell script. This is a convenient way to included scripts without including the entire code using heredocs.
To create the base64 encoded and compressed script enter the script as is into a file, then run the command:
1
|
cat audisp-install.sh | gzip | base64 > test.sh
|
Detecting completion of the kickstart script
After the virt-install
command is run the virtual machine build script virt-create-guest.sh script waits for the VM to enter the shutdown state (recall that the kickstart file specified that the machine should be shutdown after installation) it does this using the following snippet by running
virsh domstate <guest vm name> and check if it returns “shut off”.