{"id":678,"date":"2010-01-16T11:30:23","date_gmt":"2010-01-16T19:30:23","guid":{"rendered":"http:\/\/wp.colliertech.org\/cj\/?p=678"},"modified":"2010-02-05T05:33:58","modified_gmt":"2010-02-05T13:33:58","slug":"aoe-root-for-kvm-guests","status":"publish","type":"post","link":"https:\/\/wp.c9h.org\/cj\/?p=678","title":{"rendered":"AoE root for KVM guests"},"content":{"rendered":"<h1>Intro<\/h1>\n<p>So.  I&#8217;m trying to get familiar with libvirt and friends.  To this end, I&#8217;ve set up a Lucid virtual machine booting from PXE into an initrd environment which does a pivot_root to an AoE block device.<\/p>\n<p>The #virt channel on irc.oftc.net told me that in order to have libvirt provide PXE capability, I would have to install a recent version of libvirt.  I built version 0.7.5-3 from sid on my karmic laptop and it seems to be working okay.<\/p>\n<p>I decided to set up the pxe root directoy in \/var\/lib\/tftproot just because that&#8217;s what the <a href=\"http:\/\/libvirt.org\/git\/?p=libvirt.git;a=blob;f=tests\/networkxml2xmlin\/netboot-network.xml;h=ed756630534aa3487c6d6977eba734a426a711a0;hb=cebc4b8921d64d93714d780f03194b6bc9c0f7f2\">example code<\/a> had in it.<\/p>\n<h1>Configure the Virtual Network<\/h1>\n<p>I had to manually configure a virtual network.  Here is the XML config file:<\/p>\n<pre>$ sudo virsh net-dumpxml netboot\r\n&lt;network&gt;\r\n  &lt;name&gt;netboot&lt;\/name&gt;\r\n  &lt;uuid&gt;81ff0d90-c91e-6742-64da-4a736edb9a9b&lt;\/uuid&gt;\r\n  &lt;forward mode='nat'\/&gt;\r\n  &lt;bridge name='virbr1' stp='off' delay='1' \/&gt;\r\n  &lt;domain name='example.com'\/&gt;\r\n  &lt;ip address='192.168.123.1' netmask='255.255.255.0'&gt;\r\n    &lt;tftp root='\/var\/lib\/tftproot' \/&gt;\r\n    &lt;dhcp&gt;\r\n      &lt;range start='192.168.123.2' end='192.168.123.254' \/&gt;\r\n      &lt;bootp file='pxelinux.0' \/&gt;\r\n    &lt;\/dhcp&gt;\r\n  &lt;\/ip&gt;\r\n&lt;\/network&gt;\r\n<\/pre>\n<h1>Install syslinux<\/h1>\n<p>This, of course, depends on the pxelinux.0 file.  Luckily, this is packaged up in syslinux and can be installed with a simple<\/p>\n<p><code><br \/>\n$ sudo apt-get install syslinux<br \/>\n$ sudo mkdir \/var\/lib\/tftproot<br \/>\n$ sudo cp \/usr\/lib\/syslinux\/pxelinux.0 \/var\/lib\/tftproot<br \/>\n<\/code><\/p>\n<h1>Configure PXE boot parameters<\/h1>\n<p>I had to create a pxelinux config file for the virtual machine (indexed by mac address).  Note that I put a console=ttyS0,115200 argument on the kernel command line so that I can attach to the serial port from the host system for copy\/paste debugging.  Also of importance is the root=\/dev\/etherd\/e0.1p1 argument, specifying which block device we&#8217;ll be doing the pivot_root to eventually.<\/p>\n<p><code><br \/>\n$ mkdir \/var\/lib\/tftproot\/pxelinux.cfg\/<br \/>\n$ cat \/var\/lib\/tftproot\/pxelinux.cfg\/01-52-54-00-44-34-67<br \/>\nDEFAULT linux<br \/>\nLABEL linux<br \/>\nSAY Now booting the kernel from PXELINUX...<br \/>\nKERNEL vmlinuz-lucid0<br \/>\nAPPEND ro root=\/dev\/etherd\/e0.1p1 console=ttyS0,115200 initrd=initrd.img-lucid0<br \/>\n<\/code><\/p>\n<p>I decided to use the karmic kernel for lucid initially.  I&#8217;ll eventually switch over to the lucid kernel ;)<\/p>\n<p><code><br \/>\n$ sudo cp \/boot\/vmlinuz-2.6.31-17-generic \/var\/lib\/tftproot\/vmlinuz-lucid0<br \/>\n<\/code><\/p>\n<h1>Customize initramfs-tools<\/h1>\n<p>I copied \/etc\/initramfs-tools to ~\/tmp\/lucid so that I didn&#8217;t mess up the system initrd scripts:<\/p>\n<p><code><br \/>\n$ mkdir -p ~\/tmp\/lucid && cp -r \/etc\/initramfs-tools ~\/tmp\/lucid\/<br \/>\n<\/code><\/p>\n<p>Since mkinitramfs doesn&#8217;t currently have a system for AoE root, I had to do a bit of fiddling.  I copied the NFS root boot script and made a couple of modifications.<\/p>\n<pre>\r\n$ diff -u \/usr\/share\/initramfs-tools\/scripts\/nfs ~\/tmp\/lucid\/initramfs-tools\/scripts\/aoe\r\n--- \/usr\/share\/initramfs-tools\/scripts\/nfs\t2008-06-23 23:10:21.000000000 -0700\r\n+++ \/home\/cjac\/tmp\/lucid\/initramfs-tools\/scripts\/aoe\t2010-01-15 14:56:28.098298027 -0800\r\n@@ -5,59 +5,25 @@\r\n retry_nr=0\r\n \r\n # parse nfs bootargs and mount nfs \r\n-do_nfsmount()\r\n+do_aoemount()\r\n {\r\n-\r\n \tconfigure_networking\r\n \r\n-\t# get nfs root from dhcp\r\n-\tif [ \"x${NFSROOT}\" = \"xauto\" ]; then\r\n-\t\t# check if server ip is part of dhcp root-path\r\n-\t\tif [ \"${ROOTPATH#*:}\" = \"${ROOTPATH}\" ]; then\r\n-\t\t\tNFSROOT=${ROOTSERVER}:${ROOTPATH}\r\n-\t\telse\r\n-\t\t\tNFSROOT=${ROOTPATH}\r\n-\t\tfi\r\n-\r\n-\t# nfsroot=[&lt;server-ip&gt;:]&lt;root-dir&gt;[,&lt;nfs-options&gt;]\r\n-\telif [ -n \"${NFSROOT}\" ]; then\r\n-\t\t# nfs options are an optional arg\r\n-\t\tif [ \"${NFSROOT#*,}\" != \"${NFSROOT}\" ]; then\r\n-\t\t\tNFSOPTS=\"-o ${NFSROOT#*,}\"\r\n-\t\tfi\r\n-\t\tNFSROOT=${NFSROOT%%,*}\r\n-\t\tif [ \"${NFSROOT#*:}\" = \"$NFSROOT\" ]; then\r\n-\t\t\tNFSROOT=${ROOTSERVER}:${NFSROOT}\r\n-\t\tfi\r\n-\tfi\r\n+        ip link set up dev eth0\r\n \r\n-\tif [ -z \"${NFSOPTS}\" ]; then\r\n-\t\tNFSOPTS=\"-o retrans=10\"\r\n-\tfi\r\n+        ls \/dev\/etherd\/\r\n \r\n-\t[ \"$quiet\" != \"y\" ] &amp;&amp; log_begin_msg \"Running \/scripts\/nfs-premount\"\r\n-\trun_scripts \/scripts\/nfs-premount\r\n-\t[ \"$quiet\" != \"y\" ] &amp;&amp; log_end_msg\r\n+        echo &gt; \/dev\/etherd\/discover\r\n \r\n-\tif [ ${readonly} = y ]; then\r\n-\t\troflag=\"-o ro\"\r\n-\telse\r\n-\t\troflag=\"-o rw\"\r\n-\tfi\r\n+        ls \/dev\/etherd\/\r\n \r\n-\tnfsmount -o nolock ${roflag} ${NFSOPTS} ${NFSROOT} ${rootmnt}\r\n+        mount ${ROOT} ${rootmnt}\r\n }\r\n \r\n-# NFS root mounting\r\n+# AoE root mounting\r\n mountroot()\r\n {\r\n-\t[ \"$quiet\" != \"y\" ] &amp;&amp; log_begin_msg \"Running \/scripts\/nfs-top\"\r\n-\trun_scripts \/scripts\/nfs-top\r\n-\t[ \"$quiet\" != \"y\" ] &amp;&amp; log_end_msg\r\n-\r\n-\tmodprobe nfs\r\n-\t# For DHCP\r\n-\tmodprobe af_packet\r\n+\tmodprobe aoe\r\n \r\n \t# Default delay is around 180s\r\n \t# FIXME: add usplash_write info\r\n@@ -67,17 +33,13 @@\r\n \t\tdelay=${ROOTDELAY}\r\n \tfi\r\n \r\n-\t# loop until nfsmount succeds\r\n+\t# loop until aoemount succeds\r\n \twhile [ ${retry_nr} -lt ${delay} ] &amp;&amp; [ ! -e ${rootmnt}${init} ]; do\r\n \t\t[ ${retry_nr} -gt 0 ] &amp;&amp; \\\r\n-\t\t[ \"$quiet\" != \"y\" ] &amp;&amp; log_begin_msg \"Retrying nfs mount\"\r\n-\t\tdo_nfsmount\r\n+\t\t[ \"$quiet\" != \"y\" ] &amp;&amp; log_begin_msg \"Retrying AoE mount\"\r\n+\t\tdo_aoemount\r\n \t\tretry_nr=$(( ${retry_nr} + 1 ))\r\n \t\t[ ! -e ${rootmnt}${init} ] &amp;&amp; \/bin\/sleep 1\r\n \t\t[ ${retry_nr} -gt 0 ] &amp;&amp; [ \"$quiet\" != \"y\" ] &amp;&amp; log_end_msg\r\n \tdone\r\n-\r\n-\t[ \"$quiet\" != \"y\" ] &amp;&amp; log_begin_msg \"Running \/scripts\/nfs-bottom\"\r\n-\trun_scripts \/scripts\/nfs-bottom\r\n-\t[ \"$quiet\" != \"y\" ] &amp;&amp; log_end_msg\r\n }\r\n<\/pre>\n<p>(below is the full file in case udiff is less convenient)<\/p>\n<pre>\r\n$ cat ~\/tmp\/lucid\/initramfs-tools\/scripts\/aoe\r\n# NFS filesystem mounting\t\t\t-*- shell-script -*-\r\n\r\n# FIXME This needs error checking\r\n\r\nretry_nr=0\r\n\r\n# parse nfs bootargs and mount nfs \r\ndo_aoemount()\r\n{\r\n\tconfigure_networking\r\n\r\n        ip link set up dev eth0\r\n\r\n        ls \/dev\/etherd\/\r\n\r\n        echo &gt; \/dev\/etherd\/discover\r\n\r\n        ls \/dev\/etherd\/\r\n\r\n        mount ${ROOT} ${rootmnt}\r\n}\r\n\r\n# AoE root mounting\r\nmountroot()\r\n{\r\n\tmodprobe aoe\r\n\r\n\t# Default delay is around 180s\r\n\t# FIXME: add usplash_write info\r\n\tif [ -z \"${ROOTDELAY}\" ]; then\r\n\t\tdelay=180\r\n\telse\r\n\t\tdelay=${ROOTDELAY}\r\n\tfi\r\n\r\n\t# loop until aoemount succeds\r\n\twhile [ ${retry_nr} -lt ${delay} ] &amp;&amp; [ ! -e ${rootmnt}${init} ]; do\r\n\t\t[ ${retry_nr} -gt 0 ] &amp;&amp; \\\r\n\t\t[ \"$quiet\" != \"y\" ] &amp;&amp; log_begin_msg \"Retrying AoE mount\"\r\n\t\tdo_aoemount\r\n\t\tretry_nr=$(( ${retry_nr} + 1 ))\r\n\t\t[ ! -e ${rootmnt}${init} ] &amp;&amp; \/bin\/sleep 1\r\n\t\t[ ${retry_nr} -gt 0 ] &amp;&amp; [ \"$quiet\" != \"y\" ] &amp;&amp; log_end_msg\r\n\tdone\r\n}\r\n<\/pre>\n<p>There was also a small modification to the initramfs.conf file:<\/p>\n<pre>\r\n$ diff -u \/etc\/initramfs-tools\/initramfs.conf ~\/tmp\/lucid\/initramfs-tools\/initramfs.conf\r\n--- \/etc\/initramfs-tools\/initramfs.conf\t2008-07-08 18:37:42.000000000 -0700\r\n+++ \/home\/cjac\/tmp\/lucid\/initramfs-tools\/initramfs.conf\t2010-01-15 14:33:38.088295207 -0800\r\n@@ -47,14 +47,16 @@\r\n #\r\n \r\n #\r\n-# BOOT: [ local | nfs ]\r\n+# BOOT: [ local | nfs | aoe]\r\n #\r\n # local - Boot off of local media (harddrive, USB stick).\r\n #\r\n # nfs - Boot using an NFS drive as the root of the drive.\r\n #\r\n+# aoe - Boot using an AoE drive as the root of the drive.\r\n+#\r\n \r\n-BOOT=local\r\n+BOOT=aoe\r\n \r\n #\r\n # DEVICE: ...\r\n<\/pre>\n<p>I also needed to add aoe to the list of modules included in the initramfs:<\/p>\n<p><code><br \/>\n$ echo aoe >> ~\/tmp\/lucid\/initramfs-tools\/modules<br \/>\n<\/code><\/p>\n<p>In order to generate the initrd.img file from this new config, I ran the following:<\/p>\n<p><code><br \/>\n$ sudo mkinitramfs -d ~\/tmp\/lucid\/initramfs-tools\/ -o \/var\/lib\/tftproot\/initrd.img-lucid0<br \/>\n<\/code><\/p>\n<h1>Install OS to virtual block device<\/h1>\n<p>I created a lucid VM by installing from the desktop install disk.  You can grab the ISO here:<\/p>\n<p><a href=\"http:\/\/cdimage.ubuntu.com\/daily-live\/current\/\">http:\/\/cdimage.ubuntu.com\/daily-live\/current\/<\/a><\/p>\n<p>I&#8217;ll leave the creation of the virtual machine and installation as an exercise for the reader.  I put the filesystem on an lvm volume group called vg0 in a logical volume called lucid0 (ie, \/dev\/vg0\/lucid0).<\/p>\n<h1>Create virtual machine definition with virsh<\/h1>\n<p>At this point, I created a new virtual machine called lucid0.  Here is the xml for the domain:<\/p>\n<pre>$ sudo virsh dumpxml lucid0\r\n&lt;domain type='kvm' id='1'&gt;\r\n  &lt;name&gt;lucid0&lt;\/name&gt;\r\n  &lt;uuid&gt;96fbad21-4f25-5700-ddd8-1a565c7170ee&lt;\/uuid&gt;\r\n  &lt;memory&gt;524288&lt;\/memory&gt;\r\n  &lt;currentMemory&gt;524288&lt;\/currentMemory&gt;\r\n  &lt;vcpu&gt;1&lt;\/vcpu&gt;\r\n  &lt;os&gt;\r\n    &lt;type arch='x86_64' machine='pc-0.11'&gt;hvm&lt;\/type&gt;\r\n    &lt;boot dev='network'\/&gt;\r\n  &lt;\/os&gt;\r\n  &lt;features&gt;\r\n    &lt;pae\/&gt;\r\n  &lt;\/features&gt;\r\n  &lt;clock offset='localtime'\/&gt;\r\n  &lt;on_poweroff&gt;destroy&lt;\/on_poweroff&gt;\r\n  &lt;on_reboot&gt;restart&lt;\/on_reboot&gt;\r\n  &lt;on_crash&gt;restart&lt;\/on_crash&gt;\r\n  &lt;devices&gt;\r\n    &lt;emulator&gt;\/usr\/bin\/kvm&lt;\/emulator&gt;\r\n    &lt;interface type='network'&gt;\r\n      &lt;mac address='52:54:00:44:34:67'\/&gt;\r\n      &lt;source network='netboot'\/&gt;\r\n      &lt;target dev='vnet0'\/&gt;\r\n    &lt;\/interface&gt;\r\n    &lt;serial type='pty'&gt;\r\n   &lt;source path='\/dev\/pts\/4'\/&gt;\r\n      &lt;target port='0'\/&gt;\r\n    &lt;\/serial&gt;\r\n  &lt;console type='pty' tty='\/dev\/pts\/4'&gt;\r\n   &lt;source path='\/dev\/pts\/4'\/&gt;\r\n      &lt;target port='0'\/&gt;\r\n    &lt;\/console&gt;\r\n    &lt;input type='tablet' bus='usb'\/&gt;\r\n    &lt;input type='mouse' bus='ps2'\/&gt;\r\n    &lt;graphics type='vnc' port='5901' autoport='yes' listen='127.0.0.1' keymap='en-us'\/&gt;\r\n    &lt;sound model='es1370'\/&gt;\r\n    &lt;video&gt;\r\n      &lt;model type='cirrus' vram='9216' heads='1'\/&gt;\r\n    &lt;\/video&gt;\r\n  &lt;\/devices&gt;\r\n&lt;\/domain&gt;\r\n<\/pre>\n<h1>Start AoE target<\/h1>\n<p>Now we&#8217;re ready to start the AoE target and launch the virtual machine.  If you don&#8217;t have vblade installed, do so now:<\/p>\n<p><code><br \/>\n$ sudo apt-get install vblade<br \/>\n<\/code><\/p>\n<p>Start the target up with the following command:<\/p>\n<p><code><br \/>\n$ sudo vbladed 0 1 virbr1 \/dev\/vg0\/lucid0<br \/>\n<\/code><\/p>\n<h1>Boot the virtual machine<\/h1>\n<p>Now, if all goes well, you should be able to watch the virtual machine boot up and do its thing like so:<\/p>\n<p><code><br \/>\n$ sudo virsh start lucid0 && sudo screen -S lucid0 `sudo virsh ttyconsole lucid0` 115200<br \/>\n<\/code><\/p>\n<p>If you get errors about \/dev\/etherd\/e0.1p1 not existing (these might look like this):<\/p>\n<pre>\r\nBegin: Retrying AoE mount ...\r\nerr         discover    interfaces  revalidate  flush\r\nerr         discover    interfaces  revalidate  flush\r\nmount: mounting \/dev\/etherd\/e0.1p1 on \/root failed: No such file or directory\r\nDone.\r\n<\/pre>\n<p>then you might want to try restarting vbladed like this:<\/p>\n<p><code><br \/>\n$ sudo kill -9 `ps auwx | grep vblade | grep -v grep | awk '{print $2}' ` && sudo vbladed 0 1 virbr1 \/dev\/vg0\/lucid0<br \/>\n<\/code><\/p>\n<h1>Questions?  Comments?<\/h1>\n<p>So.  Now you should have a lucid gdm in your virt-manager console.  Any questions?  #virt on irc.oftc.net<\/p>\n<p>Also, feel free to <a href=\"mailto:cjac@colliertech.org?subject=AoE and KVM\">email me<\/a><\/p>\n\n<div class=\"twitter-share\"><a href=\"https:\/\/twitter.com\/intent\/tweet?via=cjamescollier\" class=\"twitter-share-button\">Tweet<\/a><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Intro So. I&#8217;m trying to get familiar with libvirt and friends. To this end, I&#8217;ve set up a Lucid virtual machine booting from PXE into an initrd environment which does a pivot_root to an AoE block device. The #virt channel on irc.oftc.net told me that in order to have libvirt provide PXE capability, I would [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[17,154,79,171,181,196,47,200,163,197,166,130,184,183],"tags":[],"class_list":["post-678","post","type-post","status-publish","format-standard","hentry","category-debian","category-dns","category-free-software","category-hardware","category-irc","category-libvirt","category-linux","category-lvm","category-networking","category-qemu","category-software","category-ubuntu","category-virtualization","category-xen"],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1YDIB-aW","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/wp.c9h.org\/cj\/index.php?rest_route=\/wp\/v2\/posts\/678","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wp.c9h.org\/cj\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wp.c9h.org\/cj\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wp.c9h.org\/cj\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/wp.c9h.org\/cj\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=678"}],"version-history":[{"count":15,"href":"https:\/\/wp.c9h.org\/cj\/index.php?rest_route=\/wp\/v2\/posts\/678\/revisions"}],"predecessor-version":[{"id":726,"href":"https:\/\/wp.c9h.org\/cj\/index.php?rest_route=\/wp\/v2\/posts\/678\/revisions\/726"}],"wp:attachment":[{"href":"https:\/\/wp.c9h.org\/cj\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=678"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wp.c9h.org\/cj\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=678"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wp.c9h.org\/cj\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=678"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}