For some side-projects I wanted a clean Linux installation to mess about with. It seemed a good idea to run virtual machines and make the most of existing hardware; what surprised me was just how easy this turned out to be
The Ubuntu documentation for KVM is excellent, I must say, but I fancied distilling things further and blogging here, as I typically do to record most of my technical adventures. I’m not going to bother with any of the GUI VM builder tools or even the Q&A install script, but simply specify the VM config fully, up front.
Optionally, check whether your CPU has virtualization extensions – any fairly recent desktop chip should do. On Ubuntu there’s a command called kvm-ok
, or you can poke /proc/cpuinfo
:
# kvm-ok INFO: /dev/kvm exists KVM acceleration can be used # egrep -q '(vmx|svm)' /proc/cpuinfo && echo 'good to go!' good to go!
First up install the KVM software:
# apt-get install qemu-kvm virtinst
This will pull in all the necessary packages. On other platforms it should be similar, but the virtinst
package is often renamed (e.g. virt-install
or vm-install
).
Before getting stuck in to KVM we need to reconfigure the system’s network adapter to be a bridge. I prefer to set a static IP for servers on my home LAN and use the /etc/network/interfaces
file for configuration:
# cat > /etc/network/interfaces auto lo eth0 br0 iface lo inet loopback iface eth0 inet manual iface br0 inet static address <IP-ADDRESS> network <NETWORK-ADDRESS> netmask <NETMASK> broadcast <BROADCAST> gateway <GATEWAY> bridge_ports eth0 bridge_stp off bridge_fd 0 bridge_maxwait 0 post-up ip link set br0 address <MAC-ADDRESS> (hit ctrl-D)
Obviously, fill in the blanks for your own system’s IP and MAC address details. Next we can blow away Ubuntu’s network mangler daemon and poke the KVM service into life:
# apt-get --purge remove network-manager # /etc/init.d/networking restart # service libvirt-bin start
Now find somewhere on your disk for the VMs and a little script to live, and create a directory. I named mine /opt/vm
. In there, try starting with this little shell script:
#!/bin/bash virt-install --name=sandbox --ram=512 --vcpus=2 --os-type=linux \ --autostart --disk=path=/opt/vm/sandbox.img,size=50 \ --graphics=vnc,listen=0.0.0.0,port=5900 --noautoconsole \ --cdrom=/opt/vm/mythbuntu-11.10-desktop-i386.iso
Walking through the above, it should be clear we’re creating a new VM called sandbox
(this is the name KVM knows it by, not a hostname), with 512MB RAM, two virtual CPUs, a Linux-friendly boot environment, and 50GB (sparse) disk. The VM will be automatically booted by the KVM service when its host system boots. The last line specifies an installation CD image from which the new VM will boot.
For the graphics configuration I’ve asked for a headless system with the console being offered up via a VNC port on the host server. Note that the listen=0.0.0.0
is essential to connect remotely (e.g. over your home LAN) to the console because otherwise the VNC port is simply bound to the loopback interface.
Running the above will bring the new VM into life:
# ./sandbox.sh Starting install... Creating storage file sandbox.img | 50 GB 00:00 Creating domain... | 0 B 00:01 Domain installation still in progress. You can reconnect to the console to complete the installation process.
What KVM means by “installation still in progress” is that it knows this system is installing from the boot CD, so you should go right ahead and fire up VNC and connect to the console (port 5900 on the host server) to complete the process.
You’ll find that KVM saved the sandbox
VM configuration in XML format in the /etc/libvirt/qemu
directory, so that’s where to go to tweak the settings. Good documentation is available at the KVM website.
Be aware, however, that because KVM assumed the attached CD ISO was only needed for initial install, it’s not featured in the saved config as a permanent connection. You can, of course, remedy this (check out the virt-install
man page for starters).
To finish off, here’s how to manage the lifecycle (start, restart, blow away, etc) of the VM. Use the virsh
utility which can either be run with a single instruction or with no parameters for an interactive CLI:
# virsh Welcome to virsh, the virtualization interactive terminal. virsh # list Id Name State ---------------------------------- 10 sandbox running virsh # destroy error: command 'destroy' requires <domain> option virsh # destroy sandbox Domain sandbox destroyed virsh # create sandbox error: Failed to open file 'sandbox': No such file or directory virsh # create sandbox.xml Domain sandbox created from sandbox.xml virsh # list Id Name State ---------------------------------- 11 sandbox running
Try the help
command, and note that the VM’s XML settings file may need updating if you change things (see dumpxml
).
I hope this is a useful and quick tutorial for KVM on Ubuntu… Good Luck!
]]>Last time we went through the steps to transcode a recording into the H.264 format, required for playback on iPad (or other Apple devices – iPod, iPhone, Mac OS X, etc).
Today we’ll complete the series by embedding an HTML5 Video player into MythWeb which will stream these files. Of course, this means playback isn’t only possible on iPad, but also any compatible browser platform. The original plan was simply to provide a file download link in MythWeb, but my friend Colin rightly suggested an embedded HTML5 Video player would be much more awesome.
Your MythWeb files are probably installed somewhere like /usr/share/mythtv/mythweb
. Open up modules/tv/tmpl/default/detail.php
and replace the default embedded player with a new HTML5 Video tag. You should find this around line 797. Replace the two lines comprising the Direct Download hyperlink with the following:
<video controls preload="none" width="360" height="153"> <source src="/h264xcode/<?php echo $program->chanid ?>_<?php echo date( 'YmdHis', $program->recstartts ) ?>.m4v"> Your browser does not support the video tag. </video>
The above requires that you make the H.264 files available through your MythWeb web server. In my case, I simply created a symlink from the server’s DocumentRoot
to where the H.264 files live (so, change this to reflect your own H.264 file location):
ln -s /mnt/mythtv-video/Videos/iPad /var/www/h264xcode
The result is the following, once the transcoded file appears on disk:
And we’re done! Browsing to the MythWeb site on an iPad shows the embedded player which, when clicked, opens fullscreen for native playback. My deep thanks to all those working on the software used in this series of articles, and I also hope you found it a useful read.
]]>However the most hated part for me is configuring TV sources and channels – digital terrestrial via an aerial, and digital via satellite. MythTV’s built-in scanner works at best intermittently (for me), and when it does, comes up with 1,000 shopping and adult channels which drown out the 20 or so I’m really interested in.
Then there’s TV listings. All credit to the folks working on XMLTV and the Radio Times listings grabber – that’s some impressive work. But stitching it into MythTV usually ends up with hand-editing the database to insert XMLTV IDs. User friendly? I think not.
Partly this is because these tools are used internationally and nothing is standardised between countries. Even in the UK there are three ways to get TV listings (EIT over the air, Bleb, and Radio Times).
Finally I snapped, and wrote a Perl program to do all this work. It feels so nice now to have a simple, lightweight, repeatable process to configure sources and channels. That’s what good automation is all about.
The code will only work in the UK, but might be a starting point for those elsewhere. It configures XMLTV IDs, but that doesn’t mean you have to use the Radio Times grabber. You still have to go through MythTV’s setup program to tell it about tuner cards (before running the import program) but that’s not hard work.
The code and instructions are hosted on GitHub. Let me know if you use it, and how you get on. Don’t forget to back up your database (using MythTV’s mythconverg_*
scripts) before starting!
After digging around online for ages I found a document with the trick to keeping persistent device names for tuner cards, which I’m sorry to say I’ve now lost. Here goes, for the sake of Google archiving…
Start with listing the PCI devices to see their Vendor and Bus ID:
oliver@htpc:~$ lspci -nnv <snipped...> 03:05.0 Multimedia controller [0480]: Philips Semiconductors SAA7146 [1131:7146] (rev 01) Subsystem: Technotrend Systemtechnik GmbH S2-3200 [13c2:1019] Flags: bus master, medium devsel, latency 64, IRQ 20 Memory at febffc00 (32-bit, non-prefetchable) [size=512] Kernel driver in use: budget_ci dvb Kernel modules: budget-ci 03:06.0 Multimedia controller [0480]: Philips Semiconductors SAA7146 [1131:7146] (rev 01) Subsystem: Technotrend Systemtechnik GmbH Technotrend-Budget/Hauppauge WinTV-NOVA-T DVB card [13c2:1005] Flags: bus master, medium devsel, latency 64, IRQ 21 Memory at febff800 (32-bit, non-prefetchable) [size=512] Kernel driver in use: budget dvb Kernel modules: budget
Hopefully there’s enough information for you to tell which card is which, if as like my situation the (highlighted) description lines are almost identical. Above, the terrestrial card is WinTV-NOVA-T
and the satellite card is S2-3200
.
The pieces of information you want to record for each card are the Bus ID – the number such as 03:05.0
at the start of the highlighted line, and the Vendor ID – the first number before the colon in square brackets such as 1131
.
We’re going to use udev rules, but not to set the device names, instead creating alias (or duplicate) names which are used by MythTV configuration.
oliver@htpc:~$ cat /etc/udev/rules.d/15-videosymlinks.rules SUBSYSTEM=="dvb", ATTRS{vendor}=="0x1131", KERNELS=="0000:03:06.0", PROGRAM="/bin/sh -c 'K=%k; K=$${K#dvb}; printf dvb/adapter101/%%s $${K#*.}'", SYMLINK+="%c" SUBSYSTEM=="dvb", ATTRS{vendor}=="0x1131", KERNELS=="0000:03:05.0", PROGRAM="/bin/sh -c 'K=%k; K=$${K#dvb}; printf dvb/adapter102/%%s $${K#*.}'", SYMLINK+="%c"
I’ve identified the cards by matching both their Vendor ID (note it’s Hex so prefixed with 0x
) and Bus ID, and chosen names adapter101
and adapter102
(scroll to the right to see). The high numbers are because, as I explained, the original device names are still present:
oliver@htpc:~$ ls -1 /dev/dvb/ adapter0 adapter1 adapter101 adapter102
Within these alias device directories are in fact symlinks (automatically created!) to the correct card device data, whatever its name happens to be on this boot:
oliver@htpc:~$ ll /dev/dvb/adapter101/ total 0 drwxr-xr-x 2 root root 120 2010-12-12 13:03 ./ drwxr-xr-x 6 root root 120 2010-12-12 13:03 ../ lrwxrwxrwx 1 root root 18 2010-12-12 13:03 demux0 -> ../adapter0/demux0 lrwxrwxrwx 1 root root 16 2010-12-12 13:03 dvr0 -> ../adapter0/dvr0 lrwxrwxrwx 1 root root 21 2010-12-12 13:03 frontend0 -> ../adapter0/frontend0 lrwxrwxrwx 1 root root 16 2010-12-12 13:03 net0 -> ../adapter0/net0
When configuring MythTV use the new alias names and this problem is solved.
]]>