[libvirt] [PATCH] lxc: do not require 'ifconfig' or 'ipconfig' in container

Serge Hallyn serge.hallyn at canonical.com
Wed Aug 31 19:02:10 UTC 2011


Quoting Scott Moser (smoser at ubuntu.com):
> Currently, the lxc implementation invokes 'ip' and 'ifconfig' commands
> inside a container using 'virRun'.  That has the side effect of requiring
> those commands to be present and to function in a manner consistent with
> the usage.  Some small roots (such as ttylinux) may not have 'ip' or
> 'ifconfig'.
> 
> This patch replaces the use of these commands with usage of
> netdevice.  The result is that lxc containers do not have to implement
> those commands, and lxc in libvirt is only dependent on the netdevice
> interface.

Requiring fewer tools in the container seems like a very good thing,
especially when trying to create a tiny busybox-based container.

thanks,
-serge

> I've tested this patch locally against the ubuntu libvirt version enough
> to verify its generally sane.  I attempted to build upstream today, but
> failed with:
>   /usr/bin/ld:
>     ../src/.libs/libvirt_driver_qemu.a(libvirt_driver_qemu_la-qemu_domain.o):
>    undefined reference to symbol 'xmlXPathRegisterNs@@LIBXML2_2.4.30
> 
> Thats probably a local issue only, but I wanted to get this patch up and
> see what others thought of it.  This is ubuntu bug
> https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/828211 .
> 
> diff --git a/src/lxc/veth.c b/src/lxc/veth.c
> index 34cb804..c24df91 100644
> --- a/src/lxc/veth.c
> +++ b/src/lxc/veth.c
> @@ -12,8 +12,11 @@
> 
>  #include <config.h>
> 
> +#include <linux/sockios.h>
> +#include <net/if.h>
>  #include <string.h>
>  #include <stdio.h>
> +#include <sys/ioctl.h>
>  #include <sys/types.h>
>  #include <sys/wait.h>
> 
> @@ -186,41 +189,49 @@ int vethDelete(const char *veth)
>   * @veth: name of veth device
>   * @upOrDown: 0 => down, 1 => up
>   *
> - * Enables a veth device using the ifconfig command.  A NULL inetAddress
> - * will cause it to be left off the command line.
> + * Enables a veth device using SIOCSIFFLAGS
>   *
> - * Returns 0 on success or -1 in case of error
> + * Returns 0 on success, -1 on failure, with errno set
>   */
>  int vethInterfaceUpOrDown(const char* veth, int upOrDown)
>  {
> -    int rc;
> -    const char *argv[] = {"ifconfig", veth, NULL, NULL};
> -    int cmdResult = 0;
> +    struct ifreq ifr;
> +    int fd, ret;
> 
> -    if (0 == upOrDown)
> -        argv[2] = "down";
> -    else
> -        argv[2] = "up";
> +    if ((fd = socket(PF_PACKET, SOCK_DGRAM, 0)) == -1)
> +        return(-1);
> 
> -    rc = virRun(argv, &cmdResult);
> +    memset(&ifr, 0, sizeof(struct ifreq));
> 
> -    if (rc != 0 ||
> -        (WIFEXITED(cmdResult) && WEXITSTATUS(cmdResult) != 0)) {
> -        if (0 == upOrDown)
> +    if (virStrcpyStatic(ifr.ifr_name, veth) == NULL) {
> +        errno = EINVAL;
> +        return -1;
> +    }
> +
> +    if ((ret = ioctl(fd, SIOCGIFFLAGS, &ifr)) == 0) {
> +        if (upOrDown)
> +            ifr.ifr_flags |= IFF_UP;
> +        else
> +            ifr.ifr_flags &= ~(IFF_UP | IFF_RUNNING);
> +
> +        ret = ioctl(fd, SIOCSIFFLAGS, &ifr);
> +    }
> +
> +    close(fd);
> +    if (ret == -1)
> +        if (upOrDown == 0)
>              /*
>               * Prevent overwriting an error log which may be set
>               * where an actual failure occurs.
>               */
> -            VIR_DEBUG("Failed to disable '%s' (%d)",
> -                      veth, WEXITSTATUS(cmdResult));
> +            VIR_DEBUG("Failed to disable '%s'", veth);
>          else
>              vethError(VIR_ERR_INTERNAL_ERROR,
> -                      _("Failed to enable '%s' (%d)"),
> -                      veth, WEXITSTATUS(cmdResult));
> -        rc = -1;
> -    }
> +                      _("Failed to enable '%s'"), veth);
> +    else
> +        ret = 0;
> 
> -    return rc;
> +    return(ret);
>  }
> 
>  /**
> @@ -279,17 +290,29 @@ int setMacAddr(const char* iface, const char* macaddr)
>   * @iface: name of device
>   * @new: new name of @iface
>   *
> - * Changes the name of the given device with the
> - * given new name using this command:
> - *     ip link set @iface name @new
> + * Changes the name of the given device.
>   *
> - * Returns 0 on success or -1 in case of error
> + * Returns 0 on success, -1 on failure with errno set.
>   */
>  int setInterfaceName(const char* iface, const char* new)
>  {
> -    const char *argv[] = {
> -        "ip", "link", "set", iface, "name", new, NULL
> -    };
> +    struct ifreq ifr;
> +    int fd = socket(PF_PACKET, SOCK_DGRAM, 0);
> 
> -    return virRun(argv, NULL);
> +    memset(&ifr, 0, sizeof(struct ifreq));
> +
> +    if (virStrcpyStatic(ifr.ifr_name, iface) == NULL) {
> +        errno = EINVAL;
> +        return -1;
> +    }
> +
> +    if (virStrcpyStatic(ifr.ifr_newname, new) == NULL) {
> +        errno = EINVAL;
> +        return -1;
> +    }
> +
> +    if (ioctl(fd, SIOCSIFNAME, &ifr))
> +        return -1;
> +
> +    return 0;
>  }
> 




More information about the libvir-list mailing list