nbsvm ===== Create, start and interact with VMs from the command line without the bullshit. Requires zfs or lvm, kvm and sudo. Socat and a vnc client are needed to interact with (and stop) a running VM. Install ------- Place nbsvm in your $PATH, eg. /usr/local/bin. Everything else is documentation. Basic Usage ----------- nbsvm doesn't manage VMs in any real sense of the word. It is a helper which starts KVM in a consistent manner, attaching the hard drive images which already exist in /dev whose name match that of the VM being started. It also includes utilities to create devices which will match a named VM, either blank or as a copy of an existing device or file, and locate the unix socket files attached to a running VM. KVM is started with a fairly conservative set of options: * 512 MB RAM * A VNC display, serial port and qemu monitor port. * USB and a tablet pointing device. * A network device connected to a tap. * Any drive images whose path prefix matched the VM's name. The start command can take arguments which are appended to the kvm command verbatim. nbsvm commands can be chained, so that: $ nbsvm foo newimg newimg newimg start -cdrom install.iso will create 3 new images for foo then start it with a cdrom. Commands can be included after the start command by terminating the kvm arguments with "--": $ nbsvm foo newimg start -cdrom installer -- vnc Create a hard drive image named for the foo VM. $ nbsvm foo newimg Start a VM foo: $ nbsvm foo start Stop it: $ nbsvm foo stop Stop it nicely: $ nbsvm foo shutdown Connect to a running VM: Serial port: $ nbsvm foo console Qemu monitor port: $ nbsvm foo monitor VNC display: $ vnc_port=12345 nbsvm foo vnc ** vnc_port must be an unused tcp port. Clones and snapshots: The cloning/snapshot API is not very good and is liable to change when I work out what it should be. LVM or ZFS is selected by setting the $store variable (default: lvm). Each has a different concept of snapshots and clones, which nbsvm follows: LVM (store=lvm): Create a new image as a COW snapshot of the existing device "master-image": $ gold=master-image nbsvm foo snapshot Create a normal new device and copy "slow-master" using dd: $ gold=slow-master nbsvm foo clone This trick is also handy if you have the PID of the dd process nbsvm spawns: $ while kill -USR1 $DD_PID; do sleep 2; done ZFS (store=zfs): Create a snapshot "foo-0@backup" of foo's first image "foo-0": $ snapshot_name=backup nbsvm foo snapshot Create a new image for foo as a clone of "bar@master": $ snapshot_vm=bar snapshot_name=master nbsvm foo clone I don't really like the ZFS implementation and it is subject to change at my whim. Suggestions welcome. nbsvm doesn't make any attempt to rename or delete images, snapshots or clones. Magic usage ----------- Magic is accessed using environment variables, which override the defaults used to launch kvm and locate/name devices. There is a full list of these available in the Variables file. Some common uses are listed here. The hypervisor binary, amount of memory, usb devices and display are overridden by the $hypervisor, $mem, $usb and $display variables, respectively: hypervisor: Default: "kvm". mem: Default: "512". display: Default: "-display vnc=unix:$drawer/vnc.sock". usb: Default: "-usb -usbdevice tablet". ** Disable usb entirely with "usb=' '". Leaving it unset, or set to "", will not work. Other device defaults are a bit more involved: Storage: Variable "drives". Constructed on the fly by looking in /dev/$vg or /dev/zvol/$zpool for any files matching the pattern nbsvm-$vm-* (or nbsvm-$class-$vm-*) and including them in a list of "-drive" arguments. "virtio" can be changed by setting $drive_if. * Snapshots and clones: newimage and clone (and with the lvm backend, snapshot) create a new hard drive image for a named VM. The new device is named nbsvm-$vm-$id (if $class is set, nbsvm-$class-$vm-$id) where $id is obtained by counting the existing devices, with the first device numbered 0. LVM devices are created in the volume group named by $vg, or "vg0". ZFS devices are created under $zpool, or "tank". newimage, and snapshot on lvm, create drives sized $drive_size (default: 10G). Mostly, only $gold (default: gold) should be set to determine which device to clone. LVM will make a clone or snapshot of "nbsvm-$gold" or "nbsvm-$class-$gold". ZFS snapshot will create a snapshot named "nbsvm-$vm-0@snapshot" or "nbsvm-$class-$vm-0@snapshot"). ZFS clone will create a clone of "nbsvm@$gold" or "nbsvm-$class@$gold". ZFS support is rather messy and will hopefully be improved soon. The device can be changed with these variables: source: The full VG and LV name, or ZFS volume name, to clone or snapshot. Default: $vg/$snapshot_source or $zpool/$snapshot_source $snapshot_source depends on the storage backend ($store) and command: LVM snapshot default: $vg/nbsvm-$gold or $vg/nbsvm-$class-$gold LVM clone uses the same scheme as LVM snapshot. ZFS snapshot default: $zpool/nbsvm-$gold or $zpool/nbsvm-$class-$gold ZFS clone default: $zpool/nbsvm@$gold or $zpool/nbsvm-$class@$gold Networking: The default network setup is to create a single virtual ethernet device attached to a tap device named "tap-$vm" on the host using this concoction: -device $net_if,netdev=net -netdev tap,id=net,ifname=tap-$vm,script=no,downscript=no The default $net_if is "virtio-net-pci", the guest's MAC address can be set with $mac, which appends ",mac=$mac" to the -device option. The entire thing can be overridden by setting $network. If $bridge is set (it has no default) then the "tap-$vm" device on the host is added to the bridge by running "brctl addif $bridge tap-$vm". If the network settings are changed by setting $network, this is not done. Saved settings and Classes: Because remembering which options go with which VMs is tedious, nbsvm first parses files in /etc/nbsvm named after the vm being started. The files are simply sourced into nbsvm's bash environment. Additional files can be parsed by setting the $class variable, which also adjusts the names of image which are used. The files are sourced in the following order: /etc/nbsvm/default.class /etc/nbsvm/$class.class (if $class is set) /etc/nbsvm/$vm.vm (or $class-$vm.vm if $class is set) Finally, $class can be set by creating a link to nbsvm named ${class}vm and calling that instead of calling the nbsvm binary directly. If the $class variable is set, it is used instead of the class name extracted from the command name. To set variables in the class or vm files which can still be overridden at runtime, write them using bash's replacement syntax like so: mem=${mem:-2048} # Can be overridden at runtime net_if=e1000 # Is forced to e1000 The $args variable is also available in the saved settings files. This is an *array*, not a plain string, of arguments to append to the kvm command. It is set simply enough: args=(-cdrom /srv/static-boot.iso -boot d) A vm file can append to arguments set in the class file[s]: args+=(-soundhw all) Arguments passed to the start command are appended to the $args array which is then used in the kvm command. I don't know I'd have command-line arguments replace $args or even if I'd want to. Patches welcome.