[libvirt] [PATCH v2] network: add 'bootp' and 'tftp' config

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 the appropriate tags to the dhcp configuration:

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

When the attributes are present, these are passed to the
arguments to dnsmasq:

 dnsmasq [...] --enable-tftp --tftp-root /srv/tftp --dhcp-boot pxeboot.img
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
                      from <tftp />                     from <bootp />


Possible future features in this field include the following:

- 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 to <bootp>.

- Currently, the BOOTP file cannot be assigned to a specific <range> or
<host>.  Even if this was implemented, it would still make sense to
allow <bootp> appearing directly within the <dhcp> element, providing
a global default.

Signed-off-by: Jeremy Kerr <jk@xxxxxxxxxx>
Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>

2009-09-15  Paolo Bonzini  <pbonzini@xxxxxxxxxx>
            Jeremy Kerr  <jk@xxxxxxxxxx>

	* docs/formatnetwork.html.in: Document new tags.
	* docs/formatnetwork.html: Regenerate.
	* docs/schemas/network.rng: Update.
	* src/network_conf.c (virNetworkDefFree): Free new fields.
	(virNetworkDHCPRangeDefParseXML): Parse <bootp>.
	(virNetworkIPParseXML): New, parsing <dhcp> and <tftp>.
	(virNetworkDefParseXML): Use virNetworkIPParseXML instead of
	virNetworkDHCPRangeDefParseXML.
	(virNetworkDefFormat): Pretty print new fields.
	* src/network_conf.h (struct _virNetworkDef): Add netboot fields.
	* src/network_driver.c (networkBuildDnsmasqArgv): Add
	TFTP and BOOTP arguments.

	* tests/Makefile.am (EXTRA_DIST): Add networkschemadata.
	* tests/networkschematest: Look in networkschemadata.
	* tests/networkschemadata/netboot-network.xml: New.
---

	Compared to v1, I fixed wrong HTML that was pointed out to me
	offline by Jiri Denemark.  Note that "make" will give errors
	for it but will _not_ abort.

 docs/formatnetwork.html                     |   15 ++++++-
 docs/formatnetwork.html.in                  |   17 ++++++--
 docs/schemas/network.rng                    |   10 ++++
 src/network_conf.c                          |   60 +++++++++++++++++++++++++-
 src/network_conf.h                          |    3 +
 src/network_driver.c                        |   14 ++++++
 tests/Makefile.am                           |    1 +
 tests/networkschemadata/netboot-network.xml |   12 +++++
 tests/networkschematest                     |    2 +-
 9 files changed, 124 insertions(+), 10 deletions(-)
 create mode 100644 tests/networkschemadata/netboot-network.xml

diff --git a/docs/formatnetwork.html b/docs/formatnetwork.html
index 845e558..e97b9be 100644
--- a/docs/formatnetwork.html
+++ b/docs/formatnetwork.html
@@ -235,7 +235,13 @@
 	address will be their default route. The <code>netmask</code>
 	attribute defines the significant bits of the network address,
 	again specified in dotted-decimal format.  <span class="since">Since 0.3.0</span>
-      </dd><dt><code>dhcp</code></dt><dd>Immediately within the <code>ip</code> element there is an
+      </dd><dt><code>tftp</code></dt><dd>Immediately within
+	the <code>ip</code> element there is an optional <code>tftp</code>
+	element. The presence of this element and of its attribute
+	<code>root</code> enables TFTP services.  The attribute specifies
+	the path to the root directory served via TFTP.
+	<span class="since">Since 0.7.1</span>
+      </dd><dt><code>dhcp</code></dt><dd>Also within the <code>ip</code> element there is an
 	optional <code>dhcp</code> element. The presence of this element
 	enables DHCP services on the virtual network. It will further
 	contain one or more <code>range</code> elements.
@@ -253,7 +259,12 @@
         assigned to that host (via the <code>ip</code> attribute), and the
 	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></dl>
+      </dd><dt><code>bootp</code></dt><dd>The optional <code>bootp</code>
+	element specifies BOOTP options to be provided by the DHCP server.
+	Only one attribute is supported, <code>file</code>, giving the file
+	to be used for the boot image).  The BOOTP options currently have to
+	be the same for all address ranges and statically assigned addresses.<span class="since">Since 0.7.1.</span>
+    </dd></dl>
         <h2>
           <a name="examples" id="examples">Example configuration</a>
         </h2>
diff --git a/docs/formatnetwork.html.in b/docs/formatnetwork.html.in
index fd68430..e471385 100644
--- a/docs/formatnetwork.html.in
+++ b/docs/formatnetwork.html.in
@@ -113,9 +113,13 @@
 	address will be their default route. The <code>netmask</code>
 	attribute defines the significant bits of the network address,
 	again specified in dotted-decimal format.  <span class="since">Since 0.3.0</span>
-      </dd>
-      <dt><code>dhcp</code></dt>
-      <dd>Immediately within the <code>ip</code> element there is an
+      </dd><dt><code>tftp</code></dt><dd>Immediately within
+	the <code>ip</code> element there is an optional <code>tftp</code>
+	element. The presence of this element and of its attribute
+	<code>root</code> enables TFTP services.  The attribute specifies
+	the path to the root directory served via TFTP.
+	<span class="since">Since 0.7.1</span>
+      </dd><dt><code>dhcp</code></dt><dd>Also within the <code>ip</code> element there is an
 	optional <code>dhcp</code> element. The presence of this element
 	enables DHCP services on the virtual network. It will further
 	contain one or more <code>range</code> elements.
@@ -137,7 +141,12 @@
         assigned to that host (via the <code>ip</code> attribute), and the
 	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>
+      </dd><dt><code>bootp</code></dt><dd>The optional <code>bootp</code>
+	element specifies BOOTP options to be provided by the DHCP server.
+	Only one attribute is supported, <code>file</code>, giving the file
+	to be used for the boot image).  The BOOTP options currently have to
+	be the same for all address ranges and statically assigned addresses.<span
+	class="since">Since 0.7.1.</span>
     </dl>
 
     <h2><a name="examples">Example configuration</a></h2>
diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng
index a4281a5..042e013 100644
--- a/docs/schemas/network.rng
+++ b/docs/schemas/network.rng
@@ -60,6 +60,11 @@
       <optional>
         <attribute name="netmask"><text/></attribute>
       </optional>
+      <optional>
+	<element name="tftp">
+	  <attribute name="root"><text/></attribute>
+	</element>
+      </optional>
       <!-- Define the range(s) of IP addresses that the DHCP
            server should hand out -->
       <element name="dhcp">
@@ -76,6 +81,11 @@
             <attribute name="ip"><text/></attribute>
           </element>
         </zeroOrMore>
+	<optional>
+	  <element name="bootp">
+	    <attribute name="file"><text/></attribute>
+	  </element>
+	</optional>
       </element>
     </element>
   </optional>
diff --git a/src/network_conf.c b/src/network_conf.c
index 3764bb4..14eb543 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,17 @@ 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 "bootp")) {
+            xmlChar *file;
+
+            if (!(file = xmlGetProp(cur, BAD_CAST "file"))) {
+                cur = cur->next;
+                continue;
+            }
+
+            def->bootfile = (char *)file;
         }
 
         cur = cur->next;
@@ -307,6 +321,37 @@ virNetworkDHCPRangeDefParseXML(virConnectPtr conn,
     return 0;
 }
 
+static int
+virNetworkIPParseXML(virConnectPtr conn,
+                     virNetworkDefPtr def,
+                     xmlNodePtr node) {
+    xmlNodePtr cur;
+
+    cur = node->children;
+    while (cur != NULL) {
+        if (cur->type == XML_ELEMENT_NODE &&
+            xmlStrEqual(cur->name, BAD_CAST "dhcp")) {
+            int result = virNetworkDHCPRangeDefParseXML(conn, def, cur);
+            if (result)
+                return result;
+
+        } else if (cur->type == XML_ELEMENT_NODE &&
+            xmlStrEqual(cur->name, BAD_CAST "tftp")) {
+            xmlChar *root;
+
+            if (!(root = xmlGetProp(cur, BAD_CAST "root"))) {
+                cur = cur->next;
+                continue;
+            }
+
+            def->tftproot = (char *)root;
+        }
+
+        cur = cur->next;
+    }
+    return 0;
+}
+
 static virNetworkDefPtr
 virNetworkDefParseXML(virConnectPtr conn,
                       xmlXPathContextPtr ctxt)
@@ -363,7 +408,7 @@ virNetworkDefParseXML(virConnectPtr conn,
         /* XXX someday we want IPv6 too, so inet_aton won't work there */
         struct in_addr inaddress, innetmask;
         char *netaddr;
-        xmlNodePtr dhcp;
+        xmlNodePtr ip;
 
         if (inet_pton(AF_INET, def->ipAddress, &inaddress) <= 0) {
             virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR,
@@ -386,8 +431,8 @@ virNetworkDefParseXML(virConnectPtr conn,
             goto error;
         }
 
-        if ((dhcp = virXPathNode(conn, "./ip[1]/dhcp[1]", ctxt)) &&
-            virNetworkDHCPRangeDefParseXML(conn, def, dhcp) < 0)
+        if ((ip = virXPathNode(conn, "./ip[1]", ctxt)) &&
+            virNetworkIPParseXML(conn, def, ip) < 0)
             goto error;
     }
 
@@ -605,6 +650,10 @@ char *virNetworkDefFormat(virConnectPtr conn,
 
         virBufferAddLit(&buf, ">\n");
 
+        if (def->tftproot) {
+            virBufferEscapeString(&buf, "    <tftp root='%s' />\n",
+                                  def->tftproot);
+        }
         if ((def->nranges || def->nhosts)) {
             int i;
             virBufferAddLit(&buf, "    <dhcp>\n");
@@ -621,6 +670,11 @@ char *virNetworkDefFormat(virConnectPtr conn,
                     virBufferVSprintf(&buf, "ip='%s' ", def->hosts[i].ip);
                 virBufferAddLit(&buf, "/>\n");
             }
+            if (def->bootfile) {
+                virBufferEscapeString(&buf, "      <bootp file='%s' />\n",
+                                      def->bootfile);
+            }
+
             virBufferAddLit(&buf, "    </dhcp>\n");
         }
 
diff --git a/src/network_conf.h b/src/network_conf.h
index 4076f9a..e983a01 100644
--- a/src/network_conf.h
+++ b/src/network_conf.h
@@ -78,6 +78,9 @@ struct _virNetworkDef {
 
     unsigned int nhosts;         /* Zero or more dhcp hosts */
     virNetworkDHCPHostDefPtr hosts;
+
+    char *tftproot;
+    char *bootfile;
 };
 
 typedef struct _virNetworkObj virNetworkObj;
diff --git a/src/network_driver.c b/src/network_driver.c
index 49855bf..2fe5c00 100644
--- a/src/network_driver.c
+++ b/src/network_driver.c
@@ -400,6 +400,10 @@ 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 */
+        (network->def->tftproot ? 3 : 0) +
+        /* --dhcp-boot pxeboot.img */
+        (network->def->bootfile ? 2 : 0) +
         1;  /* NULL */
 
     if (VIR_ALLOC_N(*argv, len) < 0)
@@ -478,6 +482,16 @@ networkBuildDnsmasqArgv(virConnectPtr conn,
         APPEND_ARG(*argv, i++, buf);
     }
 
+    if (network->def->tftproot) {
+        APPEND_ARG(*argv, i++, "--enable-tftp");
+        APPEND_ARG(*argv, i++, "--tftp-root");
+        APPEND_ARG(*argv, i++, network->def->tftproot);
+    }
+    if (network->def->bootfile) {
+        APPEND_ARG(*argv, i++, "--dhcp-boot");
+        APPEND_ARG(*argv, i++, network->def->bootfile);
+    }
+
 #undef APPEND_ARG
 
     return 0;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 74e98d1..2699343 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -51,6 +51,7 @@ EXTRA_DIST =		\
 	capabilityschematest \
 	capabilityschemadata \
 	networkschematest \
+	networkschemadata \
 	domainschematest \
 	domainschemadata \
 	interfaceschemadata \
diff --git a/tests/networkschemadata/netboot-network.xml b/tests/networkschemadata/netboot-network.xml
new file mode 100644
index 0000000..7274ee6
--- /dev/null
+++ b/tests/networkschemadata/netboot-network.xml
@@ -0,0 +1,12 @@
+<network>
+  <name>netboot</name>
+  <bridge name="virbr1" />
+  <forward/>
+  <ip address="192.168.122.1" netmask="255.255.255.0">
+    <tftp root="/var/lib/tftproot" />
+    <dhcp>
+      <range start="192.168.122.2" end="192.168.122.254" />
+      <bootp file="pxeboot.img" />
+    </dhcp>
+  </ip>
+</network>
diff --git a/tests/networkschematest b/tests/networkschematest
index 1d7cffc..a1491e1 100755
--- a/tests/networkschematest
+++ b/tests/networkschematest
@@ -3,7 +3,7 @@
 test -z "$srcdir" && srcdir=`pwd`
 test -z "$abs_srcdir" && abs_srcdir=`pwd`
 
-DIRS="../qemud"
+DIRS="../qemud networkschemadata"
 
 n=0
 f=0
-- 
1.6.2.5

--
Libvir-list mailing list
Libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list

[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]