Merge pull request #37060 from theredcat/lxc

Add lxc.get_pid and lxc.add_veth
This commit is contained in:
Mike Place 2016-10-19 11:43:42 +09:00 committed by GitHub
commit 454a721bff

View File

@ -12,6 +12,7 @@ lxc >= 1.0 (even beta alpha) is required
from __future__ import absolute_import, print_function
import datetime
import copy
import string
import textwrap
import difflib
import logging
@ -4659,3 +4660,103 @@ def apply_network_profile(name, network_profile, nic_opts=None, path=None):
tofile='after'):
diff += line
return diff
def get_pid(name, path=None):
'''
Returns a container pid.
Throw an exception if the container isn't running.
CLI Example:
.. code-block:: bash
salt '*' lxc.get_pid name
'''
if name not in list_(limit='running', path=path):
raise CommandExecutionError('Container {0} is not running, can\'t determine PID'.format(name))
info = __salt__['cmd.run']('lxc-info -n {0}'.format(name)).split("\n")
pid = [line.split(':')[1].strip() for line in info if re.match(r'\s*PID', line) != None][0]
return pid
def add_veth(name, interface_name, bridge=None, path=None):
'''
Add a veth to a container.
Note : this function doesn't update the container config, just add the interface at runtime
name
Name of the container
interface_name
Name of the interface in the container
bridge
Name of the bridge to attach the interface to (facultative)
CLI Examples:
.. code-block:: bash
salt '*' lxc.add_veth container_name eth1 br1
salt '*' lxc.add_veth container_name eth1
'''
# Get container init PID
pid = get_pid(name, path=path)
# Generate a ramdom string for veth and ensure that is isn't present on the system
while True:
random_veth = 'veth'+''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(6))
if random_veth not in __salt__['network.interfaces']().keys():
break
# Check prerequisites
if not __salt__['file.directory_exists']('/var/run/'):
raise CommandExecutionError('Directory /var/run required for lxc.add_veth doesn\'t exists')
if not __salt__['file.file_exists']('/proc/{0}/ns/net'.format(pid)):
raise CommandExecutionError('Proc file for container {0} network namespace doesn\'t exists'.format(name))
if not __salt__['file.directory_exists']('/var/run/netns'):
__salt__['file.mkdir']('/var/run/netns')
# Ensure that the symlink is up to date (change on container restart)
if __salt__['file.is_link']('/var/run/netns/{0}'.format(name)):
__salt__['file.remove']('/var/run/netns/{0}'.format(name))
__salt__['file.symlink']('/proc/{0}/ns/net'.format(pid), '/var/run/netns/{0}'.format(name))
# Ensure that interface doesn't exists
interface_exists = 0 == __salt__['cmd.retcode']('ip netns exec {netns} ip address list {interface}'.format(
netns=name,
interface=interface_name
))
if interface_exists:
raise CommandExecutionError('Interface {interface} already exists in {container}'.format(
interface=interface_name,
container=name
))
# Create veth and bring it up
if __salt__['cmd.retcode']('ip link add name {veth} type veth peer name {veth}_c'.format(veth=random_veth)) != 0:
raise CommandExecutionError('Error while creating the veth pair {0}'.format(random_veth))
if __salt__['cmd.retcode']('ip link set dev {0} up'.format(random_veth)) != 0:
raise CommandExecutionError('Error while bringing up host-side veth {0}'.format(random_veth))
# Attach it to the container
attached = 0 == __salt__['cmd.retcode']('ip link set dev {veth}_c netns {container} name {interface_name}'.format(
veth=random_veth,
container=name,
interface_name=interface_name
))
if not attached:
raise CommandExecutionError('Error while attaching the veth {veth} to container {container}'.format(
veth=random_veth,
container=name
))
__salt__['file.remove']('/var/run/netns/{0}'.format(name))
if bridge is not None:
__salt__['bridge.addif'](bridge, random_veth)