[libvirt] [RFC,PATCH] network: add 'netboot' option to dhcp config

Jeremy Kerr jk at ozlabs.org
Fri Sep 11 04:47:49 UTC 2009


Currently, libvirtd will start a dnsmasq process for the virtual
network, but (aside from killing the dnsmasq process and replacing it),
there's no way to define tftp boot options.

This change introduces a 'netboot' tag to the dhcp configuration:

 <network>
   <name>default</name>
   <bridge name="virbr%d" />
   <forward/>
   <ip address="192.168.122.1" netmask="255.255.255.0">
     <dhcp>
       <range start="192.168.122.2" end="192.168.122.254" />
       <netboot root="/srv/tftp" file="pxeboot.img"/>
     </dhcp>
   </ip>
 </network>

When root= and file= attributes are present, these are passed to the
arguments to dnsmasq:

 dnsmasq [...] --enable-tftp --tftp-root /srv/tftp --dhcp-boot pxeboot.img

At present, only local tftp servers are supported (ie, dnsmasq runs as
the tftp server), but we could improve this in future by adding a
server= attribute.

Signed-off-by: Jeremy Kerr <jk at ozlabs.org>

---
 docs/formatnetwork.html.in |    6 ++++++
 docs/schemas/network.rng   |    6 ++++++
 src/network_conf.c         |   28 ++++++++++++++++++++++++++++
 src/network_conf.h         |    9 +++++++++
 src/network_driver.c       |   10 ++++++++++
 5 files changed, 59 insertions(+)

diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
index fd68430..3186498 100644
--- a/docs/formatnetwork.html.in
+++ b/docs/formatnetwork.html.in
@@ -138,6 +138,12 @@
 	name to be given that host by the DHCP server (via the
         <code>name</code> attribute).  <span class="since">Since 0.4.5</span>
       </dd>
+      <dt><code>netboot</code></dt>
+      <dd>The optional <code>netboot</code> element specified network boot
+        options to be provided by the DHCP server. Two attributes are
+        required: <code>root</code> (the root path of the TFTP server), and
+        <code>file</code> (the file to be used for the boot image).
+      </dd>
     </dl>
 
     <h2><a name="examples">Example configuration</a></h2>
diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng
index a4281a5..571e916 100644
--- a/docs/schemas/network.rng
+++ b/docs/schemas/network.rng
@@ -76,6 +76,12 @@
             <attribute name="ip"><text/></attribute>
           </element>
         </zeroOrMore>
+	<optional>
+	  <element name="netboot">
+	    <attribute name="root"><text/></attribute>
+	    <attribute name="file"><text/></attribute>
+	  </element>
+	</optional>
       </element>
     </element>
   </optional>
diff --git a/src/network_conf.c b/src/network_conf.c
index 3764bb4..87bb5e4 100644
--- a/src/network_conf.c
+++ b/src/network_conf.c
@@ -115,6 +115,9 @@ void virNetworkDefFree(virNetworkDefPtr def)
     }
     VIR_FREE(def->hosts);
 
+    VIR_FREE(def->tftproot);
+    VIR_FREE(def->bootfile);
+
     VIR_FREE(def);
 }
 
@@ -299,6 +302,24 @@ virNetworkDHCPRangeDefParseXML(virConnectPtr conn,
             def->hosts[def->nhosts].name = (char *)name;
             def->hosts[def->nhosts].ip = (char *)ip;
             def->nhosts++;
+
+        } else if (cur->type == XML_ELEMENT_NODE &&
+            xmlStrEqual(cur->name, BAD_CAST "netboot")) {
+            xmlChar *root, *file;
+
+            if (!(root = xmlGetProp(cur, BAD_CAST "root"))) {
+                cur = cur->next;
+                continue;
+            }
+
+            if (!(file = xmlGetProp(cur, BAD_CAST "file"))) {
+                cur = cur->next;
+                xmlFree(root);
+                continue;
+            }
+
+            def->tftproot = (char *)root;
+            def->bootfile = (char *)file;
         }
 
         cur = cur->next;
@@ -621,6 +642,13 @@ char *virNetworkDefFormat(virConnectPtr conn,
                     virBufferVSprintf(&buf, "ip='%s' ", def->hosts[i].ip);
                 virBufferAddLit(&buf, "/>\n");
             }
+            if (virNetworkDefProvidesNetboot(def)) {
+                virBufferAddLit(&buf, "      <netboot");
+                virBufferEscapeString(&buf, " root='%s'", def->tftproot);
+                virBufferEscapeString(&buf, " file='%s'", def->bootfile);
+                virBufferAddLit(&buf, " />\n");
+            }
+
             virBufferAddLit(&buf, "    </dhcp>\n");
         }
 
diff --git a/src/network_conf.h b/src/network_conf.h
index 4076f9a..f6f7c1e 100644
--- a/src/network_conf.h
+++ b/src/network_conf.h
@@ -78,8 +78,17 @@ struct _virNetworkDef {
 
     unsigned int nhosts;         /* Zero or more dhcp hosts */
     virNetworkDHCPHostDefPtr hosts;
+
+    char *tftproot;
+    char *bootfile;
 };
 
+static inline int
+virNetworkDefProvidesNetboot(const virNetworkDefPtr def)
+{
+        return def->tftproot && def->bootfile;
+}
+
 typedef struct _virNetworkObj virNetworkObj;
 typedef virNetworkObj *virNetworkObjPtr;
 struct _virNetworkObj {
diff --git a/src/network_driver.c b/src/network_driver.c
index 49855bf..cf462f2 100644
--- a/src/network_driver.c
+++ b/src/network_driver.c
@@ -400,6 +400,8 @@ networkBuildDnsmasqArgv(virConnectPtr conn,
         (2 * network->def->nranges) + /* --dhcp-range 10.0.0.2,10.0.0.254 */
         /*  --dhcp-host 01:23:45:67:89:0a,hostname,10.0.0.3 */
         (2 * network->def->nhosts) +
+        /* --enable-tftp --tftp-root /srv/tftp --dhcp-boot pxeboot.img */
+        (virNetworkDefProvidesNetboot(network->def) ? 5 : 0) +
         1;  /* NULL */
 
     if (VIR_ALLOC_N(*argv, len) < 0)
@@ -478,6 +480,14 @@ networkBuildDnsmasqArgv(virConnectPtr conn,
         APPEND_ARG(*argv, i++, buf);
     }
 
+    if (virNetworkDefProvidesNetboot(network->def)) {
+        APPEND_ARG(*argv, i++, "--enable-tftp");
+        APPEND_ARG(*argv, i++, "--tftp-root");
+        APPEND_ARG(*argv, i++, network->def->tftproot);
+        APPEND_ARG(*argv, i++, "--dhcp-boot");
+        APPEND_ARG(*argv, i++, network->def->bootfile);
+    }
+
 #undef APPEND_ARG
 
     return 0;




More information about the libvir-list mailing list