Cats and Code » virtualization http://blog.gorwits.me.uk by Oliver Gorwits Sat, 29 Mar 2014 23:28:44 +0000 en-US hourly 1 http://wordpress.org/?v=3.6.1 Internet accessible cats – part 2 http://blog.gorwits.me.uk/2013/01/03/internet-accessible-cats-part-2/?utm_source=rss&utm_medium=rss&utm_campaign=internet-accessible-cats-part-2 http://blog.gorwits.me.uk/2013/01/03/internet-accessible-cats-part-2/#comments Thu, 03 Jan 2013 22:08:21 +0000 Oliver Gorwits http://blog.gorwits.me.uk/?p=855 Continue reading ]]> So far so good for access to the new Cat Cam: from within the house we can view video from the cats’ shed, yet the camera is safely on its own DMZ.

In this final post I’ll show how I made the camera video feed available on the Internet.

One thing I wanted from the outset was for Internet clients not to make direct connections to the camera itself. I was a little worried about the ability of the web server and CPU in the camera to cope with multiple clients, and also the security implications of direct access. A second requirement was to have multi platform access – that is, desktop and iOS. This potentially means different streaming video formats.

We have one linux server in the house, which is used for many different things and runs virtual machines. My back-of-an-envelope plan looked something like this:

First step was to create the VM, but remember that the camera feed is in a DMZ using a VLAN, so the VM must live there too. In KVM it’s possible either to send all traffic to a guest system and let it process the VLANs or, you can separate the tagged VLAN traffic in the host system so the guest is dumb and just sees untagged frames. Clearly the latter is preferable so that were the guest to suffer attack from the Internet, it ought not to be able to put traffic onto the house workstation network. The guest is completely within the DMZ.

With that done and a basic Ubuntu system installed, I started work on Apache and VLC (the Swiss Army Chainsaw of video processing). First up, VLC…

Luckily the camera’s video feed comes in MJPEG format with a discoverable URL. The idea is to take this feed, duplicate it, and transcode the respective feeds into something suitable for a desktop browser and for iOS. As a bonus, I’ll timestamp the video to make it easy to tell if the transcoder has crashed (the timestamp would be wrong). After a lot of reading online about how to configure VLC I came up with the following monstrosity:

/usr/bin/cvlc -I dummy http://guest:guest@172.16.30.10:8888/videostream.cgi?rate=0
  --sout='#duplicate{

    dst="transcode{
      width=320,heigh=240,fps=25,vcodec=h264,vb=256,acodec=none,
      venc=x264{profile=baseline,level=30,keyint=30,ref=1},
      sfilter=marq{marquee=\"[%Y-%m-%d %H:%M:%S]\",position=8,size=18}
    }:std{access=livehttp{
        seglen=10,delsegs=true,numsegs=5,
        index=/var/www/streaming/cats.m3u8,
        index-url=/streaming/cats-########.ts},
      mux=ts{use-key-frames},
      dst=/var/www/streaming/cats-########.ts}",

    dst="transcode{
      width=640,heigh=480,fps=25,vcodec=theo,vb=512,acodec=none,
      sfilter=marq{marquee=\"[%Y-%m-%d %H:%M:%S]\",position=8,size=18}
    }:http{mux=ogg,dst=127.0.0.1:8081/catcam.ogg}"

  }'

Of the two transcodes (“dst=”), the second is more straightforward. It creates an Ogg format stream using the Theora video codec, which modern browsers should be able to cope with. This is a video stream being served from VLC’s built-in web server, so I’ll need to proxy it via Apache. The configuration also applies a filter (“sfilter=”) to add a timestamp on the video stream.

The first transcode uses the new HTTP Live Streaming support in VLC. This is a rather elegant specification from Apple (which is why I selected it for the iOS clients) for simple and efficient delivery of streaming video. It creates a set of files and assumes you have a web server to serve them. The files each contain a few seconds of video, and the client retrieves them and plays one after another. The “######” templates an incrementing number within the segment filename. Again, the timestamp is added to the video stream.

CPU load for the above runs at about 60% (in the VM) on the dual core Athlon X2 245e processor. I wrapped the above in an Upstart init file, and just in case VLC gets its knickers in a twist, I added a cron job to periodically stop and start the service.

Now on to Apache. It needs to proxy the Ogg stream and serve the Live Streaming files, and prevent any other access to the web server:

# redirect any non-cat requests to the cat index.html
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/streaming/cats.*
RewriteCond %{REQUEST_URI} !^/stream/catcam.ogg$
RewriteCond %{REQUEST_URI} !^/index.html$
RewriteRule ^(.*) http://%{HTTP_HOST}/index.html [R,L]

ProxyReceiveBufferSize 16384
ProxyRequests On
ProxyVia On
ProxyPreserveHost On

<Proxy *>
    Order deny,allow
    Allow from all
</Proxy>

# VLC server stream
ProxyPass /stream/catcam.ogg http://localhost:8081/catcam.ogg
ProxyPassReverse /stream/catcam.ogg http://localhost:8081/catcam.ogg

Last but not least for this server, we need a web page which offers up the two video streams. This uses an HTML5 video tag:

<!DOCTYPE html>
<html>
    <head>
        <title>Cat Cam</title>
        <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
        <META HTTP-EQUIV="Pragma" CONTENT="no-cache">
    </head>
    <body>
        <h1>Cat Cam</h1>
        <video id="video" autoplay="autoplay">
            <source src="/streaming/cats.m3u8">
            <source src="/stream/catcam.ogg" type="video/ogg; codecs=theora">
            Your browser doesn't appear to support the HTML5 <code>&lt;video&gt;</code> element.
        </video>
    </body>
</html>

All that remains is to enable a NAT rule and firewall pinhole on the home router for the web server (which is, of course, in the DMZ network connected directly to the router).

Let’s see the end result, taken on my iPhone this evening, also demonstrating the automatically activated night vision mode:

It’s nice to be able to check in on the wee beasties when I’m out at work. Other than a lot of reading about VLC, it wasn’t particularly difficult to do, and I think the end result is really quite good.

]]>
http://blog.gorwits.me.uk/2013/01/03/internet-accessible-cats-part-2/feed/ 0
Virtual Machine on Mythbuntu http://blog.gorwits.me.uk/2012/01/04/virtual-machine-on-mythbuntu/?utm_source=rss&utm_medium=rss&utm_campaign=virtual-machine-on-mythbuntu http://blog.gorwits.me.uk/2012/01/04/virtual-machine-on-mythbuntu/#comments Wed, 04 Jan 2012 23:45:10 +0000 Oliver Gorwits http://blog.gorwits.me.uk/?p=728 Continue reading ]]> I have a Linux box running the excellent Mythbuntu (Ubuntu-based) distribution, headless (that is, without a monitor). Quite a lot of the time it’s sat around doing nothing (and even during recording or playback the CPU is idle).

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!

]]>
http://blog.gorwits.me.uk/2012/01/04/virtual-machine-on-mythbuntu/feed/ 0