https://gitlab.com/libvirt/libvirt/-/issues/13
Add support for downscript:
<interface type='ethernet'>
<mac address='00:11:22:33:44:55'/>
<script path='/etc/qemu-ifup'/>
<downscript path='/path/to/my/downscript'/>
</interface>
Signed-off-by: Chen Hanxiao <chen_han_xiao(a)126.com>
---
docs/schemas/domaincommon.rng | 8 ++++++++
src/conf/domain_conf.c | 9 +++++++++
src/conf/domain_conf.h | 1 +
src/qemu/qemu_extdevice.c | 4 ++++
src/qemu/qemu_hotplug.c | 6 ++++++
5 files changed, 28 insertions(+)
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 9d60b090f3..6727cd743b 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3191,6 +3191,14 @@
<empty/>
</element>
</optional>
+ <optional>
+ <element name="downscript">
+ <attribute name="path">
+ <ref name="filePath"/>
+ </attribute>
+ <empty/>
+ </element>
+ </optional>
<optional>
<element name="backenddomain">
<attribute name="name">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index c201fc901d..1406cf079e 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2520,6 +2520,7 @@ virDomainNetDefClear(virDomainNetDefPtr def)
VIR_FREE(def->teaming.persistent);
VIR_FREE(def->virtPortProfile);
VIR_FREE(def->script);
+ VIR_FREE(def->downscript);
VIR_FREE(def->domain_name);
VIR_FREE(def->ifname);
VIR_FREE(def->ifname_guest);
@@ -11977,6 +11978,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
g_autofree char *ifname_guest = NULL;
g_autofree char *ifname_guest_actual = NULL;
g_autofree char *script = NULL;
+ g_autofree char *downscript = NULL;
g_autofree char *address = NULL;
g_autofree char *port = NULL;
g_autofree char *localaddr = NULL;
@@ -12149,6 +12151,9 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
} else if (!script &&
virXMLNodeNameEqual(cur, "script")) {
script = virXMLPropString(cur, "path");
+ } else if (!downscript &&
+ virXMLNodeNameEqual(cur, "downscript")) {
+ downscript = virXMLPropString(cur, "path");
} else if (!domain_name &&
virXMLNodeNameEqual(cur, "backenddomain")) {
domain_name = virXMLPropString(cur, "name");
@@ -12482,6 +12487,8 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
if (script != NULL)
def->script = g_steal_pointer(&script);
+ if (downscript != NULL)
+ def->downscript = g_steal_pointer(&downscript);
if (domain_name != NULL)
def->domain_name = g_steal_pointer(&domain_name);
if (ifname != NULL)
@@ -26567,6 +26574,8 @@ virDomainNetDefFormat(virBufferPtr buf,
virBufferEscapeString(buf, "<script path='%s'/>\n",
def->script);
+ virBufferEscapeString(buf, "<downscript path='%s'/>\n",
+ def->downscript);
virBufferEscapeString(buf, "<backenddomain name='%s'/>\n",
def->domain_name);
if (def->ifname &&
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index ddc75d8de2..e152c599ca 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1055,6 +1055,7 @@ struct _virDomainNetDef {
unsigned long sndbuf;
} tune;
char *script;
+ char *downscript;
char *domain_name; /* backend domain name */
char *ifname; /* interface name on the host (<target dev='x'/>) */
int managed_tap; /* enum virTristateBool - ABSENT == YES */
diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c
index 2096272761..4962521de4 100644
--- a/src/qemu/qemu_extdevice.c
+++ b/src/qemu/qemu_extdevice.c
@@ -213,6 +213,7 @@ qemuExtDevicesStop(virQEMUDriverPtr driver,
virDomainObjPtr vm)
{
virDomainDefPtr def = vm->def;
+ virDomainNetType actualType;
size_t i;
if (qemuExtDevicesInitPaths(driver, def) < 0)
@@ -230,10 +231,13 @@ qemuExtDevicesStop(virQEMUDriverPtr driver,
for (i = 0; i < def->nnets; i++) {
virDomainNetDefPtr net = def->nets[i];
+ actualType = virDomainNetGetActualType(net);
qemuSlirpPtr slirp = QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp;
if (slirp)
qemuSlirpStop(slirp, vm, driver, net);
+ if (actualType == VIR_DOMAIN_NET_TYPE_ETHERNET && net->downscript)
+ virNetDevRunEthernetScript(net->ifname, net->downscript);
}
for (i = 0; i < def->nfss; i++) {
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 5608566d69..97c6508a55 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -5942,6 +5942,12 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm,
ret = qemuDomainRemoveDevice(driver, vm, &detach);
}
+ if ((virDomainDeviceType)match->type == VIR_DOMAIN_DEVICE_NET) {
+ virDomainNetDefPtr net =
detach.data.net;
+ if (net->script)
+ virNetDevRunEthernetScript(net->ifname, net->downscript);
+ }
The fact that you need to typecast the comparison should have raised a
red flag. But this is not placed correctly anyway. The way the device
detach works is:
1) we send the detach request to qemu, which in turn sends it to the guest
2) we wait couple of seconds to see whether the detach was successful,
if it was, then qemuDomainRemoveDevice() is called, which handles the
device removal and cleanup (e.g. executing down scripts)
3) if the detach timed out, then the control is returned back to user
and we wait for DEVICE_DEL event, which eventually comes and then the
qemuDomainRemoveDevice() is called, which calls the down script.
Therefore, the proper place and form is:
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index d831fcd4a6..7dde7c0c75 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -4672,7 +4672,11 @@ qemuDomainRemoveNetDevice(virQEMUDriverPtr driver,
virDomainNetReleaseActualDevice(conn, vm->def, net);
else
VIR_WARN("Unable to release network device '%s'",
NULLSTR(net->ifname));
+ } else if (net->type == VIR_DOMAIN_NET_TYPE_ETHERNET) {
+ if (net->script)
+ virNetDevRunEthernetScript(net->ifname, net->downscript);
}
+
virDomainNetDefFree(net);
return 0;
}
For the rest see my comment to the cover letter.
Michal