Parsing Libvirt XML with xmllint

I’ve been playing around with the LXC support in libvirt recently,
and I’m trying to use a model where each LXC instance is backed by a
dedicated LVM volume. This means that the process of starting an
instance is:

mount the instance root filesystem if necessary

start the instance

It’s annoying to have to do this by hand. I could simply add all the
LXC filesystems to /etc/fstab, but this would mean and extra step
when creating and deleting each instance.

I thought about creating a wrapper script to handle the mounting (and
unmounting, perhaps) for me, but this leads to another problem: I need
a way to figure out which backing device corresponding to the virtual
instance I’m trying to boot.

I could just adopt a strict naming scheme, so that for a given
instance “foo” the backing store would be
/dev/vg_something/domain-foo, but that’s too easy! In order to make
life interesting:

I’ve added some namespace-prefixed metadata to the instance XML
description, and

Written a shell script to extract this data (and more) using
xmllint.

Metadata

The metadata node can be used by applications to store custom
metadata in the form of XML nodes/trees. Applications must use
custom namespaces on their XML nodes/trees, with only one top-level
element per namespace (if the application needs structure, they
should have sub-elements to their namespace element).

This means that if you want to add metadata to a domain description,
you need to define a namespace and use a namespace prefix. For
example, if I want to add a device element pointing at the backend
storage device for my domain, it might look like this:

Extracting metadata with xmllint

The xmllint tool, part of libxml, can extract nodes from an XML
document using xpath expressions. Unfortunately, while xmllint
does have namespace support, it’s not particularly convenient. Using
the --shell mode there’s a helpful setns command:

But that’s not available from the command line. We can use the
namespace-uri() and local-name() xpath functions to get to the
same place, albeit more verbosely. An equivalent to the above shell
session would be: