On 02/12/2014 07:07 PM, Michal Privoznik wrote:
Basically, the idea is copied from domain code, where tainting
exists for a while. Currently, only one taint reason exists -
VIR_NETWORK_TAINT_HOOK to mark those networks which caused invoking
of hook script.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/conf/network_conf.c | 52 ++++++++++++++++++++++++++++++++++++++++++++-
src/conf/network_conf.h | 17 +++++++++++++++
src/libvirt_private.syms | 3 +++
src/network/bridge_driver.c | 20 +++++++++++++++++
4 files changed, 91 insertions(+), 1 deletion(-)
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 8b6236d..bac0465 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -72,6 +72,22 @@ VIR_ENUM_IMPL(virNetworkDNSForwardPlainNames,
"yes",
"no")
+VIR_ENUM_IMPL(virNetworkTaint, VIR_NETWORK_TAINT_LAST,
+ "hook-script");
+
+bool
+virNetworkObjTaint(virNetworkObjPtr obj,
+ enum virNetworkTaintFlags taint)
+{
+ unsigned int flag = (1 << taint);
+
+ if (obj->taint & flag)
+ return false;
+
+ obj->taint |= flag;
+ return true;
+}
+
virNetworkObjPtr virNetworkFindByUUID(virNetworkObjListPtr nets,
const unsigned char *uuid)
{
@@ -2784,6 +2800,7 @@ virNetworkObjFormat(virNetworkObjPtr net,
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
char *class_id = virBitmapFormat(net->class_id);
+ size_t i;
if (!class_id)
goto no_memory;
@@ -2793,6 +2810,12 @@ virNetworkObjFormat(virNetworkObjPtr net,
virBufferAsprintf(&buf, " <floor sum='%llu'/>\n",
net->floor_sum);
VIR_FREE(class_id);
+ for (i = 0; i < VIR_NETWORK_TAINT_LAST; i++) {
+ if (net->taint & (1 << i))
+ virBufferAsprintf(&buf, " <taint
flag='%s'/>\n",
+ virNetworkTaintTypeToString(i));
+ }
+
virBufferAdjustIndent(&buf, 2);
if (virNetworkDefFormatBuf(&buf, net->def, flags) < 0)
goto error;
@@ -2903,10 +2926,13 @@ virNetworkLoadState(virNetworkObjListPtr nets,
virNetworkDefPtr def = NULL;
virNetworkObjPtr net = NULL;
xmlDocPtr xml = NULL;
- xmlNodePtr node = NULL;
+ xmlNodePtr node = NULL, *nodes = NULL;
xmlXPathContextPtr ctxt = NULL;
virBitmapPtr class_id_map = NULL;
unsigned long long floor_sum_val = 0;
+ unsigned int taint = 0;
+ int n;
+ size_t i;
if ((configFile = virNetworkConfigFile(stateDir, name)) == NULL)
@@ -2962,6 +2988,27 @@ virNetworkLoadState(virNetworkObjListPtr nets,
goto error;
}
VIR_FREE(floor_sum);
+
+ if ((n = virXPathNodeSet("./taint", ctxt, &nodes)) < 0)
+ goto error;
+
+ for (i = 0; i < n; i++) {
+ char *str = virXMLPropString(nodes[i], "flag");
+ if (str) {
+ int flag = virNetworkTaintTypeFromString(str);
+ if (flag < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Unknown taint flag %s"), str);
+ VIR_FREE(str);
+ goto error;
+ }
+ VIR_FREE(str);
+ /* Compute taint mask here. The network object does not
+ * exist yet, so we can't use virNetworkObjtTaint. */
+ taint |= (1 << flag);
+ }
+ }
+ VIR_FREE(nodes);
}
/* create the object */
@@ -2978,6 +3025,8 @@ virNetworkLoadState(virNetworkObjListPtr nets,
if (floor_sum_val > 0)
net->floor_sum = floor_sum_val;
+ net->taint = taint;
+
cleanup:
VIR_FREE(configFile);
xmlFreeDoc(xml);
@@ -2985,6 +3034,7 @@ cleanup:
return net;
error:
+ VIR_FREE(nodes);
virBitmapFree(class_id_map);
virNetworkDefFree(def);
goto cleanup;
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 47124ce..3abe180 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -287,6 +287,8 @@ struct _virNetworkObj {
virBitmapPtr class_id; /* bitmap of class IDs for QoS */
unsigned long long floor_sum; /* sum of all 'floor'-s of attached NICs */
+
+ unsigned int taint;
};
typedef struct _virNetworkObjList virNetworkObjList;
@@ -296,12 +298,26 @@ struct _virNetworkObjList {
virNetworkObjPtr *objs;
};
+enum virNetworkTaintFlags {
+ VIR_NETWORK_TAINT_HOOK, /* Hook script was executed over
+ network. We can't guarantee
+ connectivity or other settings
+ as the script may have played
+ with iptables, tc, you name it.
+ */
+
+ VIR_NETWORK_TAINT_LAST
+};
+
static inline int
virNetworkObjIsActive(const virNetworkObj *net)
{
return net->active;
}
+bool virNetworkObjTaint(virNetworkObjPtr obj,
+ enum virNetworkTaintFlags taint);
+
virNetworkObjPtr virNetworkFindByUUID(virNetworkObjListPtr nets,
const unsigned char *uuid);
virNetworkObjPtr virNetworkFindByName(virNetworkObjListPtr nets,
@@ -455,4 +471,5 @@ virNetworkDefUpdateSection(virNetworkDefPtr def,
const char *xml,
unsigned int flags); /* virNetworkUpdateFlags */
+VIR_ENUM_DECL(virNetworkTaint)
#endif /* __NETWORK_CONF_H__ */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index b554f11..ab4be02 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -528,6 +528,7 @@ virNetworkObjListFree;
virNetworkObjLock;
virNetworkObjReplacePersistentDef;
virNetworkObjSetDefTransient;
+virNetworkObjTaint;
virNetworkObjUnlock;
virNetworkObjUnsetDefTransient;
virNetworkObjUpdate;
@@ -536,6 +537,8 @@ virNetworkSaveConfig;
virNetworkSaveStatus;
virNetworkSetBridgeMacAddr;
virNetworkSetBridgeName;
+virNetworkTaintTypeFromString;
+virNetworkTaintTypeToString;
virPortGroupFindByName;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 6a2d56a..ee264b9 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -112,6 +112,9 @@ static int networkPlugBandwidth(virNetworkObjPtr net,
static int networkUnplugBandwidth(virNetworkObjPtr net,
virDomainNetDefPtr iface);
+static void networkNetworkObjTaint(virNetworkObjPtr net,
+ enum virNetworkTaintFlags taint);
+
static virNetworkDriverStatePtr driverState = NULL;
static virNetworkObjPtr
@@ -169,6 +172,8 @@ networkRunHook(virNetworkObjPtr network,
*/
if (hookret < 0)
goto cleanup;
+
+ networkNetworkObjTaint(network, VIR_NETWORK_TAINT_HOOK);
}
ret = 0;
@@ -4344,3 +4349,18 @@ networkUnplugBandwidth(virNetworkObjPtr net,
cleanup:
return ret;
}
+
+static void
+networkNetworkObjTaint(virNetworkObjPtr net,
+ enum virNetworkTaintFlags taint)
+{
+ if (virNetworkObjTaint(net, taint)) {
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ virUUIDFormat(net->def->uuid, uuidstr);
+
+ VIR_WARN("Network name='%s' uuid=%s is tainted: %s",
+ net->def->name,
+ uuidstr,
+ virNetworkTaintTypeToString(taint));
+ }
+}
It's occurred to me that if a hook script exists, then all networks on
the host will be tainted. That made me wonder how useful this really
is... (I guess if nothing else it makes it simpler when debugging
someone else's problem - just asking for the output of "virsh
net-dumpxml $netname" will tell us whether or not they're running a hook
script, rather than relying on them to tell us...). So, okay ACK.