From: root <root(a)vlap.laine.org>
This patch adds the flag VIR_INTERFACE_XML_INACTIVE to
virInterfaceGetXMLDesc's flags. When it is *not* set (the default),
the live interface info will be returned in the XML. in particular,
the IP address(es) and netmask(s) will be retrieved by querying the
device directly, rather than just reporting what's in the config
file. The backend of this is in netcf's new ncf_if_xml_state()
function.
Any live interface ip address info in the xml will have the property
"source" set to "device", eg:
<ip address='10.24.0.1' prefix='24'
source='device'/>
Also, if an interface is currently inactive, no ip addresses will be
returned, since an inactive interface device can't be queried for IP
addresses (effectively it has none).
A difference in the XML from previously - it is now acceptable to have
both a dhcp *and* an ip node (or neither) within the protocol
node. Before you had to have one or the other, but couldn't have both.
Note that you need at least netcf 0.1.2 for this to build and work,
and an upcoming release (patches submitted today) for it to work
exactly as described above.
---
include/libvirt/libvirt.h.in | 4 +++
src/conf/interface_conf.c | 62 ++++++++++++++++++++++-------------------
src/conf/interface_conf.h | 1 +
src/interface/netcf_driver.c | 8 ++++-
src/libvirt.c | 15 +++++++---
tools/virsh.c | 10 +++++-
6 files changed, 63 insertions(+), 37 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 4e63e48..fd0c90b 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -922,6 +922,10 @@ virInterfacePtr virInterfaceLookupByMACString (virConnectPtr
conn,
const char* virInterfaceGetName (virInterfacePtr iface);
const char* virInterfaceGetMACString (virInterfacePtr iface);
+typedef enum {
+ VIR_INTERFACE_XML_INACTIVE = 1 /* dump inactive interface information */
+} virInterfaceXMLFlags;
+
char * virInterfaceGetXMLDesc (virInterfacePtr iface,
unsigned int flags);
virInterfacePtr virInterfaceDefineXML (virConnectPtr conn,
diff --git a/src/conf/interface_conf.c b/src/conf/interface_conf.c
index e646351..b422464 100644
--- a/src/conf/interface_conf.c
+++ b/src/conf/interface_conf.c
@@ -92,6 +92,7 @@ void virInterfaceDefFree(virInterfaceDefPtr def)
VIR_FREE(def->proto.family);
VIR_FREE(def->proto.address);
VIR_FREE(def->proto.gateway);
+ VIR_FREE(def->proto.source);
VIR_FREE(def);
}
@@ -272,6 +273,8 @@ virInterfaceDefParseIp(virConnectPtr conn, virInterfaceDefPtr def,
"%s", _("Invalid ip address prefix
value"));
return(-1);
}
+ tmp = virXPathString(conn, "string(./ip[1]/@source)", ctxt);
+ def->proto.source = tmp;
}
tmp = virXPathString(conn, "string(./route[1]/@gateway)", ctxt);
def->proto.gateway = tmp;
@@ -282,22 +285,19 @@ virInterfaceDefParseIp(virConnectPtr conn, virInterfaceDefPtr def,
static int
virInterfaceDefParseProtoIPv4(virConnectPtr conn, virInterfaceDefPtr def,
xmlXPathContextPtr ctxt) {
- xmlNodePtr cur;
- int ret;
+ xmlNodePtr dhcp, ip;
+ int ret = 0;
- cur = virXPathNode(conn, "./dhcp", ctxt);
- if (cur != NULL)
- ret = virInterfaceDefParseDhcp(conn, def, cur, ctxt);
- else {
- cur = virXPathNode(conn, "./ip", ctxt);
- if (cur != NULL)
- ret = virInterfaceDefParseIp(conn, def, cur, ctxt);
- else {
- virInterfaceReportError(conn, VIR_ERR_XML_ERROR,
- "%s", _("interface miss dhcp or ip
adressing"));
- ret = -1;
- }
- }
+ dhcp = virXPathNode(conn, "./dhcp", ctxt);
+ if (dhcp != NULL)
+ ret = virInterfaceDefParseDhcp(conn, def, dhcp, ctxt);
+
+ if (ret != 0)
+ return(ret);
+
+ ip = virXPathNode(conn, "./ip", ctxt);
+ if (ip != NULL)
+ ret = virInterfaceDefParseIp(conn, def, ip, ctxt);
return(ret);
}
@@ -1005,6 +1005,7 @@ virInterfaceVlanDefFormat(virConnectPtr conn, virBufferPtr buf,
static int
virInterfaceProtocolDefFormat(virConnectPtr conn ATTRIBUTE_UNUSED,
virBufferPtr buf, const virInterfaceDefPtr def) {
+ char prefixStr[16];
if (def->proto.family == NULL)
return(0);
virBufferVSprintf(buf, " <protocol family='%s'>\n",
def->proto.family);
@@ -1015,20 +1016,23 @@ virInterfaceProtocolDefFormat(virConnectPtr conn
ATTRIBUTE_UNUSED,
virBufferAddLit(buf, " <dhcp peerdns='yes'/>\n");
else
virBufferAddLit(buf, " <dhcp/>\n");
- } else {
- /* theorically if we don't have dhcp we should have an address */
- if (def->proto.address != NULL) {
- if (def->proto.prefix != 0)
- virBufferVSprintf(buf, " <ip address='%s'
prefix='%d'/>\n",
- def->proto.address, def->proto.prefix);
- else
- virBufferVSprintf(buf, " <ip
address='%s'/>\n",
- def->proto.address);
- }
- if (def->proto.gateway != NULL) {
- virBufferVSprintf(buf, " <route
gateway='%s'/>\n",
- def->proto.gateway);
- }
+ }
+ if (def->proto.address != NULL) {
+ if (def->proto.prefix != 0)
+ snprintf(prefixStr, sizeof(prefixStr), "%d",
def->proto.prefix);
+
+ virBufferVSprintf(buf, " <ip
address='%s'%s%s%s%s%s%s/>\n",
+ def->proto.address,
+ def->proto.prefix ? " prefix='" :
"",
+ def->proto.prefix ? prefixStr : "",
+ def->proto.prefix ? "'" :
"",
+ def->proto.source ? " source='" :
"",
+ def->proto.source ? def->proto.source : "",
+ def->proto.source ? "'" :
"");
+ }
+ if (def->proto.gateway != NULL) {
+ virBufferVSprintf(buf, " <route gateway='%s'/>\n",
+ def->proto.gateway);
}
virBufferAddLit(buf, " </protocol>\n");
return(0);
diff --git a/src/conf/interface_conf.h b/src/conf/interface_conf.h
index bb9dce4..df871aa 100644
--- a/src/conf/interface_conf.h
+++ b/src/conf/interface_conf.h
@@ -132,6 +132,7 @@ struct _virInterfaceProtocolDef {
char *address; /* ip address */
int prefix; /* ip prefix */
char *gateway; /* route gateway */
+ char *source; /* source of address - "device" or "config"
(default) */
};
diff --git a/src/interface/netcf_driver.c b/src/interface/netcf_driver.c
index ca14fb0..b5c3664 100644
--- a/src/interface/netcf_driver.c
+++ b/src/interface/netcf_driver.c
@@ -326,7 +326,7 @@ cleanup:
}
static char *interfaceGetXMLDesc(virInterfacePtr ifinfo,
- unsigned int flags ATTRIBUTE_UNUSED)
+ unsigned int flags)
{
struct interface_driver *driver = ifinfo->conn->interfacePrivateData;
struct netcf_if *iface = NULL;
@@ -342,7 +342,11 @@ static char *interfaceGetXMLDesc(virInterfacePtr ifinfo,
goto cleanup;
}
- xmlstr = ncf_if_xml_desc(iface);
+ if ((flags & VIR_INTERFACE_XML_INACTIVE)) {
+ xmlstr = ncf_if_xml_desc(iface);
+ } else {
+ xmlstr = ncf_if_xml_state(iface);
+ }
if (!xmlstr) {
const char *errmsg, *details;
int errcode = ncf_error(driver->netcf, &errmsg, &details);
diff --git a/src/libvirt.c b/src/libvirt.c
index bcb89e1..bd712dc 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -5915,10 +5915,17 @@ virInterfaceGetMACString(virInterfacePtr iface)
/**
* virInterfaceGetXMLDesc:
* @iface: an interface object
- * @flags: an OR'ed set of extraction flags, not used yet
+ * @flags: an OR'ed set of extraction flags. Current valid bits:
+ *
+ * VIR_INTERFACE_XML_INACTIVE - return the static configuration,
+ * suitable for use redefining the
+ * interface via virInterfaceDefineXML()
*
- * Provide an XML description of the interface. The description may be reused
- * later to redefine the interface with virInterfaceDefineXML().
+ * Provide an XML description of the interface. If
+ * VIR_INTERFACE_XML_INACTIVE is set, the description may be reused
+ * later to redefine the interface with virInterfaceDefineXML(). If it
+ * is not set, the ip address and netmask will be the current live
+ * setting of the interface, not the settings from the config files.
*
* Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case of error.
* the caller must free() the returned value.
@@ -5935,7 +5942,7 @@ virInterfaceGetXMLDesc(virInterfacePtr iface, unsigned int flags)
virLibInterfaceError(NULL, VIR_ERR_INVALID_INTERFACE, __FUNCTION__);
return (NULL);
}
- if (flags != 0) {
+ if ((flags & ~VIR_INTERFACE_XML_INACTIVE) != 0) {
virLibInterfaceError(iface, VIR_ERR_INVALID_ARG, __FUNCTION__);
goto error;
}
diff --git a/tools/virsh.c b/tools/virsh.c
index 3482389..77f1d70 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -2763,7 +2763,7 @@ cmdInterfaceEdit (vshControl *ctl, const vshCmd *cmd)
char *doc = NULL;
char *doc_edited = NULL;
char *doc_reread = NULL;
- int flags = 0;
+ int flags = VIR_INTERFACE_XML_INACTIVE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
goto cleanup;
@@ -3297,6 +3297,7 @@ static const vshCmdInfo info_interface_dumpxml[] = {
static const vshCmdOptDef opts_interface_dumpxml[] = {
{"interface", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("interface name
or MAC address")},
+ {"inactive", VSH_OT_BOOL, 0, gettext_noop("show inactive defined
XML")},
{NULL, 0, 0, NULL}
};
@@ -3306,6 +3307,11 @@ cmdInterfaceDumpXML(vshControl *ctl, const vshCmd *cmd)
virInterfacePtr iface;
int ret = TRUE;
char *dump;
+ int flags = 0;
+ int inactive = vshCommandOptBool(cmd, "inactive");
+
+ if (inactive)
+ flags |= VIR_INTERFACE_XML_INACTIVE;
if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
return FALSE;
@@ -3313,7 +3319,7 @@ cmdInterfaceDumpXML(vshControl *ctl, const vshCmd *cmd)
if (!(iface = vshCommandOptInterface(ctl, cmd, NULL)))
return FALSE;
- dump = virInterfaceGetXMLDesc(iface, 0);
+ dump = virInterfaceGetXMLDesc(iface, flags);
if (dump != NULL) {
printf("%s", dump);
free(dump);
--
1.6.2.5