I run a number of VM’s under KVM.  Windows VM’s, RedHat VM’s, SLES and Ubuntu VM’s.  Recently, we attempted to provision a VM using LANDesk.  We ran into an issue where KVM was not assigning a BIOS serial number.  LANDesk uses the BIOS serial number to identify the client to the LANDesk server.  

I worked with RedHat on this, and they came back with a simple answer.  qemu-kvm has the ability to specify a serial number, but RedHat’s utilities, which are used to do things like… start vm’s,  do no thave any method which to call this option.  The option is simple:

-smbios type=1,serial=c88f3f87

So the functionality is there, but theres no way to use it, and use the tools which RedHat supplies to interact with VM’s.

So, taking this piece of information, I set out figuring out how to add this command line option to the command line that virsh generates when you start a VM.   If you have a look at one of the confiruation files for VM’s, you’ll see that theyre XML, and virsh simply takes these XML attributes and builds a command line.  The issue is that virsh does not have any option for the serial.  It does however have a UUID, and an attribute which lets you specify what executable to run, to start the vm.  I thought maybe the UUID would be a good unique identifier for a VM.  So i wrote the following wrapper:

#!/usr/bin/perl
my $qemukvm = "/usr/bin/qemu-kvm";
my $args;
my $serial;
foreach (@ARGV) {
  $args .= " $_";
  if ($_ =~  m/[\w]{8}(-[\w]{4}){3}-[\w]{12}/) {
    my @tmp = split(/-/, $_);
    $serial = $tmp[0];
  }
}
if ($serial) {
  exec ($qemukvm . $args . " -smbios type=1,serial=" . $serial);
} else {
  exec ($qemukvm . $args);
}

And then set the "emulator" attribute in the VM’s config file to my wrapper.  Then i undefined my vm, and redefined it.  After that, I started up my vm, and what do you know, I’ve got a bios serial. W00t!