--- /dev/null
+bindings
+history
+300.d/disk.img
+400.d/disk.img
+500.d/rhel6.img
+500.d/win7.img
+600.d/libguestfs-1.16.2.tar.gz
--- /dev/null
+<link rel="stylesheet" href="style.css" type="text/css"/>
+<script src="code.js" type="text/javascript"></script>
+
+<div id="titlepage">
+<p class="title">
+ libguestfs <br/> <br/>
+ tools for viewing and modifying <br/> virtual machine disk images
+</p>
+<p><author>
+Richard W.M. Jones <br/> Red Hat <br/>
+<small>rjones @ redhat.com</small>
+</author></p>
+</div>
--- /dev/null
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" href="style.css" type="text/css"/>
+<script src="code.js" type="text/javascript"></script>
+
+<h1>Library, API, tools</h1>
+
+<img style="position: absolute; top: 4em; left: 12em;" src="disk.png"/>
+<img style="position: absolute; top: 4em; left: 16em;" src="flash.png"/>
+<img style="position: absolute; top: 4em; left: 20em;" src="file.png"/>
+
+<img style="position: absolute; top: 4.75em; left: 12em;" src="arrows1.svg"/>
+
+<p class="bubble" style="position: absolute; top: 7em; left: 12em; width: 10em;">libguestfs.so</p>
+
+<img style="position: absolute; top: 9em; left: 12em;" src="arrows2.svg"/>
+
+<p class="bubble" style="position: absolute; top: 12em; left: 2.5em;">C</p>
+
+<p class="bubble" style="position: absolute; top: 12em; left: 10em;">Python</p>
+
+<p class="bubble" style="position: absolute; top: 12em; left: 18em;">Ruby</p>
+
+<p class="bubble" style="position: absolute; top: 12em; left: 25em;">shell</p>
+
+<p class="bubbleinverse" style="position: absolute; top: 12em; left: 32em;">· · ·</p>
+
+<p class="bubble" style="position: absolute; top: 17em; left: 3em;">virt-resize</p>
+
+<p class="bubble" style="position: absolute; top: 17em; left: 10.5em;">virt-df</p>
+
+<p class="bubble" style="position: absolute; top: 17em; left: 18em;">guestfish</p>
+
+<p class="bubbleinverse" style="position: absolute; top: 17em; left: 25em;">· · ·</p>
--- /dev/null
+#!/bin/bash -
+
+source functions
+
+remember 'ls -l -h'
+remember 'file disk.img'
+remember 'guestfish --ro -i -a disk.img'
+
+echo "Example: Modify a disk image"
+
+cd 300.d
+terminal
--- /dev/null
+#!/bin/bash -
+
+source functions
+
+echo "Example: Inspection"
+
+remember 'ls -l -h'
+remember 'file disk.img'
+remember 'virt-df -h -a disk.img'
+remember 'virt-filesystems -a disk.img --all --long -h'
+remember 'virt-inspector -a disk.img | highlight | less -r'
+
+cd 400.d
+terminal
--- /dev/null
+#!/bin/bash -
+
+source functions
+
+echo "Example: Auditing"
+
+remember 'ls -l -h'
+remember 'emacs -nw audit.py'
+remember './audit.py win7.img'
+remember './audit.py rhel6.img'
+
+cd 500.d
+terminal
--- /dev/null
+#!/usr/bin/python
+
+import re
+import sys
+import guestfs
+
+def mount_disk (g, root):
+ mps = g.inspect_get_mountpoints (root)
+ def compare (a, b):
+ if len(a[0]) > len(b[0]):
+ return 1
+ elif len(a[0]) == len(b[0]):
+ return 0
+ else:
+ return -1
+ mps.sort (compare)
+ for mp_dev in mps:
+ try:
+ g.mount_ro (mp_dev[1], mp_dev[0])
+ except RuntimeError as msg:
+ print "%s (ignored)" % msg
+
+if len (sys.argv) != 2:
+ raise (Error ("disk [image]"))
+disk = sys.argv[1]
+
+g = guestfs.GuestFS ()
+g.add_drive_opts (disk, readonly=1)
+
+g.launch ()
+
+roots = g.inspect_os ()
+if len (roots) == 0:
+ raise (Error ("inspect_vm: no operating systems found"))
+
+for root in roots:
+ mount_disk (g, root)
+
+ apps = g.inspect_list_applications (root)
+ for app in apps:
+ if re.search ('firefox', app['app_name'], re.IGNORECASE):
+ print ("%s: Firefox version %s" % (disk, app['app_version']))
+
+ g.umount_all ()
--- /dev/null
+#!/bin/bash -
+
+source functions
+
+echo "Example: Prepopulate a disk image"
+
+remember 'emacs -nw prepopulate.py'
+remember './prepopulate.py'
+remember 'ls -l -h'
+remember 'virt-df -h -a disk.img'
+remember 'guestfish -a disk.img -m /dev/sda1 --ro'
+
+cd 600.d
+
+rm -f disk.img
+
+terminal
--- /dev/null
+#!/usr/bin/python
+
+import os
+import guestfs
+
+input = "libguestfs-1.16.2.tar.gz"
+output = "disk.img"
+
+g = guestfs.GuestFS ()
+
+f = open (output, "w")
+f.truncate (512 * 1024 * 1024)
+f.close ()
+
+g.add_drive_opts (output, format = "raw", readonly = 0)
+
+g.launch ()
+
+g.part_disk ("/dev/sda", "mbr")
+g.mkfs ("ext4", "/dev/sda1")
+g.mount ("/dev/sda1", "/")
+g.tgz_in (input, "/")
+
+g.close ()
--- /dev/null
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<link rel="stylesheet" href="style.css" type="text/css"/>
+<script src="code.js" type="text/javascript"></script>
+
+<h1>libguestfs.org</h1>
+
+<p>
+ <small>Languages:</small>
+ C/C++, Perl, Python, Ruby, OCaml, Java, PHP, Erlang, shell script
+</p>
+
+<table class="tools">
+<tr>
+<td><p class="bubble">guestfish</p></td>
+<td><p class="bubble" style="width: 8em;">virt-copy-out</p></td>
+<td><p class="bubble" style="width: 9em;">virt-inspector</p></td>
+<td><p class="bubble" style="width: 8em;">virt-sparsify</p></td>
+</tr>
+<tr>
+<td><p class="bubble" style="width: 8em;">guestmount</p></td>
+<td><p class="bubble">virt-df</p></td>
+<td><p class="bubble">virt-ls</p></td>
+<td><p class="bubble" style="width: 8em;">virt-tar-in</p></td>
+</tr>
+<tr>
+<td><p class="bubble" style="width: 10em;">virt-alignment-scan</p></td>
+<td><p class="bubble">virt-edit</p></td>
+<td><p class="bubble">virt-make-fs</p></td>
+<td><p class="bubble" style="width: 8em;">virt-tar-out</p></td>
+</tr>
+<tr>
+<td><p class="bubble">virt-cat</p></td>
+<td><p class="bubble" style="width: 9em;">virt-filesystems</p></td>
+<td><p class="bubble">virt-rescue</p></td>
+<td><p class="bubble" style="width: 8em;">virt-win-reg</p></td>
+</tr>
+<tr>
+<td><p class="bubble" style="width: 8em;">virt-copy-in</p></td>
+<td><p class="bubble">virt-format</p></td>
+<td><p class="bubble">virt-resize</p></td>
+</tr>
+</table>
+
+<p>
+ Aeolus, OpenStack Essex, Boxgrinder, Oz, virt-manager, virt-v2v, virt-p2v
+</p>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.48.2 r9819"
+ sodipodi:docname="arrows1.svg">
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2"
+ inkscape:cx="173.44713"
+ inkscape:cy="979.98192"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="true"
+ inkscape:window-width="1143"
+ inkscape:window-height="843"
+ inkscape:window-x="449"
+ inkscape:window-y="31"
+ inkscape:window-maximized="0">
+ <inkscape:grid
+ id="grid3761"
+ type="xygrid" />
+ </sodipodi:namedview>
+ <defs
+ id="defs4">
+ <marker
+ style="overflow:visible"
+ id="Arrow1Lstart"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow1Lstart">
+ <path
+ transform="scale(0.8) translate(12.5,0)"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ id="path3766" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="Arrow1Lend"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow1Lend">
+ <path
+ transform="scale(0.8) rotate(180) translate(12.5,0)"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ id="path3769" />
+ </marker>
+ <marker
+ style="overflow:visible"
+ id="Arrow1Lstartf"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow1Lstartf">
+ <path
+ transform="scale(0.8) translate(12.5,0)"
+ style="marker-start:none;stroke:#cc0000;stroke-width:1.0pt;fill:#cc0000;fill-rule:evenodd"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ id="path4582" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="Arrow1Lendk"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow1Lendk">
+ <path
+ transform="scale(0.8) rotate(180) translate(12.5,0)"
+ style="marker-start:none;stroke:#cc0000;stroke-width:1.0pt;fill:#cc0000;fill-rule:evenodd"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ id="path4585" />
+ </marker>
+ <marker
+ style="overflow:visible"
+ id="Arrow1Lstartc"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow1Lstartc">
+ <path
+ transform="scale(0.8) translate(12.5,0)"
+ style="marker-start:none;stroke:#cc0000;stroke-width:1.0pt;fill:#cc0000;fill-rule:evenodd"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ id="path4588" />
+ </marker>
+ </defs>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ inkscape:groupmode="layer"
+ inkscape:label="Layer 1">
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path3753"
+ d="m 46,27.362183 100,66"
+ style="fill:none;stroke:#cc0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lstartc);marker-end:none" />
+ <path
+ style="fill:none;stroke:#cc0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lstartf);marker-end:none"
+ d="m 254,27.362183 -99,66"
+ id="path3757"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path3759"
+ d="m 150,92.362183 0,-65"
+ style="stroke-linejoin:miter;marker-end:url(#Arrow1Lendk);stroke-opacity:1;stroke:#cc0000;stroke-linecap:butt;stroke-width:1px;fill:none" />
+ </g>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="744.09448819"
+ height="1052.3622047"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.48.2 r9819"
+ sodipodi:docname="arrows2.svg">
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2"
+ inkscape:cx="174.44713"
+ inkscape:cy="979.98192"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="true"
+ inkscape:window-width="1143"
+ inkscape:window-height="843"
+ inkscape:window-x="449"
+ inkscape:window-y="31"
+ inkscape:window-maximized="0">
+ <inkscape:grid
+ id="grid3761"
+ type="xygrid" />
+ </sodipodi:namedview>
+ <defs
+ id="defs4">
+ <marker
+ style="overflow:visible"
+ id="Arrow1Lstart"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow1Lstart">
+ <path
+ transform="scale(0.8) translate(12.5,0)"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ id="path3766" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="Arrow1Lend"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow1Lend">
+ <path
+ transform="scale(0.8) rotate(180) translate(12.5,0)"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ id="path3769" />
+ </marker>
+ <marker
+ style="overflow:visible"
+ id="Arrow1Lstartf"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow1Lstartf">
+ <path
+ transform="scale(0.8) translate(12.5,0)"
+ style="marker-start:none;stroke:#cc0000;stroke-width:1.0pt;fill:#cc0000;fill-rule:evenodd"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ id="path4582" />
+ </marker>
+ <marker
+ style="overflow:visible;"
+ id="Arrow1Lendk"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow1Lendk">
+ <path
+ transform="scale(0.8) rotate(180) translate(12.5,0)"
+ style="marker-start:none;stroke:#cc0000;stroke-width:1.0pt;fill:#cc0000;fill-rule:evenodd"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ id="path4585" />
+ </marker>
+ <marker
+ style="overflow:visible"
+ id="Arrow1Lstartc"
+ refX="0.0"
+ refY="0.0"
+ orient="auto"
+ inkscape:stockid="Arrow1Lstartc">
+ <path
+ transform="scale(0.8) translate(12.5,0)"
+ style="marker-start:none;stroke:#cc0000;stroke-width:1.0pt;fill:#cc0000;fill-rule:evenodd"
+ d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+ id="path4588" />
+ </marker>
+ </defs>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ inkscape:groupmode="layer"
+ inkscape:label="Layer 1">
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path3753"
+ d="m 134,27.362183 -100,66"
+ style="fill:none;stroke:#cc0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lstartc);marker-end:none" />
+ <path
+ style="fill:none;stroke:#cc0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow1Lstartf);marker-end:none"
+ d="m 167,27.362183 99,66"
+ id="path3757"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#cc0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lendk)"
+ d="m 194,92.362183 -40,-65"
+ id="path3061"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0"
+ id="path3063"
+ d="m 106,92.362183 40,-65"
+ style="fill:none;stroke:#cc0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lendk)" />
+ </g>
+</svg>
--- /dev/null
+# -*- shell-script -*-
+
+# Fancy prompt colours (see
+# https://wiki.archlinux.org/index.php/Color_Bash_Prompt)
+promptcol='\e[0;32m' ;# colour for the prompt
+commandcol='\e[1;31m' ;# colour for the typed command
+outputcol='\e[0m' ;# colour for command output
+
+export PS1="\n\[$promptcol\]\$ \[$commandcol\]"
+
+trap 'echo -ne "$outputcol"' DEBUG
+
+# Load key bindings (if any).
+bind -f $talkdir/bindings
--- /dev/null
+# -*- shell-script -*-
+# This creates some standard functions. See also $talkdir/bashrc
+# which runs in the same bash context as the terminal.
+
+# Place any local environment variables and settings in "local".
+if [ -f local ]; then source local; fi
+
+# Environment variables.
+export HISTFILE=$talkdir/history
+export PATH=$talkdir:$PATH
+export LIBVIRT_DEFAULT_URI=qemu:///system
+export EDITOR="emacs -nw"
+
+# remember <command> <args ...>
+#
+# This function does two things: (1) It adds the command and arguments
+# to the shell history, so that commands can be recalled using up
+# arrow or reverse search. (2) It makes a function key recall the
+# command. The first command is assigned to F2, the second to F3 and
+# so forth.
+
+rm -f $HISTFILE
+touch $HISTFILE
+rm -f $talkdir/bindings
+touch bindings
+
+fnum=2
+keys=(- OP OQ OR OS '[15~' '[17~' '[18~' '[19~' '[20~' '[21~')
+
+remember ()
+{
+ echo "$@" >> $HISTFILE
+ echo \"\\e${keys[$fnum]}\":\"\\C-k \\C-u"$@"\" >> $talkdir/bindings
+ ((fnum++))
+}
+
+terminal ()
+{
+ chmod -w $HISTFILE
+ /bin/bash --rcfile $talkdir/bashrc "$@"
+}
--- /dev/null
+#!/bin/sh -
+source-highlight -s xml -o STDOUT -f esc
--- /dev/null
+[20 minutes + 5 for questions]
+
+!!!!! DISPLAY RESOLUTION !!!!!
+
+[BEFORE:
+ guestfish -a /dev/null run
+ ~/d/techtalk-pse/techtalk-pse
+]
+
+[Audience is:
+ - cloud developers
+ - general interest
+
+ What do they want to do with images:
+ - file injection
+ - inspection for auditing
+ - creation of blank / prepopulated
+ - resizing
+ - use it from languages like Python, C, Ruby, Perl, Java
+
+ Adoption / find out more:
+ - website
+]
+
+[website:
+
+libguestfs is a set of tools for accessing and modifying virtual
+machine (VM) disk images. You can use this to inject files, resize,
+rescue, create, view or audit disks. libguestfs is also a library that
+you can link to management programs written in C, Perl, Python, Ruby,
+Java and other languages. In this talk, Richard Jones will introduce
+the tools and give live demonstrations. He also talks about how they
+work behind the scenes.
+]
+
+
+100 INTRODUCTION
+
+ - website
+ - my email address
+
+200 OVERVIEW
+
+C library, API and a set of tools
+
+(just a few are shown here)
+
+full time development for 3 years, > 300,000 lines of code
+
+using kernel + qemu code, so can handle qcow2, all sorts of filesystems
+
+300 GUESTFISH
+
+
+
+400 INSPECTION
+
+
+
+500 AUDITING
+
+
+
+600 PREPOPULATED DISK IMAGE
+
+
+
+900 SUMMARY
+
+ - summary page
+ tools (all of them here)
+ used in OpenStack
+ used in Aeolus
+ used in Boxgrinder
+ used in Oz
+ used in virt-manager
+ used in virt-v2v, virt-p2v
--- /dev/null
+/* Red Hat red is rgb(204,0,0). */
+
+body {
+ background: url(redhat.jpg) no-repeat;
+ background-position: 98% 0;
+ font-size: 24pt;
+ font-family: liberation, helvetica;
+}
+
+body td { /* why?? */
+ font-size: 28pt;
+}
+
+h1 {
+ color: rgb(204,0,0);
+ font-size: 48px;
+ top: 8;
+ left: 0;
+ border-bottom: 2px solid rgb(204,0,0);
+}
+
+b {
+ color: rgb(204,0,0);
+}
+
+div#titlepage {
+ margin-top: 100px;
+ text-align: center;
+}
+
+div#titlepage p.title {
+ color: rgb(204,0,0);
+ font-weight: bold;
+ font-size: 48px;
+}
+
+div#titlepage author {
+ font-size: 36px;
+}
+
+/* In-page controls. */
+p#pagecontrols {
+ font-size: small;
+ position: absolute;
+ right: 340px;
+ top: 1em;
+}
+
+p#pagecontrols a {
+ background: #fee;
+ text-decoration: none;
+ padding-left: 1.5em;
+ padding-right: 1.5em;
+ padding-top: 1em;
+ padding-bottom: 1em;
+}
+
+p#pagecontrols a:hover {
+ background: #f33;
+}
+
+/* Bubble around names of virt-tools. */
+p.bubble {
+ font-weight: bold;
+ color: white;
+ width: 6em;
+ text-align: center;
+ background-color: rgb(204,0,0);
+ -moz-border-radius: 0.2em;
+ border-radius: 0.2em;
+}
+
+p.bubbleinverse {
+ font-weight: bold;
+ color: rgb(204,0,0);
+ width: 6em;
+ text-align: center;
+ background-color: white;
+}
+
+table.tools td {
+ padding-bottom: 0.5em;
+ padding-right: 0.5em;
+}
\ No newline at end of file