mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
network: Introduce network hooks
There might be some use cases, where user wants to prepare the host or its environment prior to starting a network and do some cleanup after the network has been shut down. Consider all the functionality that libvirt doesn't currently have as an example what a hook script can possibly do. Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
e0a31274ec
commit
f1ab06e43d
@ -13,9 +13,15 @@
|
||||
actions occur:</p>
|
||||
<ul>
|
||||
<li>The libvirt daemon starts, stops, or reloads its
|
||||
configuration<br/><br/></li>
|
||||
<li>A QEMU guest is started or stopped<br/><br/></li>
|
||||
<li>An LXC guest is started or stopped<br/><br/></li>
|
||||
configuration
|
||||
(<span class="since">since 0.8.0</span>)<br/><br/></li>
|
||||
<li>A QEMU guest is started or stopped
|
||||
(<span class="since">since 0.8.0</span>)<br/><br/></li>
|
||||
<li>An LXC guest is started or stopped
|
||||
(<span class="since">since 0.8.0</span>)<br/><br/></li>
|
||||
<li>A network is started or stopped or an interface is
|
||||
plugged/unplugged to/from the network
|
||||
(<span class="since">since 1.2.2</span>)<br/><br/></li>
|
||||
</ul>
|
||||
|
||||
<h2><a name="location">Script location</a></h2>
|
||||
@ -44,6 +50,9 @@
|
||||
Executed when a QEMU guest is started, stopped, or migrated<br/><br/></li>
|
||||
<li><code>/etc/libvirt/hooks/lxc</code><br /><br/>
|
||||
Executed when an LXC guest is started or stopped</li>
|
||||
<li><code>/etc/libvirt/hooks/network</code><br/><br/>
|
||||
Executed when a network is started or stopped or an
|
||||
interface is plugged/unplugged to/from the network</li>
|
||||
</ul>
|
||||
<br/>
|
||||
|
||||
@ -66,6 +75,39 @@
|
||||
XML description for the domain on their stdin. This includes items
|
||||
such the UUID of the domain and its storage information, and is
|
||||
intended to provide all the libvirt information the script needs.</p>
|
||||
<p>For all cases, stdin of the network hook script is provided with the
|
||||
full XML description of the network status in the following form:</p>
|
||||
|
||||
<pre><hookData>
|
||||
<network>
|
||||
<name>$network_name</name>
|
||||
<uuid>afca425a-2c3a-420c-b2fb-dd7b4950d722</uuid>
|
||||
...
|
||||
</network>
|
||||
</hookData></pre>
|
||||
|
||||
<p>In the case of an interface
|
||||
being plugged/unplugged to/from the network, the network XML will be
|
||||
followed with the full XML description of the domain containing the
|
||||
interface that is being plugged/unplugged:</p>
|
||||
|
||||
<pre><hookData>
|
||||
<network>
|
||||
<name>$network_name</name>
|
||||
<uuid>afca425a-2c3a-420c-b2fb-dd7b4950d722</uuid>
|
||||
...
|
||||
</network>
|
||||
<domain type='$domain_type' id='$domain_id'>
|
||||
<name>$domain_name</name>
|
||||
<uuid>afca425a-2c3a-420c-b2fb-dd7b4950d722</uuid>
|
||||
...
|
||||
</domain>
|
||||
</hookData></pre>
|
||||
|
||||
<p>Please note that this approach is different from other cases such as
|
||||
<code>daemon</code>, <code>qemu</code> or <code>lxc</code> hook scripts,
|
||||
because two XMLs may be passed here, while in the other cases only a single
|
||||
XML is passed.</p>
|
||||
|
||||
<p>The command line arguments take this approach:</p>
|
||||
<ol>
|
||||
@ -181,25 +223,49 @@
|
||||
<pre>/etc/libvirt/hooks/lxc guest_name reconnect begin -</pre>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h5><a name="network">/etc/libvirt/hooks/network</a></h5>
|
||||
<ul>
|
||||
<li><span class="since">Since 1.2.2</span>, before a network is started,
|
||||
this script is called as:<br/>
|
||||
<pre>/etc/libvirt/hooks/network network_name start begin -</pre></li>
|
||||
<li>After the network is started, up ∧ running, the script is
|
||||
called as:<br/>
|
||||
<pre>/etc/libvirt/hooks/network network_name started begin -</pre></li>
|
||||
<li>When a network is shut down, this script is called as:<br/>
|
||||
<pre>/etc/libvirt/hooks/network network_name stopped end -</pre></li>
|
||||
<li>Later, when network is started and there's an interface from a
|
||||
domain to be plugged into the network, the hook script is called as:<br/>
|
||||
<pre>/etc/libvirt/hooks/network network_name plugged begin -</pre>
|
||||
Please note, that in this case, the script is passed both network and
|
||||
domain XMLs on its stdin.</li>
|
||||
<li>When the domain from previous case is shutting down, the interface
|
||||
is unplugged. This leads to another script invocation:<br/>
|
||||
<pre>/etc/libvirt/hooks/network network_name unplugged begin -</pre>
|
||||
And again, as in previous case, both network and domain XMLs are passed
|
||||
onto script's stdin.</li>
|
||||
</ul>
|
||||
|
||||
<br/>
|
||||
|
||||
<h2><a name="execution">Script execution</a></h2>
|
||||
<ul>
|
||||
<li>The "start" operation for the guest hook scripts, qemu and lxc,
|
||||
executes <b>prior</b> to the guest being created. This allows the
|
||||
guest start operation to be aborted if the script returns indicating
|
||||
failure.<br/><br/></li>
|
||||
<li>The "shutdown" operation for the guest hook scripts, qemu and lxc,
|
||||
executes <b>after</b> the guest has stopped. If the hook script
|
||||
indicates failure in its return, the shut down of the guest cannot
|
||||
be aborted because it has already been performed.<br/><br/></li>
|
||||
<li>The "start" operation for the guest and network hook scripts,
|
||||
executes <b>prior</b> to the object (guest or network) being created.
|
||||
This allows the object start operation to be aborted if the script
|
||||
returns indicating failure.<br/><br/></li>
|
||||
<li>The "shutdown" operation for the guest and network hook scripts,
|
||||
executes <b>after</b> the object (guest or network) has stopped. If
|
||||
the hook script indicates failure in its return, the shut down of the
|
||||
object cannot be aborted because it has already been performed.
|
||||
<br/><br/></li>
|
||||
<li>Hook scripts execute in a synchronous fashion. Libvirt waits
|
||||
for them to return before continuing the given operation.<br/><br/>
|
||||
This is most noticeable with the guest start operation, as a lengthy
|
||||
operation in the hook script can mean an extended wait for the guest
|
||||
to be available to end users.<br/><br/></li>
|
||||
This is most noticeable with the guest or network start operation,
|
||||
as a lengthy operation in the hook script can mean an extended wait
|
||||
for the guest or network to be available to end users.<br/><br/></li>
|
||||
<li>For a hook script to be utilised, it must have its execute bit set
|
||||
(ie. chmod o+rx <i>qemu</i>), and must be present when the libvirt
|
||||
(e.g. chmod o+rx <i>qemu</i>), and must be present when the libvirt
|
||||
daemon is started.<br/><br/></li>
|
||||
<li>If a hook script is added to a host after the libvirt daemon is
|
||||
already running, it won't be used until the libvirt daemon
|
||||
|
@ -3937,7 +3937,7 @@ lxcDomainAttachDeviceNetLive(virConnectPtr conn,
|
||||
* network's pool of devices, or resolve bridge device name
|
||||
* to the one defined in the network definition.
|
||||
*/
|
||||
if (networkAllocateActualDevice(net) < 0)
|
||||
if (networkAllocateActualDevice(vm->def, net) < 0)
|
||||
return -1;
|
||||
|
||||
actualType = virDomainNetGetActualType(net);
|
||||
@ -4485,7 +4485,7 @@ lxcDomainDetachDeviceNetLive(virDomainObjPtr vm,
|
||||
ret = 0;
|
||||
cleanup:
|
||||
if (!ret) {
|
||||
networkReleaseActualDevice(detach);
|
||||
networkReleaseActualDevice(vm->def, detach);
|
||||
virDomainNetRemove(vm->def, detachidx);
|
||||
virDomainNetDefFree(detach);
|
||||
}
|
||||
|
@ -198,7 +198,7 @@ static void virLXCProcessCleanup(virLXCDriverPtr driver,
|
||||
iface->ifname));
|
||||
ignore_value(virNetDevVethDelete(iface->ifname));
|
||||
}
|
||||
networkReleaseActualDevice(iface);
|
||||
networkReleaseActualDevice(vm->def, iface);
|
||||
}
|
||||
|
||||
virDomainConfVMNWFilterTeardown(vm);
|
||||
@ -374,7 +374,7 @@ static int virLXCProcessSetupInterfaces(virConnectPtr conn,
|
||||
* network's pool of devices, or resolve bridge device name
|
||||
* to the one defined in the network definition.
|
||||
*/
|
||||
if (networkAllocateActualDevice(def->nets[i]) < 0)
|
||||
if (networkAllocateActualDevice(def, def->nets[i]) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (VIR_EXPAND_N(*veths, *nveths, 1) < 0)
|
||||
@ -476,7 +476,7 @@ cleanup:
|
||||
ignore_value(virNetDevOpenvswitchRemovePort(
|
||||
virDomainNetGetActualBridgeName(iface),
|
||||
iface->ifname));
|
||||
networkReleaseActualDevice(iface);
|
||||
networkReleaseActualDevice(def, iface);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
@ -71,6 +71,7 @@
|
||||
#include "virstring.h"
|
||||
#include "viraccessapicheck.h"
|
||||
#include "network_event.h"
|
||||
#include "virhook.h"
|
||||
|
||||
#define VIR_FROM_THIS VIR_FROM_NETWORK
|
||||
|
||||
@ -134,6 +135,51 @@ networkObjFromNetwork(virNetworkPtr net)
|
||||
return network;
|
||||
}
|
||||
|
||||
static int
|
||||
networkRunHook(virNetworkObjPtr network,
|
||||
virDomainDefPtr dom,
|
||||
int op,
|
||||
int sub_op)
|
||||
{
|
||||
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||
char *xml = NULL, *net_xml = NULL, *dom_xml = NULL;
|
||||
int hookret;
|
||||
int ret = -1;
|
||||
|
||||
if (virHookPresent(VIR_HOOK_DRIVER_NETWORK)) {
|
||||
virBufferAddLit(&buf, "<hookData>\n");
|
||||
virBufferAdjustIndent(&buf, 2);
|
||||
if (virNetworkDefFormatBuf(&buf, network->def, 0) < 0)
|
||||
goto cleanup;
|
||||
if (dom && virDomainDefFormatInternal(dom, 0, &buf) < 0)
|
||||
goto cleanup;
|
||||
|
||||
virBufferAdjustIndent(&buf, -2);
|
||||
virBufferAddLit(&buf, "</hookData>");
|
||||
|
||||
if (virBufferError(&buf) ||
|
||||
!(xml = virBufferContentAndReset(&buf)))
|
||||
goto cleanup;
|
||||
|
||||
hookret = virHookCall(VIR_HOOK_DRIVER_NETWORK, network->def->name,
|
||||
op, sub_op, NULL, xml, NULL);
|
||||
|
||||
/*
|
||||
* If the script raised an error, pass it to the callee.
|
||||
*/
|
||||
if (hookret < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
virBufferFreeAndReset(&buf);
|
||||
VIR_FREE(xml);
|
||||
VIR_FREE(net_xml);
|
||||
VIR_FREE(dom_xml);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *
|
||||
networkDnsmasqLeaseFileNameDefault(const char *netname)
|
||||
{
|
||||
@ -2008,6 +2054,13 @@ networkStartNetwork(virNetworkDriverStatePtr driver,
|
||||
if (virNetworkObjSetDefTransient(network, true) < 0)
|
||||
goto cleanup;
|
||||
|
||||
/* Run an early hook to set-up missing devices.
|
||||
* If the script raised an error abort the launch. */
|
||||
if (networkRunHook(network, NULL,
|
||||
VIR_HOOK_NETWORK_OP_START,
|
||||
VIR_HOOK_SUBOP_BEGIN) < 0)
|
||||
goto cleanup;
|
||||
|
||||
switch (network->def->forward.type) {
|
||||
|
||||
case VIR_NETWORK_FORWARD_NONE:
|
||||
@ -2027,6 +2080,12 @@ networkStartNetwork(virNetworkDriverStatePtr driver,
|
||||
break;
|
||||
}
|
||||
|
||||
/* finally we can call the 'started' hook script if any */
|
||||
if (networkRunHook(network, NULL,
|
||||
VIR_HOOK_NETWORK_OP_STARTED,
|
||||
VIR_HOOK_SUBOP_BEGIN) < 0)
|
||||
goto cleanup;
|
||||
|
||||
/* Persist the live configuration now that anything autogenerated
|
||||
* is setup.
|
||||
*/
|
||||
@ -2087,6 +2146,10 @@ static int networkShutdownNetwork(virNetworkDriverStatePtr driver,
|
||||
break;
|
||||
}
|
||||
|
||||
/* now that we know it's stopped call the hook if present */
|
||||
networkRunHook(network, NULL, VIR_HOOK_NETWORK_OP_STOPPED,
|
||||
VIR_HOOK_SUBOP_END);
|
||||
|
||||
network->active = 0;
|
||||
virNetworkObjUnsetDefTransient(network);
|
||||
return ret;
|
||||
@ -3239,6 +3302,7 @@ finish:
|
||||
}
|
||||
|
||||
/* networkAllocateActualDevice:
|
||||
* @dom: domain definition that @iface belongs to
|
||||
* @iface: the original NetDef from the domain
|
||||
*
|
||||
* Looks up the network reference by iface, allocates a physical
|
||||
@ -3250,7 +3314,8 @@ finish:
|
||||
* Returns 0 on success, -1 on failure.
|
||||
*/
|
||||
int
|
||||
networkAllocateActualDevice(virDomainNetDefPtr iface)
|
||||
networkAllocateActualDevice(virDomainDefPtr dom,
|
||||
virDomainNetDefPtr iface)
|
||||
{
|
||||
virNetworkDriverStatePtr driver = driverState;
|
||||
enum virDomainNetType actualType = iface->type;
|
||||
@ -3583,6 +3648,12 @@ validate:
|
||||
}
|
||||
}
|
||||
|
||||
/* finally we can call the 'plugged' hook script if any */
|
||||
if (networkRunHook(network, dom,
|
||||
VIR_HOOK_NETWORK_OP_IFACE_PLUGGED,
|
||||
VIR_HOOK_SUBOP_BEGIN) < 0)
|
||||
goto error;
|
||||
|
||||
if (dev) {
|
||||
/* we are now assured of success, so mark the allocation */
|
||||
dev->connections++;
|
||||
@ -3618,6 +3689,7 @@ error:
|
||||
}
|
||||
|
||||
/* networkNotifyActualDevice:
|
||||
* @dom: domain definition that @iface belongs to
|
||||
* @iface: the domain's NetDef with an "actual" device already filled in.
|
||||
*
|
||||
* Called to notify the network driver when libvirtd is restarted and
|
||||
@ -3628,7 +3700,8 @@ error:
|
||||
* Returns 0 on success, -1 on failure.
|
||||
*/
|
||||
int
|
||||
networkNotifyActualDevice(virDomainNetDefPtr iface)
|
||||
networkNotifyActualDevice(virDomainDefPtr dom,
|
||||
virDomainNetDefPtr iface)
|
||||
{
|
||||
virNetworkDriverStatePtr driver = driverState;
|
||||
enum virDomainNetType actualType = virDomainNetGetActualType(iface);
|
||||
@ -3781,6 +3854,11 @@ networkNotifyActualDevice(virDomainNetDefPtr iface)
|
||||
}
|
||||
|
||||
success:
|
||||
/* finally we can call the 'plugged' hook script if any */
|
||||
if (networkRunHook(network, dom, VIR_HOOK_NETWORK_OP_IFACE_PLUGGED,
|
||||
VIR_HOOK_SUBOP_BEGIN) < 0)
|
||||
goto error;
|
||||
|
||||
netdef->connections++;
|
||||
VIR_DEBUG("Using network %s, %d connections",
|
||||
netdef->name, netdef->connections);
|
||||
@ -3796,6 +3874,7 @@ error:
|
||||
|
||||
|
||||
/* networkReleaseActualDevice:
|
||||
* @dom: domain definition that @iface belongs to
|
||||
* @iface: a domain's NetDef (interface definition)
|
||||
*
|
||||
* Given a domain <interface> element that previously had its <actual>
|
||||
@ -3806,7 +3885,8 @@ error:
|
||||
* Returns 0 on success, -1 on failure.
|
||||
*/
|
||||
int
|
||||
networkReleaseActualDevice(virDomainNetDefPtr iface)
|
||||
networkReleaseActualDevice(virDomainDefPtr dom,
|
||||
virDomainNetDefPtr iface)
|
||||
{
|
||||
virNetworkDriverStatePtr driver = driverState;
|
||||
enum virDomainNetType actualType = virDomainNetGetActualType(iface);
|
||||
@ -3925,6 +4005,11 @@ networkReleaseActualDevice(virDomainNetDefPtr iface)
|
||||
success:
|
||||
if (iface->data.network.actual)
|
||||
netdef->connections--;
|
||||
|
||||
/* finally we can call the 'unplugged' hook script if any */
|
||||
networkRunHook(network, dom, VIR_HOOK_NETWORK_OP_IFACE_UNPLUGGED,
|
||||
VIR_HOOK_SUBOP_BEGIN);
|
||||
|
||||
VIR_DEBUG("Releasing network %s, %d connections",
|
||||
netdef->name, netdef->connections);
|
||||
ret = 0;
|
||||
|
@ -34,12 +34,15 @@
|
||||
int networkRegister(void);
|
||||
|
||||
# if WITH_NETWORK
|
||||
int networkAllocateActualDevice(virDomainNetDefPtr iface)
|
||||
ATTRIBUTE_NONNULL(1);
|
||||
int networkNotifyActualDevice(virDomainNetDefPtr iface)
|
||||
ATTRIBUTE_NONNULL(1);
|
||||
int networkReleaseActualDevice(virDomainNetDefPtr iface)
|
||||
ATTRIBUTE_NONNULL(1);
|
||||
int networkAllocateActualDevice(virDomainDefPtr dom,
|
||||
virDomainNetDefPtr iface)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
||||
int networkNotifyActualDevice(virDomainDefPtr dom,
|
||||
virDomainNetDefPtr iface)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
||||
int networkReleaseActualDevice(virDomainDefPtr dom,
|
||||
virDomainNetDefPtr iface)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
||||
|
||||
int networkGetNetworkAddress(const char *netname, char **netaddr)
|
||||
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
|
||||
@ -51,9 +54,9 @@ int networkDnsmasqConfContents(virNetworkObjPtr network,
|
||||
dnsmasqCapsPtr caps);
|
||||
# else
|
||||
/* Define no-op replacements that don't drag in any link dependencies. */
|
||||
# define networkAllocateActualDevice(iface) 0
|
||||
# define networkAllocateActualDevice(dom, iface) 0
|
||||
# define networkNotifyActualDevice(iface) (iface=iface, 0)
|
||||
# define networkReleaseActualDevice(iface) (iface=iface, 0)
|
||||
# define networkReleaseActualDevice(dom, iface) (dom=dom, iface=iface, 0)
|
||||
# define networkGetNetworkAddress(netname, netaddr) (-2)
|
||||
# define networkDnsmasqConfContents(network, pidfile, configstr, \
|
||||
dctx, caps) 0
|
||||
|
@ -548,7 +548,7 @@ qemuNetworkPrepareDevices(virDomainDefPtr def)
|
||||
* network's pool of devices, or resolve bridge device name
|
||||
* to the one defined in the network definition.
|
||||
*/
|
||||
if (networkAllocateActualDevice(net) < 0)
|
||||
if (networkAllocateActualDevice(def, net) < 0)
|
||||
goto cleanup;
|
||||
|
||||
actualType = virDomainNetGetActualType(net);
|
||||
|
@ -837,7 +837,7 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
|
||||
* network's pool of devices, or resolve bridge device name
|
||||
* to the one defined in the network definition.
|
||||
*/
|
||||
if (networkAllocateActualDevice(net) < 0)
|
||||
if (networkAllocateActualDevice(vm->def, net) < 0)
|
||||
goto cleanup;
|
||||
|
||||
actualType = virDomainNetGetActualType(net);
|
||||
@ -1082,7 +1082,7 @@ cleanup:
|
||||
|
||||
virDomainNetRemoveHostdev(vm->def, net);
|
||||
|
||||
networkReleaseActualDevice(net);
|
||||
networkReleaseActualDevice(vm->def, net);
|
||||
}
|
||||
|
||||
VIR_FREE(nicstr);
|
||||
@ -2017,7 +2017,7 @@ qemuDomainChangeNet(virQEMUDriverPtr driver,
|
||||
* free it if we fail for any reason
|
||||
*/
|
||||
if (newdev->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
|
||||
networkAllocateActualDevice(newdev) < 0) {
|
||||
networkAllocateActualDevice(vm->def, newdev) < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -2204,7 +2204,7 @@ qemuDomainChangeNet(virQEMUDriverPtr driver,
|
||||
|
||||
/* this function doesn't work with HOSTDEV networks yet, thus
|
||||
* no need to change the pointer in the hostdev structure */
|
||||
networkReleaseActualDevice(olddev);
|
||||
networkReleaseActualDevice(vm->def, olddev);
|
||||
virDomainNetDefFree(olddev);
|
||||
/* move newdev into the nets list, and NULL it out from the
|
||||
* virDomainDeviceDef that we were given so that the caller
|
||||
@ -2236,7 +2236,7 @@ cleanup:
|
||||
* replace the entire device object.
|
||||
*/
|
||||
if (newdev)
|
||||
networkReleaseActualDevice(newdev);
|
||||
networkReleaseActualDevice(vm->def, newdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -2649,7 +2649,7 @@ qemuDomainRemoveHostDevice(virQEMUDriverPtr driver,
|
||||
virDomainHostdevDefFree(hostdev);
|
||||
|
||||
if (net) {
|
||||
networkReleaseActualDevice(net);
|
||||
networkReleaseActualDevice(vm->def, net);
|
||||
virDomainNetDefFree(net);
|
||||
}
|
||||
virObjectUnref(cfg);
|
||||
@ -2717,7 +2717,7 @@ qemuDomainRemoveNetDevice(virQEMUDriverPtr driver,
|
||||
virDomainNetGetActualBridgeName(net),
|
||||
net->ifname));
|
||||
|
||||
networkReleaseActualDevice(net);
|
||||
networkReleaseActualDevice(vm->def, net);
|
||||
virDomainNetDefFree(net);
|
||||
virObjectUnref(cfg);
|
||||
}
|
||||
|
@ -2773,7 +2773,7 @@ qemuProcessNotifyNets(virDomainDefPtr def)
|
||||
|
||||
for (i = 0; i < def->nnets; i++) {
|
||||
virDomainNetDefPtr net = def->nets[i];
|
||||
if (networkNotifyActualDevice(net) < 0)
|
||||
if (networkNotifyActualDevice(def, net) < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@ -4393,7 +4393,7 @@ void qemuProcessStop(virQEMUDriverPtr driver,
|
||||
|
||||
/* kick the device out of the hostdev list too */
|
||||
virDomainNetRemoveHostdev(def, net);
|
||||
networkReleaseActualDevice(net);
|
||||
networkReleaseActualDevice(vm->def, net);
|
||||
}
|
||||
|
||||
retry:
|
||||
|
@ -48,12 +48,14 @@ VIR_ENUM_DECL(virHookDaemonOp)
|
||||
VIR_ENUM_DECL(virHookSubop)
|
||||
VIR_ENUM_DECL(virHookQemuOp)
|
||||
VIR_ENUM_DECL(virHookLxcOp)
|
||||
VIR_ENUM_DECL(virHookNetworkOp)
|
||||
|
||||
VIR_ENUM_IMPL(virHookDriver,
|
||||
VIR_HOOK_DRIVER_LAST,
|
||||
"daemon",
|
||||
"qemu",
|
||||
"lxc")
|
||||
"lxc",
|
||||
"network")
|
||||
|
||||
VIR_ENUM_IMPL(virHookDaemonOp, VIR_HOOK_DAEMON_OP_LAST,
|
||||
"start",
|
||||
@ -83,6 +85,13 @@ VIR_ENUM_IMPL(virHookLxcOp, VIR_HOOK_LXC_OP_LAST,
|
||||
"started",
|
||||
"reconnect")
|
||||
|
||||
VIR_ENUM_IMPL(virHookNetworkOp, VIR_HOOK_NETWORK_OP_LAST,
|
||||
"start",
|
||||
"started",
|
||||
"stopped",
|
||||
"plugged",
|
||||
"unplugged")
|
||||
|
||||
static int virHooksFound = -1;
|
||||
|
||||
/**
|
||||
@ -246,6 +255,8 @@ virHookCall(int driver,
|
||||
case VIR_HOOK_DRIVER_LXC:
|
||||
opstr = virHookLxcOpTypeToString(op);
|
||||
break;
|
||||
case VIR_HOOK_DRIVER_NETWORK:
|
||||
opstr = virHookNetworkOpTypeToString(op);
|
||||
}
|
||||
if (opstr == NULL) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
|
@ -30,6 +30,7 @@ enum virHookDriverType {
|
||||
VIR_HOOK_DRIVER_DAEMON = 0, /* Daemon related events */
|
||||
VIR_HOOK_DRIVER_QEMU, /* QEmu domains related events */
|
||||
VIR_HOOK_DRIVER_LXC, /* LXC domains related events */
|
||||
VIR_HOOK_DRIVER_NETWORK, /* network related events */
|
||||
|
||||
VIR_HOOK_DRIVER_LAST,
|
||||
};
|
||||
@ -74,6 +75,16 @@ enum virHookLxcOpType {
|
||||
VIR_HOOK_LXC_OP_LAST,
|
||||
};
|
||||
|
||||
enum virHookNetworkOpType {
|
||||
VIR_HOOK_NETWORK_OP_START, /* network is about to start */
|
||||
VIR_HOOK_NETWORK_OP_STARTED, /* network has start */
|
||||
VIR_HOOK_NETWORK_OP_STOPPED, /* network has stopped */
|
||||
VIR_HOOK_NETWORK_OP_IFACE_PLUGGED, /* an interface has been plugged into the network */
|
||||
VIR_HOOK_NETWORK_OP_IFACE_UNPLUGGED, /* an interface was unplugged from the network */
|
||||
|
||||
VIR_HOOK_NETWORK_OP_LAST,
|
||||
};
|
||||
|
||||
int virHookInitialize(void);
|
||||
|
||||
int virHookPresent(int driver);
|
||||
|
Loading…
Reference in New Issue
Block a user