Vendor Image conversion
The cloud service uses RAW images for all the VMs hosted. If you upload any other different image type like QCOW2 or VMDK, it will be converted to RAW when the machine gets started the first time, or when it gets deployed to a volume that's also in RAW format.
All the servers of the cloud service are running KVM as hypervisor technology. In some scenarios, specially with providers, you may have an image prepared to be run on a different hypervisor like Microsoft HyperV, Xen, Oracle VirtualBox, VMware ESXi or VMware Workstation. In those cases, although the image data could be converted, it may not contain the drivers that allow it to boot or access the network. The direct result is that the machine may not boot or not have access to the network.
This procedure shows how to convert those images and inject the KVM drivers, also called virtio, inside the VM, so it can be used later as an image.
Let's use as an example that we have a vendor image called vendor.vmdk that we want to convert to be able to use it on the cloud service.
The procedure would be the following:
- Convert the image to QCOW2
- Upload the image to the cloud service
- Create a volume based on that image so we can edit it
- Create a helper VM to allow us to inject the drivers
- Attach the volume into the helper VM
- Inject virtio drivers into the volume using the helper VM
- Detach volume from helper VM
- Create image based on volume
- Cleanup
At the end, you would have an image with the proper drivers that you can use to boot additional machines.
Convert the image to compressed qcow2
With the image downloaded into aiadm
or lxplus
you can just convert the image before upload like this:
Upload the image to the cloud service
You can upload the image to the OpenStack Glance image service. Please ensure than the minimum disk size has been set as the one specified in the command like:
openstack image create --min-disk 100 --file vendor.qcow2 --disk-format qcow2 --property architecture='x86_64' --property hw_architecture='x86_64' --progress vendor_original
On our example the min-disk value is set to 100GB and the architecture of the image is x86_64.
Create a volume using that image
Once the image is uploaded, you need to create a volume using that image as a source. You can do it with the below command:
Warning
Please make sure that the size of the disk matches with the min-disk size.
This process may take a bit as it needs to copy the image data into the volume.
Create a helper VM
In order to inject the drivers, you need a helper VM. In this procedure we are using an alma9 x86_64 VM and using an already existing keypair to connect to the VM.
openstack server create --image 'ALMA9 - x86_64' --flavor m2.small --key-name mykeypair vendorhelperVM
Attach the volume into the helper VM
Once the machine has started, you need to attach the volume to the VM. You can do this with:
Inject drivers into the volume
Once you have connected to the machine as root using your keypair, you can see that there is an additional disk on it
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
vda 252:0 0 20G 0 disk
├─vda1 252:1 0 19.5G 0 part /
├─vda14 252:14 0 4M 0 part
└─vda15 252:15 0 545M 0 part /boot/efi
vdb 252:32 0 100G 0 disk
├─vdb1 252:33 0 1G 0 part
└─vdb2 252:34 0 99G 0 part
We should install lvm2
into the helper machine that will help us to identify the boot and root partitions
We can try to scan for LVM volumes, find the mountpoints and then enable them like this:
$ vgscan
Found volume group "centos" using metadata type lvm2
$ lvdisplay | grep Path
LV Path /dev/centos/swap
LV Path /dev/centos/home
LV Path /dev/centos/root
$ vgchange -ay centos
So, it seems that in this particular case we have the following partition layout:
Once you've identified the partitions, we just need /boot and /root to install the drivers. We can mount them into the machine and then bind-mount your system paths into the root volume's mount point like this:
mkdir /mnt/root
mount /dev/centos/root /mnt/root
mount /dev/vdb1 /mnt/root/boot
for x in sys proc run dev tmp; do mount --bind /$x /mnt/root/$x; done
Now we can use dracut to update the initrd file. First we need to chroot and find the version of the kernel:
$ cd /mnt
$ chroot root bash
$ grep initramfs- /boot/grub2/grub.cfg
initrd16 /initramfs-3.10.0-1160.36.2.el7.x86_64.img
initrd16 /initramfs-3.10.0-1127.el7.x86_64.img
initrd16 /initramfs-3.10.0-957.21.3.el7.x86_64.img
initrd16 /initramfs-3.10.0-862.el7.x86_64.img
initrd16 /initramfs-0-rescue-c582f3834dad4ee4819cb4ee1aa446aa.img
$ ls /boot/initramfs-* -l
-rw-------. 1 root root 64100034 Jul 31 2019 /boot/initramfs-0-rescue-c582f3834dad4ee4819cb4ee1aa446aa.img
-rw-------. 1 root root 21417154 Aug 26 2021 /boot/initramfs-3.10.0-1127.el7.x86_64.img
-rw-------. 1 root root 13915816 Aug 26 2021 /boot/initramfs-3.10.0-1127.el7.x86_64kdump.img
-rw-------. 1 root root 21422539 Aug 26 2021 /boot/initramfs-3.10.0-1160.36.2.el7.x86_64.img
-rw-------. 1 root root 13919120 Sep 9 2021 /boot/initramfs-3.10.0-1160.36.2.el7.x86_64kdump.img
-rw-------. 1 root root 21322813 Jul 31 2019 /boot/initramfs-3.10.0-862.el7.x86_64.img
-rw-------. 1 root root 13534097 Jul 31 2019 /boot/initramfs-3.10.0-862.el7.x86_64kdump.img
-rw-------. 1 root root 20976832 Apr 30 2020 /boot/initramfs-3.10.0-957.21.3.el7.x86_64.img
-rw-------. 1 root root 13551551 Apr 30 2020 /boot/initramfs-3.10.0-957.21.3.el7.x86_64kdump.img
In our case it's the most recent version in that list, so we can just inject the drivers in there:
dracut -f /boot/initramfs-3.10.0-1160.36.2.el7.x86_64.img 3.10.0-1160.36.2.el7.x86_64 --add-drivers "virtio virtio_pci virtio_blk virtio_net"
And check that they were injected properly:
$ lsinitrd /boot/initramfs-3.10.0-1160.36.2.el7.x86_64.img | grep virtio
Arguments: -f --add-drivers 'virtio virtio_pci virtio_blk virtio_net'
-rw-r--r-- 1 root root 8240 Jul 21 2021 usr/lib/modules/3.10.0-1160.36.2.el7.x86_64/kernel/drivers/block/virtio_blk.ko.xz
-rw-r--r-- 1 root root 12968 Jul 21 2021 usr/lib/modules/3.10.0-1160.36.2.el7.x86_64/kernel/drivers/char/virtio_console.ko.xz
drwxr-xr-x 2 root root 0 Aug 2 14:49 usr/lib/modules/3.10.0-1160.36.2.el7.x86_64/kernel/drivers/gpu/drm/virtio
-rw-r--r-- 1 root root 24160 Jul 21 2021 usr/lib/modules/3.10.0-1160.36.2.el7.x86_64/kernel/drivers/gpu/drm/virtio/virtio-gpu.ko.xz
-rw-r--r-- 1 root root 14216 Jul 21 2021 usr/lib/modules/3.10.0-1160.36.2.el7.x86_64/kernel/drivers/net/virtio_net.ko.xz
-rw-r--r-- 1 root root 8224 Jul 21 2021 usr/lib/modules/3.10.0-1160.36.2.el7.x86_64/kernel/drivers/scsi/virtio_scsi.ko.xz
drwxr-xr-x 2 root root 0 Aug 2 14:49 usr/lib/modules/3.10.0-1160.36.2.el7.x86_64/kernel/drivers/virtio
-rw-r--r-- 1 root root 4548 Jul 21 2021 usr/lib/modules/3.10.0-1160.36.2.el7.x86_64/kernel/drivers/virtio/virtio.ko.xz
-rw-r--r-- 1 root root 9896 Jul 21 2021 usr/lib/modules/3.10.0-1160.36.2.el7.x86_64/kernel/drivers/virtio/virtio_pci.ko.xz
-rw-r--r-- 1 root root 8576 Jul 21 2021 usr/lib/modules/3.10.0-1160.36.2.el7.x86_64/kernel/drivers/virtio/virtio_ring.ko.xz
You can exit from chroot and then unmount everything
$ exit
$ for x in sys proc run dev tmp; do umount /mnt/root/$x; done
$ umount /mnt/root/boot
$ umount /mnt/root
In case of LVM you may also disable the volume group you've just enabled, so you can reattach the volume if you need additional fixes.
Detach volume from helper VM
Once the machine has started, you need to attach the volume to the VM, you can do it with:
Create image based on volume
Create an image based on the volume after the fix, so you can create new volumes or machines booted directly from this image:
openstack image create --min-disk 100 --volume vendor_volume --disk-format qcow2 --property architecture='x86_64' --property hw_architecture='x86_64' --progress vendor
Cleanup
Once the image has finished to be created, you can delete the original vendor volume and the helper VM you've used to get into this point.
Now you can create machines booted from this image or from volumes using this image as a source.