I'm trying to convert my kvm build script written in BASH to Python. In BASH, I've written the following lines within my script to execute a fresh KVM instance built from an ISO image:
virt-install \
--name=${VMNAME} \
--ram=${MEMSIZE} \
--vcpus=${VCPUS} \
--os-type "linux" \
--location ${ISOFILE} \
--file=/var/lib/libvirt/images/${VMNAME}.dsk \
--file-size=${DISKSIZE} \
--network bridge=br0 \
--graphics=none \
--os-variant="rhel7" \
-x 'console=ttyS0,115200n8 serial' \
-x "ks=http://192.168.1.10/boot/centos7.ks"
This creates a successful build, and is visible through the "virsh" console using virt-install.
The script I'm using in Python to mimic what is happening in my BASH script looks like this:
kvm_cmd = ['/usr/bin/virt-install', \
'--name=' + SELECT_SPECS[0], \
'--ram=' + SELECT_SPECS[2], \
'--vcpus=' + SELECT_SPECS[3], \
'--os-type=linux', \
'--location=' + CONFIG_VM[1], \
'--file=/var/lib/libvirt/images/' + SELECT_SPECS[0] + '.dsk', \
'--file-size=' + SELECT_SPECS[4], \
'--network=bridge:br0', \
'--nographics', \
'--os-variant=' + CONFIG_VM[2], \
'-x "console=ttyS0,115200n8 serial"', \
'-x "ks=' + KS_REPO + CONFIG_VM[0] + '.ks"']
process = subprocess.run(kvm_cmd, stdout=subprocess.PIPE)
print(kvm_cmd)
print('VM ' + SELECT_SPECS[0] + ' created!')
return
Right now, I'm trying to perform the BASH command using Python's subprocess.run() function. Although I'm not seeing the serial output during run time, I can send a ^] signal while the Python script is running to exit out of the console, and re-enter the virsh console in another window/terminal.
Entering console, I can see that the installation runs into some anaconda issues that report "Kickstart file /run/install/ks.cfg is missing".
I can confirm that all my command argument variables are where they belong. I've used both --network bridge:br0 and --bridge=br0 for testing, as well as defining a kickstart file locally with '-x "ks=file:/centos7.ks' and --initrd-inject=/path/to/centos7.ks with the same results.
['/usr/bin/virt-install', '--name=test', '--ram=2048', '--vcpus=1', '--os-type=linux', \
'--location=/DataStore/ISOs/CentOS-7-x86_64-Minimal-1708.iso', '--file=/var/lib/libvirt/images/test.dsk', \
'--file-size=20', '--bridge=br0', '--graphics=none', '--os-variant=rhel7', '-x \
"console=ttyS0,115200n8 serial"', '-x "ks=http://192.168.1.10/boot/centos7.ks"']
Can anyone help me figure out why the kickstart won't load using python's Subprocess.run() function, but I can run it no problem when I run the command in BASH?
Is there a better way to create my kvm's with the details mentioned other than using BASH virt-install in a subprocess, preferably with a Python library? I've had a look at libvirt, but could not find a solution to my BASH query.
The equivalent to the shell script fragment:
-x 'console=ttyS0,115200n8 serial' \
-x "ks=http://${KS_REPO}/boot/${CONFIG_VM}.ks"
is (assuming a new enough Python to support f-strings for brevity):
[
'-x', 'console=ttyS0,115200n8 serial',
'-x', f'ks=http://{KS_REPO}/boot/{CONFIG_VM[0]}.ks',
]
No literal quotes, only syntactic ones, in both languages.