mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-08 13:24:23 +00:00
Add network-down script
Analogously to lxc.network.script.up, add the ability to register a down script. It is called before the guest network is finally destroyed, allowing to clean up resources that are not reset/destroyed automatically. Parameters of the down script are identical to the up script except for the execution context "down". Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
This commit is contained in:
parent
c8dee0f165
commit
74a2b5864f
@ -374,6 +374,26 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
<option>lxc.network.script.down</option>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
add a configuration option to specify a script to be
|
||||||
|
executed before destroying the network used from the
|
||||||
|
host side. The following arguments are passed to the
|
||||||
|
script: container name and config section name (net)
|
||||||
|
Additional arguments depend on the config section
|
||||||
|
employing a script hook; the following are used by the
|
||||||
|
network system: execution context (down), network type
|
||||||
|
(empty/veth/macvlan/phys), Depending on the network
|
||||||
|
type, other arguments may be passed:
|
||||||
|
veth/macvlan/phys. And finally (host-sided) device name.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect2>
|
</refsect2>
|
||||||
|
|
||||||
|
@ -138,6 +138,20 @@ static instanciate_cb netdev_conf[LXC_NET_MAXCONFTYPE + 1] = {
|
|||||||
[LXC_NET_EMPTY] = instanciate_empty,
|
[LXC_NET_EMPTY] = instanciate_empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int shutdown_veth(struct lxc_handler *, struct lxc_netdev *);
|
||||||
|
static int shutdown_macvlan(struct lxc_handler *, struct lxc_netdev *);
|
||||||
|
static int shutdown_vlan(struct lxc_handler *, struct lxc_netdev *);
|
||||||
|
static int shutdown_phys(struct lxc_handler *, struct lxc_netdev *);
|
||||||
|
static int shutdown_empty(struct lxc_handler *, struct lxc_netdev *);
|
||||||
|
|
||||||
|
static instanciate_cb netdev_deconf[LXC_NET_MAXCONFTYPE + 1] = {
|
||||||
|
[LXC_NET_VETH] = shutdown_veth,
|
||||||
|
[LXC_NET_MACVLAN] = shutdown_macvlan,
|
||||||
|
[LXC_NET_VLAN] = shutdown_vlan,
|
||||||
|
[LXC_NET_PHYS] = shutdown_phys,
|
||||||
|
[LXC_NET_EMPTY] = shutdown_empty,
|
||||||
|
};
|
||||||
|
|
||||||
static struct mount_opt mount_opt[] = {
|
static struct mount_opt mount_opt[] = {
|
||||||
{ "defaults", 0, 0 },
|
{ "defaults", 0, 0 },
|
||||||
{ "ro", 0, MS_RDONLY },
|
{ "ro", 0, MS_RDONLY },
|
||||||
@ -1765,6 +1779,8 @@ static int instanciate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
veth1 = mktemp(veth1buf);
|
veth1 = mktemp(veth1buf);
|
||||||
|
/* store away for deconf */
|
||||||
|
memcpy(netdev->priv.veth_attr.veth1, veth1, IFNAMSIZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(veth2buf, sizeof(veth2buf), "vethXXXXXX");
|
snprintf(veth2buf, sizeof(veth2buf), "vethXXXXXX");
|
||||||
@ -1841,6 +1857,25 @@ out_delete:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int shutdown_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
||||||
|
{
|
||||||
|
char *veth1;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (netdev->priv.veth_attr.pair)
|
||||||
|
veth1 = netdev->priv.veth_attr.pair;
|
||||||
|
else
|
||||||
|
veth1 = netdev->priv.veth_attr.veth1;
|
||||||
|
|
||||||
|
if (netdev->downscript) {
|
||||||
|
err = run_script(handler->name, "net", netdev->downscript,
|
||||||
|
"down", "veth", veth1, (char*) NULL);
|
||||||
|
if (err)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int instanciate_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
static int instanciate_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
||||||
{
|
{
|
||||||
char peerbuf[IFNAMSIZ], *peer;
|
char peerbuf[IFNAMSIZ], *peer;
|
||||||
@ -1889,6 +1924,20 @@ static int instanciate_macvlan(struct lxc_handler *handler, struct lxc_netdev *n
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int shutdown_macvlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (netdev->downscript) {
|
||||||
|
err = run_script(handler->name, "net", netdev->downscript,
|
||||||
|
"down", "macvlan", netdev->link,
|
||||||
|
(char*) NULL);
|
||||||
|
if (err)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* XXX: merge with instanciate_macvlan */
|
/* XXX: merge with instanciate_macvlan */
|
||||||
static int instanciate_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
static int instanciate_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
||||||
{
|
{
|
||||||
@ -1926,6 +1975,11 @@ static int instanciate_vlan(struct lxc_handler *handler, struct lxc_netdev *netd
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int shutdown_vlan(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int instanciate_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
static int instanciate_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
||||||
{
|
{
|
||||||
if (!netdev->link) {
|
if (!netdev->link) {
|
||||||
@ -1950,6 +2004,19 @@ static int instanciate_phys(struct lxc_handler *handler, struct lxc_netdev *netd
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int shutdown_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (netdev->downscript) {
|
||||||
|
err = run_script(handler->name, "net", netdev->downscript,
|
||||||
|
"down", "phys", netdev->link, (char*) NULL);
|
||||||
|
if (err)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int instanciate_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
static int instanciate_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
||||||
{
|
{
|
||||||
netdev->ifindex = 0;
|
netdev->ifindex = 0;
|
||||||
@ -1963,6 +2030,19 @@ static int instanciate_empty(struct lxc_handler *handler, struct lxc_netdev *net
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int shutdown_empty(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (netdev->downscript) {
|
||||||
|
err = run_script(handler->name, "net", netdev->downscript,
|
||||||
|
"down", "empty", (char*) NULL);
|
||||||
|
if (err)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int lxc_create_network(struct lxc_handler *handler)
|
int lxc_create_network(struct lxc_handler *handler)
|
||||||
{
|
{
|
||||||
struct lxc_list *network = &handler->conf->network;
|
struct lxc_list *network = &handler->conf->network;
|
||||||
@ -1989,28 +2069,32 @@ int lxc_create_network(struct lxc_handler *handler)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lxc_delete_network(struct lxc_list *network)
|
void lxc_delete_network(struct lxc_handler *handler)
|
||||||
{
|
{
|
||||||
|
struct lxc_list *network = &handler->conf->network;
|
||||||
struct lxc_list *iterator;
|
struct lxc_list *iterator;
|
||||||
struct lxc_netdev *netdev;
|
struct lxc_netdev *netdev;
|
||||||
|
|
||||||
lxc_list_for_each(iterator, network) {
|
lxc_list_for_each(iterator, network) {
|
||||||
netdev = iterator->elem;
|
netdev = iterator->elem;
|
||||||
if (netdev->ifindex == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (netdev->type == LXC_NET_PHYS) {
|
if (netdev->ifindex != 0 && netdev->type == LXC_NET_PHYS) {
|
||||||
if (lxc_netdev_rename_by_index(netdev->ifindex, netdev->link))
|
if (lxc_netdev_rename_by_index(netdev->ifindex, netdev->link))
|
||||||
WARN("failed to rename to the initial name the " \
|
WARN("failed to rename to the initial name the " \
|
||||||
"netdev '%s'", netdev->link);
|
"netdev '%s'", netdev->link);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (netdev_deconf[netdev->type](handler, netdev)) {
|
||||||
|
WARN("failed to destroy netdev");
|
||||||
|
}
|
||||||
|
|
||||||
/* Recent kernel remove the virtual interfaces when the network
|
/* Recent kernel remove the virtual interfaces when the network
|
||||||
* namespace is destroyed but in case we did not moved the
|
* namespace is destroyed but in case we did not moved the
|
||||||
* interface to the network namespace, we have to destroy it
|
* interface to the network namespace, we have to destroy it
|
||||||
*/
|
*/
|
||||||
if (lxc_netdev_delete_by_index(netdev->ifindex))
|
if (netdev->ifindex != 0 &&
|
||||||
|
lxc_netdev_delete_by_index(netdev->ifindex))
|
||||||
WARN("failed to remove interface '%s'", netdev->name);
|
WARN("failed to remove interface '%s'", netdev->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#define _conf_h
|
#define _conf_h
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <net/if.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
@ -76,6 +77,7 @@ struct lxc_route6 {
|
|||||||
|
|
||||||
struct ifla_veth {
|
struct ifla_veth {
|
||||||
char *pair; /* pair name */
|
char *pair; /* pair name */
|
||||||
|
char veth1[IFNAMSIZ]; /* needed for deconf */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ifla_vlan {
|
struct ifla_vlan {
|
||||||
@ -103,6 +105,7 @@ union netdev_p {
|
|||||||
* @ipv4 : a list of ipv4 addresses to be set on the network device
|
* @ipv4 : a list of ipv4 addresses to be set on the network device
|
||||||
* @ipv6 : a list of ipv6 addresses to be set on the network device
|
* @ipv6 : a list of ipv6 addresses to be set on the network device
|
||||||
* @upscript : a script filename to be executed during interface configuration
|
* @upscript : a script filename to be executed during interface configuration
|
||||||
|
* @downscript : a script filename to be executed during interface destruction
|
||||||
*/
|
*/
|
||||||
struct lxc_netdev {
|
struct lxc_netdev {
|
||||||
int type;
|
int type;
|
||||||
@ -120,6 +123,7 @@ struct lxc_netdev {
|
|||||||
struct in6_addr *ipv6_gateway;
|
struct in6_addr *ipv6_gateway;
|
||||||
bool ipv6_gateway_auto;
|
bool ipv6_gateway_auto;
|
||||||
char *upscript;
|
char *upscript;
|
||||||
|
char *downscript;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -242,7 +246,7 @@ extern struct lxc_conf *lxc_conf_init(void);
|
|||||||
extern int pin_rootfs(const char *rootfs);
|
extern int pin_rootfs(const char *rootfs);
|
||||||
|
|
||||||
extern int lxc_create_network(struct lxc_handler *handler);
|
extern int lxc_create_network(struct lxc_handler *handler);
|
||||||
extern void lxc_delete_network(struct lxc_list *networks);
|
extern void lxc_delete_network(struct lxc_handler *handler);
|
||||||
extern int lxc_assign_network(struct lxc_list *networks, pid_t pid);
|
extern int lxc_assign_network(struct lxc_list *networks, pid_t pid);
|
||||||
extern int lxc_find_gateway_addresses(struct lxc_handler *handler);
|
extern int lxc_find_gateway_addresses(struct lxc_handler *handler);
|
||||||
|
|
||||||
|
@ -111,6 +111,7 @@ static struct config config[] = {
|
|||||||
{ "lxc.network.macvlan.mode", config_network_macvlan_mode },
|
{ "lxc.network.macvlan.mode", config_network_macvlan_mode },
|
||||||
{ "lxc.network.veth.pair", config_network_veth_pair },
|
{ "lxc.network.veth.pair", config_network_veth_pair },
|
||||||
{ "lxc.network.script.up", config_network_script },
|
{ "lxc.network.script.up", config_network_script },
|
||||||
|
{ "lxc.network.script.down", config_network_script },
|
||||||
{ "lxc.network.hwaddr", config_network_hwaddr },
|
{ "lxc.network.hwaddr", config_network_hwaddr },
|
||||||
{ "lxc.network.mtu", config_network_mtu },
|
{ "lxc.network.mtu", config_network_mtu },
|
||||||
{ "lxc.network.vlan.id", config_network_vlan_id },
|
{ "lxc.network.vlan.id", config_network_vlan_id },
|
||||||
@ -595,6 +596,10 @@ static int config_network_script(const char *key, char *value,
|
|||||||
netdev->upscript = copy;
|
netdev->upscript = copy;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (strcmp(key, "lxc.network.script.down") == 0) {
|
||||||
|
netdev->downscript = copy;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
SYSERROR("Unknown key: %s", key);
|
SYSERROR("Unknown key: %s", key);
|
||||||
free(copy);
|
free(copy);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -652,7 +652,7 @@ int lxc_spawn(struct lxc_handler *handler)
|
|||||||
|
|
||||||
out_delete_net:
|
out_delete_net:
|
||||||
if (clone_flags & CLONE_NEWNET)
|
if (clone_flags & CLONE_NEWNET)
|
||||||
lxc_delete_network(&handler->conf->network);
|
lxc_delete_network(handler);
|
||||||
out_abort:
|
out_abort:
|
||||||
lxc_abort(name, handler);
|
lxc_abort(name, handler);
|
||||||
lxc_sync_fini(handler);
|
lxc_sync_fini(handler);
|
||||||
@ -684,7 +684,7 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
|
|||||||
err = lxc_spawn(handler);
|
err = lxc_spawn(handler);
|
||||||
if (err) {
|
if (err) {
|
||||||
ERROR("failed to spawn '%s'", name);
|
ERROR("failed to spawn '%s'", name);
|
||||||
goto out_fini;
|
goto out_fini_nonet;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = lxc_poll(name, handler);
|
err = lxc_poll(name, handler);
|
||||||
@ -719,6 +719,9 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
|
|||||||
|
|
||||||
err = lxc_error_set_and_log(handler->pid, status);
|
err = lxc_error_set_and_log(handler->pid, status);
|
||||||
out_fini:
|
out_fini:
|
||||||
|
lxc_delete_network(handler);
|
||||||
|
|
||||||
|
out_fini_nonet:
|
||||||
lxc_cgroup_destroy(name);
|
lxc_cgroup_destroy(name);
|
||||||
lxc_fini(name, handler);
|
lxc_fini(name, handler);
|
||||||
return err;
|
return err;
|
||||||
|
Loading…
Reference in New Issue
Block a user