diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 8b6236d878148a0a29c881bb6aff07ea1134f728..bac04657d162367af292dfea66b03c2a9cd044ca 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, " \n", net->floor_sum);
VIR_FREE(class_id);
+ for (i = 0; i < VIR_NETWORK_TAINT_LAST; i++) {
+ if (net->taint & (1 << i))
+ virBufferAsprintf(&buf, " \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 47124ce81825aa1b094c7aed446e400f31de1fc9..3abe1800035182d2caeefdd3c0aa791a25c88b8a 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 cd6c87a566b0505398ff6f35fc61b69aa45dd006..2eead3d6def7d6a3bf2484460909da0ca310bfde 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -529,6 +529,7 @@ virNetworkObjListFree;
virNetworkObjLock;
virNetworkObjReplacePersistentDef;
virNetworkObjSetDefTransient;
+virNetworkObjTaint;
virNetworkObjUnlock;
virNetworkObjUnsetDefTransient;
virNetworkObjUpdate;
@@ -537,6 +538,8 @@ virNetworkSaveConfig;
virNetworkSaveStatus;
virNetworkSetBridgeMacAddr;
virNetworkSetBridgeName;
+virNetworkTaintTypeFromString;
+virNetworkTaintTypeToString;
virPortGroupFindByName;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 6a2d56ae4f249f7fe9972d0ebc87dd27a1487627..ee264b99891636f5cd4b367a2afc47db26d1896b 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));
+ }
+}