From 9de7309125d644360b59b84e40cf40c031b09b3d Mon Sep 17 00:00:00 2001 From: Michal Privoznik Date: Tue, 4 Feb 2014 17:36:54 +0100 Subject: [PATCH] network: Taint networks that are using hook script 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 --- 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 8b6236d878..bac04657d1 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 47124ce818..3abe180003 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 cd6c87a566..2eead3d6de 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 6a2d56ae4f..ee264b9989 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)); + } +}