Summary
Over the summer of 2019 I worked on the libvirt project as a part of Google Summer of Code. My proposal involved the introduction of cloud-init on virt-manager/virt-install. Cloud-init is a package that contains utilities for early initialization of cloud instances. The idea behind my proposal was to use cloud-init for injecting multiple user-data configuration options during the first steps of cloud image installations, making this whole process more automated through specific command line arguments when using virt-install.
To start understanding the code a little more, I also worked on side patches for virt-install command line arguments, either adding options to existing features or introducing new ones, according to the libvirt domain attributes documentation.
Project progress
With my mentors we agreed that the first step was to inject a bare –cloud-init cli option in the existing image installation process, and start morphing it from there on.
The following cloud-init options are now available:
–cloud-init
root-password-generate=yes|no
root-password-file=/path/to/file
disable=yes|no
ssh-key=/path/to/key
In all cases, the default username is root.
The first few patches introduced the bare –cloud-init option, which creates a user named root and generates a random password for first login. Password expires immediatedly and the user is forced to set a new one. The bare cloud-init argument also defaults to disable cloud-init service after first boot.
The disable option, as mentioned above, if set true, exits cloud-init service after first login, and remains inactive afterwards. It doesn’t remove it completely though, that is left to the user to decide upon.
The root-password-generate option generates a 16digit password containing alphanumeric characters, which is set to expire after first login, so the user is forced to change it immediately after.
After a while I added the root-password-file option, which takes as input the path of a file containing a password set by the user.
The last password related option, ssh-key, gives the ability to log using an ssh key pair, by providing the path of the public key. Login is then available by ssh root@vm_ip_address.
For each of these options, cloud-init code creates two files: the meta-data and user-data file.
The meta-data file is empty for now, but in future implementations can contain the hostname and instance-id of the cloud instance and more configuration options, as described in the cloud-init documentation.
The user-data file is the file that contains all the user set configuration information. It was decided to be in YAML format, and can contain both dictionary values (as used for the password declaration and expiration) as well as shell commands (used for the disable option, for example).
Both files are combined in an iso image, using the genisoimage tool. It was already used by the virt-install code, so a small adjustment was needed to use it with the right flags in case if a cloud-image installation. The config.iso is injected during the installation, thus configuring the cloud image selected before first login.
The created files are stored in a temporary directory and cleaned up after being used by genisoimage. The created iso is also deleted after the installation. The whole process is being logged, and the contents of the meta-data and user-data files are printed to the console.
At last, for all options mentioned above, basic testing was introduced as well.
Issues that came up
When discussing the cloud-init option default behavior, we were wondering about the default username set for login. After a bit of research, I found out that all cloud distributions have a default username set, which usually is the distribution’s name (very few have also a default password, like CirrOS). We decided that we should avoid leaving the default username set by each distribution and create a user named root on all cases, to initially have a distro-agnostic behavior of the cloud-init argument, which can later be handled differently per distro by using libosinfo.
We also discussed upon the password options. We wanted to avoid having a password given directly through the command line, which was solved by the root-password-file option. There was the issue of the logs, as well as the console, were the user-data file containing the password was printed. We decided to scrub the password from both. Only the generated random password is printed in the console, with a 10 second timeout which can be bypassed by pressing Enter. The reason for this is to alert the user for the password generation, by pausing the installation long enough to be noticeable that the password is printed and be able to use it to login.
Conclusion
During GSoC 2019 I managed to introduce some basic options for cloud-init configuration in virt-install. The whole process required a lot of research and tryouts, to understand the logic connecting the two and the formats that would work on each case. There are still many options that will enrich the configuration during cloud image installations, and a lot of discussion on the way this is going to be implemented and integrated to the existing code, and there still is the need to add this feature to virt-manager and have the process be done using the GUI as well.
List of cloud-init commits:
https://github.com/virt-manager/virt-manager/commits/cloudinit
The link contains commits on the cloud-init branch on virt-manager/virt-install official repository, which is going to be merged soon. The related commits are issued with the “cloudinit” title preffix.
List of virt-install commits:
https://github.com/virt-manager/virt-manager/commits?author=AthinaPl
The link contains all the commits that I issued during the GSoC period for virt-install.