This is in response to bugzilla 664629
https://bugzilla.redhat.com/show_bug.cgi?id=664629
The patch below returns an appropriate error message if the chain of
nwfilters is found to contain unresolvable variables and therefore
cannot be instantiated.
Example: The following XMl added to a domain:
<interface type='bridge'>
<mac address='52:54:00:9f:80:45'/>
<source bridge='virbr0'/>
<model type='virtio'/>
<filterref filter='test'/>
</interface>
that references the following filter
<filter name='test' chain='root'>
<filterref filter='clean-traffic'/>
<filterref filter='allow-dhcp-server'/>
</filter>
now displays upon 'virsh start mydomain'
error: Failed to start domain mydomain
error: internal error Cannot instantiate filter due to unresolvable variable: DHCPSERVER
'DHPCSERVER' is contained in allow-dhcp-server.
Signed-off-by: Stefan Berger <stefanb(a)linux.vnet.ibm.com>
---
src/nwfilter/nwfilter_gentech_driver.c | 84 +++++++++++++++++++++++++++++++--
1 file changed, 80 insertions(+), 4 deletions(-)
Index: libvirt-acl/src/nwfilter/nwfilter_gentech_driver.c
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_gentech_driver.c
+++ libvirt-acl/src/nwfilter/nwfilter_gentech_driver.c
@@ -200,6 +200,68 @@ virNWFilterCreateVarHashmap(char *macadd
/**
+ * Convert a virNWFilterHashTable into a string of comma-separated
+ * variable names.
+ */
+struct printString
+{
+ virBuffer buf;
+ const char *separator;
+ bool reportMAC;
+ bool reportIP;
+};
+
+
+static void
+_printString(void *payload ATTRIBUTE_UNUSED, const void *name, void *data)
+{
+ struct printString *ps = data;
+
+ if ((STREQ((char *)name, NWFILTER_STD_VAR_IP ) && !ps->reportIP ) ||
+ (STREQ((char *)name, NWFILTER_STD_VAR_MAC) && !ps->reportMAC))
+ return;
+
+ if (virBufferUse(&ps->buf) && ps->separator)
+ virBufferAdd(&ps->buf, ps->separator, -1);
+
+ virBufferAdd(&ps->buf, name, -1);
+}
+
+/**
+ * virNWFilterPrintVars
+ *
+ * @var: hash table containing variables
+ * @separaptro: separator to use between variable names, i.e., ", "
+ * @reportMAC: whether to report the 'MAC' variable
+ * @reportIP : whether to report the IP variable
+ *
+ * Returns a string of comma separated variable names
+ */
+static char *
+virNWFilterPrintVars(virHashTablePtr vars,
+ const char *separator,
+ bool reportMAC,
+ bool reportIP)
+{
+ struct printString ps = {
+ .buf = VIR_BUFFER_INITIALIZER,
+ .separator = separator,
+ .reportMAC = reportMAC,
+ .reportIP = reportIP,
+ };
+
+ virHashForEach(vars, _printString, &ps);
+
+ if (virBufferError(&ps.buf)) {
+ virBufferFreeAndReset(&ps.buf);
+ virReportOOMError();
+ return NULL;
+ }
+ return virBufferContentAndReset(&ps.buf);
+}
+
+
+/**
* virNWFilterRuleInstantiate:
* @conn: pointer to virConnect object
* @techdriver: the driver to use for instantiation
@@ -575,6 +637,7 @@ virNWFilterInstantiate(virConnectPtr con
virNWFilterRuleInstPtr *insts = NULL;
void **ptrs = NULL;
int instantiate = 1;
+ char *buf;
virNWFilterHashTablePtr missing_vars = virNWFilterHashTableCreate(0);
if (!missing_vars) {
@@ -607,11 +670,9 @@ virNWFilterInstantiate(virConnectPtr con
}
goto err_exit;
}
- rc = 1;
- goto err_exit;
+ goto err_unresolvable_vars;
} else if (virHashSize(missing_vars->hashTable) > 1) {
- rc = 1;
- goto err_exit;
+ goto err_unresolvable_vars;
} else if (!forceWithPendingReq &&
virNWFilterLookupLearnReq(ifindex) != NULL) {
goto err_exit;
@@ -674,6 +735,21 @@ err_exit:
virNWFilterHashTableFree(missing_vars);
return rc;
+
+err_unresolvable_vars:
+
+ buf = virNWFilterPrintVars(missing_vars->hashTable, ", ", false,
false);
+ if (buf) {
+ virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Cannot instantiate filter due to unresolvable "
+ "variable%s: %s"),
+ strstr(buf, ", ") ? "s" : "",
+ buf);
+ VIR_FREE(buf);
+ }
+
+ rc = 1;
+ goto err_exit;
}