add lxc runner

This commit is contained in:
Matthew Williams 2014-01-29 22:04:02 -05:00
parent 85cbec910e
commit b1d7c69228
2 changed files with 304 additions and 1 deletions

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
'''
Work with linux containers
Control Linux Containers via Salt
:depends: lxc package for distribution
'''

303
salt/runners/lxc.py Normal file
View File

@ -0,0 +1,303 @@
# -*- coding: utf-8 -*-
'''
Control Linux Containers via Salt
:depends: lxc execution module
'''
# Import Salt libs
import salt.client
import salt.utils.virt
import salt.key
# Don't shadow built-in's.
__func_alias__ = {
'list_': 'list'
}
def _do(name, fun):
'''
Invoke a function in the lxc module with no args
'''
host = find_guest(name, quiet=True)
if not host:
return False
client = salt.client.LocalClient(__opts__['conf_file'])
cmd_ret = client.cmd_iter(
host,
'lxc.{0}'.format(fun),
[name],
timeout=60)
data = next(cmd_ret)
data = data.get(host, {}).get('ret', None)
if data:
data = {host: data}
return data
def find_guest(name, quiet=False):
'''
Returns the host for a container.
.. code-block:: bash
salt-run lxc.find_guest name
'''
data = list_(quiet=True)
for host, l in data.items():
# Check if data is a dict, and not '"virt.full_info" is not available.'
if not isinstance(l, dict):
continue
for x in 'running', 'frozen', 'stopped':
if name in l[x]:
if not quiet:
salt.output.display_output(
host,
'lxc_find_host',
__opts__)
return host
return None
def init(name,
host=None,
**kwargs):
'''
Initialize a new container
.. code-block:: bash
salt-run lxc.init name host=minion_id [cpuset=cgroups_cpuset] \\
[cpushare=cgroups_cpushare] [memory=cgroups_memory] \\
[nic=nic_profile] [profile=lxc_profile] \\
[nic_opts=nic_opts] [start=(true|false)] \\
[seed=(true|false)] [install=(true|false)] \\
[config=minion_config]
name
Name of the container.
host
Minion to start the container on. Required.
cpuset
cgroups cpuset.
cpushare
cgroups cpu shares.
memory
cgroups memory limit, in MB.
nic
Network interfaces profile (defined in config or pillar).
profile
A LXC profile (defined in config or pillar).
nic_opts
Extra options for network interfaces. E.g:
{"eth0": {"mac": "aa:bb:cc:dd:ee:ff", "ipv4": "10.1.1.1", "ipv6": "2001:db8::ff00:42:8329"}}
start
Start the newly created container.
seed
Seed the container with the minion config and autosign its key. Default: true
install
If salt-minion is not already installed, install it. Default: true
config
Optional config paramers. By default, the id is set to the name of the
container.
'''
print('Searching for LXC Hosts')
data = __salt__['lxc.list'](host, quiet=True)
for host, containers in data.items():
if name in sum(containers.values(), []):
print('Container "{0}" is already deployed'.format(name))
return 'fail'
if host is None:
#TODO: Support selection of host based on available memory/cpu/etc.
print('A host must be provided.')
return 'fail'
if host not in data:
print('Host "{0}" was not found'.format(host))
return 'fail'
seed = kwargs.get('seed', True)
if seed:
kv = salt.utils.virt.VirtKey(host, name, __opts__)
if kv.authorize():
print('Minion will be preseeded.')
else:
print('Preauthorization failed.')
return 'fail'
client = salt.client.LocalClient(__opts__['conf_file'])
print('Creating container {0} on host {1}.'.format(name, host))
args = [name]
_tf = lambda x: 'true' if x else 'false'
args.append('seed={0}'.format(_tf(seed)))
args.append('install={0}'.format(_tf(kwargs.get('install', True))))
args.append('start={0}'.format(_tf(kwargs.get('start', True))))
for x in ('cpuset', 'cpushare', 'memory', 'nic', 'profile',
'nic_opts', 'config'):
if x in kwargs:
args.append('{0}={1}'.format(x, kwargs.get(x)))
cmd_ret = client.cmd_iter(host,
'lxc.init',
args,
timeout=600)
ret = next(cmd_ret)
if not ret:
print('Container {0} was not initialized.'.format(name))
return 'fail'
print('Container {0} initialized on host {1}'.format(name, host))
return 'good'
def list_(host=None, quiet=False):
'''
List defined containers (running, stopped, and frozen) for the named
(or all) host(s).
.. code-block:: bash
salt-run lxc.list [host=minion_id]
'''
tgt = host or '*'
ret = {}
client = salt.client.LocalClient(__opts__['conf_file'])
for info in client.cmd_iter(tgt,
'lxc.list'):
if not info:
continue
if not isinstance(info, dict):
continue
chunk = {}
id_ = info.keys()[0]
if host and host != id_:
continue
if not isinstance(info[id_], dict):
continue
if 'ret' not in info[id_]:
continue
if not isinstance(info[id_]['ret'], dict):
continue
chunk[id_] = info[id_]['ret']
ret.update(chunk)
if not quiet:
salt.output.display_output(chunk, 'lxc_list', __opts__)
return ret
def purge(name, delete_key=True, quiet=False):
'''
Purge the named container and delete its minion key if present.
WARNING: Destroys all data associated with the container.
.. code-block:: bash
salt-run lxc.purge name
'''
data = _do(name, 'destroy')
if data is False:
return data
if delete_key:
skey = salt.key.Key(__opts__)
skey.delete_key(name)
if data is None:
return
if not quiet:
salt.output.display_output(data, 'lxc_purge', __opts__)
return data
def start(name, quiet=False):
'''
Start the named container.
.. code-block:: bash
salt-run lxc.start name
'''
data = _do(name, 'start')
if data and not quiet:
salt.output.display_output(data, 'lxc_start', __opts__)
return data
def stop(name, quiet=False):
'''
Stop the named container.
.. code-block:: bash
salt-run lxc.stop name
'''
data = _do(name, 'stop')
if data and not quiet:
salt.output.display_output(data, 'lxc_force_off', __opts__)
return data
def freeze(name, quiet=False):
'''
Freeze the named container
.. code-block:: bash
salt-run lxc.freeze name
'''
data = _do(name, 'freeze')
if data and not quiet:
salt.output.display_output(data, 'lxc_pause', __opts__)
return data
def unfreeze(name, quiet=False):
'''
Unfreeze the named container
.. code-block:: bash
salt-run lxc.unfreeze name
'''
data = _do(name, 'unfreeze')
if data and not quiet:
salt.output.display_output(data, 'lxc_resume', __opts__)
return data
def info(name, quiet=False):
'''
Returns information about a container.
.. code-block:: bash
salt-run lxc.info name
'''
data = _do(name, 'info')
if data and not quiet:
salt.output.display_output(data, 'lxc_info', __opts__)
return data