How to fully automate unattended virt-install?
Asked Answered
D

2

8

Let me start by saying what I want to do. I'd like to fully automate, in an unattended way, the building of QEMU/KVM VM images using virt-install. I know that some folks use the GUI tool to do this, or they edit a pre-existing image's XML description, but I want to start from scratch.

I've Googled around and examples of doing this are hard to find. What I have found is that virt-install is the command to use, and that it can be used interactively with a TTY console attached (you manually answer configuration questions during the install). For a fully automated solution, you can specify a kickstart file (typically preseed.cfg) to provide answers to questions that you'd normally enter manually. The kickstart file can also specify additional software to install, disk and network configuration, etc.).

I think I've got this mostly working except that the installation hangs shortly after install begins. I think it has something to do with the need (or not) to have a console attached to the install. Here is the virt-install command I am using:

virt-install --connect qemu:///system \
  --name vm --ram 128 \
  --disk path=./vm.qcow2,size=8,format=qcow2 \
  --location 'http://archive.ubuntu.com/ubuntu/dists/trusty/main/installer-amd64/' \
  --network user,model=virtio \
  --initrd-inject preseed.cfg \
  --extra-args="console=tty0 console=ttyS0,115200"

This is the preseed.cfg file (which I cribbed from many examples on the web and in the Ubuntu documentation):

### Localization
# Locale sets language and country.
d-i debian-installer/locale string en_US
# Keyboard selection.
d-i keyboard-configuration/layoutcode string us
d-i keyboard-configuration/modelcode string pc105
d-i keyboard-configuration/variantcode string

### Network configuration
# netcfg will choose an interface that has link if possible. This makes it
# skip displaying a list if there is more than one interface.
d-i netcfg/choose_interface select auto
# Any hostname and domain names assigned from dhcp take precedence over
# values set here. However, setting the values still prevents the questions
# from being shown, even if values come from dhcp.
d-i netcfg/get_hostname string vm
d-i netcfg/get_domain string foobar.net
# Disable that annoying WEP key dialog.
d-i netcfg/wireless_wep string

### Mirror settings
d-i mirror/country string manual
d-i mirror/http/hostname string us.archive.ubuntu.com
d-i mirror/http/directory string /ubuntu
d-i mirror/http/proxy string

### Partitioning
# Encrypt your home directory?
d-i user-setup/encrypt-home boolean false
# Alternatively, you can specify a disk to partition. The device name
# can be given in either devfs or traditional non-devfs format.
d-i partman-auto/disk string /dev/vda
# In addition, you'll need to specify the method to use.
# The presently available methods are: "regular", "lvm" and "crypto"
d-i partman-auto/method string regular
# You can choose from any of the predefined partitioning recipes.
d-i partman-auto/choose_recipe select atomic
# This makes partman automatically partition without confirmation, provided
# that you told it what to do using one of the methods above.
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true

### Clock and time zone setup
# Controls whether or not the hardware clock is set to UTC.
d-i clock-setup/utc boolean true
# You may set this to any valid setting for $TZ; see the contents of
# /usr/share/zoneinfo/ for valid values.
d-i time/zone string UTC

### Account setup
# Skip creation of a root account (normal user account will be able to
# use sudo).
d-i passwd/root-login boolean false

# To create a normal user account.
d-i passwd/user-fullname string VMuser
d-i passwd/username string vmuser
# Normal user's password, either in clear text
# or encrypted using an MD5 hash.
d-i passwd/user-password-crypted password CRACKMECRACKM

# This is fairly safe to set, it makes grub install automatically to the MBR
# if no other operating system is detected on the machine.
d-i grub-installer/only_debian boolean true

### Package selection
d-i tasksel/first multiselect standard
# Individual additional packages to install
d-i pkgsel/include string openssh-server

### Finishing up the first stage install
# Avoid that last message about the install being complete.
d-i finish-install/reboot_in_progress note
# How do you want to manage upgrades on this system?
d-i pkgsel/update-policy select none

After all that, when I execute the virt-install command I see:

WARNING  Unable to connect to graphical console: virt-viewer not installed. Please install the 'virt-viewer' package.
WARNING  No console to launch for the guest, defaulting to --wait -1

Starting install...
Retrieving file linux...                                                                                
Retrieving file initrd.gz...                                                                            
Allocating 'virtinst-linux.rCdX0h'                                                                      
Transferring virtinst-linux.rCdX0h                                                                      
Allocating 'virtinst-initrd.gz.BbRBMv'                                                                  
Transferring virtinst-initrd.gz.BbRBMv                                                                  
Creating domain...                                                                                      
Domain installation still in progress. Waiting for installation to complete.

and it just hangs. If I ^Z into the background and start virsh I see the vm in a running state.

I think I'm close, but need to fix it so that:

  1. Install shows complete and virt-install returns to shell.
  2. The new VM is shutdown and I'm left with the image file ready to go.

I think #2 can be accomplished in the preseed.cfg file with some kind of cleanup instructions (still researching this), but any help of fixing #1 would be greatly appreciated.

Derr answered 4/10, 2016 at 20:57 Comment(5)
Hi, have you finally solved your issue? I think I am experiencing kind of same trouble...Otiose
@HadrienTOMA I never did get it figured out and decided to use Packer to do my automated VM builds. It works well (fully unattended), seems to be well supported, and will build VM images for a number of platforms in addition to QEMU (e.g. AWS-AMI, VirtualBox, etc.).Derr
Alright, thank you for mentioning Packer, I will try it!Otiose
@HadrienTOMA This repo may also help you get started building VMs for QEMU with Packer. I found it very useful.Derr
Great, thank you very much!Otiose
S
6

To have virt-install use a Kickstart file to initialize an operating system, you need to pass the ks= argument to the kernel by specifying it via the --extra-args parameter:

--initrd-inject preseed.cfg \
--extra-args="ks=file:/preseed.cfg console=tty0 console=ttyS0,115200"

The above example injects a local Kickstart file onto the guest operating system, to be used for automated installation.

You can also specify ks via HTTP:

--extra-args="ks=http://192.168.1.1/preseed.cfg"

or FTP:

--extra-args="ks=ftp://192.168.1.1/preseed.cfg"

or NFS:

--extra-args="ks=nfs:192.168.1.1:/preseed.cfg"
Smyth answered 28/7, 2017 at 4:0 Comment(0)
C
0

I just want to add another use-case that may be helpful for a similar goal (as raised in your question).

If you have an existing disk image with everything already installed (you might have created this before, or cloned it from an existing KVM guest), stored in /var/lib/libvirt/images/debian10.qcow2, you can automate the creation of a new KVM virtual machine by importing that image with virt-install and its options --noautoconsole, e.g.,

virt-install --virt-type kvm --name debian10 --disk /var/lib/libvirt/images/debian10.qcow2 --import --os-variant debian10 --vcpus 1 --memory 1024 --noautoconsole

The domain (or the virtual machine) named debian10 will be created without asking for any interaction, virt-install will exit quickly as mentioned in its manual

--noautoconsole: Don't automatically try to connect to the guest console...
Note, virt-install exits quickly when this option is specified...

Since you have the image with everything already installed, the termination of virt-install causes no problem, rather a desired behaviour in this case.

Coloratura answered 16/3, 2023 at 23:42 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.