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(a)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;