Merge branch '2014.7' into merge_forward_fifteen_second_try

Conflicts:
	salt/states/file.py
This commit is contained in:
rallytime 2015-01-29 13:42:49 -07:00
commit c65d9673a7
14 changed files with 215 additions and 84 deletions

3
.gitignore vendored
View file

@ -64,3 +64,6 @@ _version.py
# Ignore grains file written out during tests
tests/integration/files/conf/grains
# Ignore file cache created by jinja tests
tests/unit/templates/roots

View file

@ -163,7 +163,7 @@ at the ``debug`` level:
.. code-block:: yaml
log_granular_levels:
'salt': 'warning',
'salt': 'warning'
'salt.modules': 'debug'
@ -172,4 +172,4 @@ External Logging Handlers
Besides the internal logging handlers used by salt, there are some external
which can be used, see the :doc:`external logging handlers<handlers/index>`
document.
document.

View file

@ -294,7 +294,7 @@ def create(vm_):
if private_networking is not None:
if not isinstance(private_networking, bool):
raise SaltCloudConfigError("'private_networking' should be a boolean value.")
kwargs['private_networking'] = private_networking
kwargs['private_networking'] = str(private_networking).lower()
backups_enabled = config.get_cloud_config_value(
'backups_enabled', vm_, __opts__, search_global=False, default=None,
@ -302,7 +302,7 @@ def create(vm_):
if backups_enabled is not None:
if not isinstance(backups_enabled, bool):
raise SaltCloudConfigError("'backups_enabled' should be a boolean value.")
kwargs['backups_enabled'] = backups_enabled
kwargs['backups_enabled'] = str(backups_enabled).lower()
salt.utils.cloud.fire_event(
'event',

View file

@ -1536,7 +1536,7 @@ def build_interface(iface, iface_type, enabled, **settings):
if not __salt__['pkg.version']('ppp'):
inst = __salt__['pkg.install']('ppp')
elif iface_type is 'bond':
elif iface_type == 'bond':
if 'slaves' not in settings:
msg = 'slaves is a required setting for bond interfaces'
log.error(msg)

View file

@ -66,9 +66,11 @@ def _active_mountinfo(ret):
_sep = comps.index('-')
device_name = comps[_sep + 2]
device_uuid = None
device_label = None
if device_name:
device_uuid = blkid_info.get(device_name, {}).get('UUID')
device_uuid = device_uuid and device_uuid.lower()
device_label = blkid_info.get(device_name, {}).get('LABEL')
ret[comps[4]] = {'mountid': comps[0],
'parentid': comps[1],
'major': device[0],
@ -79,7 +81,8 @@ def _active_mountinfo(ret):
'device': device_name,
'alt_device': _list.get(comps[4], None),
'superopts': comps[_sep + 3].split(','),
'device_uuid': device_uuid}
'device_uuid': device_uuid,
'device_label': device_label}
return ret

View file

@ -156,33 +156,65 @@ def cpustats():
salt '*' status.cpustats
'''
procf = '/proc/stat'
if not os.path.isfile(procf):
return {}
stats = salt.utils.fopen(procf, 'r').read().splitlines()
ret = {}
for line in stats:
if not line:
continue
comps = line.split()
if comps[0] == 'cpu':
ret[comps[0]] = {'idle': _number(comps[4]),
'iowait': _number(comps[5]),
'irq': _number(comps[6]),
'nice': _number(comps[2]),
'softirq': _number(comps[7]),
'steal': _number(comps[8]),
'system': _number(comps[3]),
'user': _number(comps[1])}
elif comps[0] == 'intr':
ret[comps[0]] = {'total': _number(comps[1]),
'irqs': [_number(x) for x in comps[2:]]}
elif comps[0] == 'softirq':
ret[comps[0]] = {'total': _number(comps[1]),
'softirqs': [_number(x) for x in comps[2:]]}
else:
ret[comps[0]] = _number(comps[1])
return ret
def linux_cpustats():
'''
linux specific implementation of cpustats
'''
procf = '/proc/stat'
if not os.path.isfile(procf):
return {}
stats = salt.utils.fopen(procf, 'r').read().splitlines()
ret = {}
for line in stats:
if not line:
continue
comps = line.split()
if comps[0] == 'cpu':
ret[comps[0]] = {'idle': _number(comps[4]),
'iowait': _number(comps[5]),
'irq': _number(comps[6]),
'nice': _number(comps[2]),
'softirq': _number(comps[7]),
'steal': _number(comps[8]),
'system': _number(comps[3]),
'user': _number(comps[1])}
elif comps[0] == 'intr':
ret[comps[0]] = {'total': _number(comps[1]),
'irqs': [_number(x) for x in comps[2:]]}
elif comps[0] == 'softirq':
ret[comps[0]] = {'total': _number(comps[1]),
'softirqs': [_number(x) for x in comps[2:]]}
else:
ret[comps[0]] = _number(comps[1])
return ret
def freebsd_cpustats():
'''
freebsd specific implementation of cpustats
'''
vmstat = __salt__['cmd.run']('vmstat -P').splitlines()
vm0 = vmstat[0].split()
cpu0loc = vm0.index('cpu0')
vm1 = vmstat[1].split()
usloc = vm1.index('us')
vm2 = vmstat[2].split()
cpuctr = 0
ret = {}
for cpu in vm0[cpu0loc:]:
ret[cpu] = {'us': _number(vm2[usloc + 3 * cpuctr]),
'sy': _number(vm2[usloc + 1 + 3 * cpuctr]),
'id': _number(vm2[usloc + 2 + 3 * cpuctr]), }
cpuctr += 1
return ret
# dict that return a function that does the right thing per platform
get_version = {
'Linux': linux_cpustats,
'FreeBSD': freebsd_cpustats,
}
errmsg = 'This method is unsupported on the current operating system!'
return get_version.get(__grains__['kernel'], lambda: errmsg)()
def meminfo():
@ -195,22 +227,53 @@ def meminfo():
salt '*' status.meminfo
'''
procf = '/proc/meminfo'
if not os.path.isfile(procf):
return {}
stats = salt.utils.fopen(procf, 'r').read().splitlines()
ret = {}
for line in stats:
if not line:
continue
comps = line.split()
comps[0] = comps[0].replace(':', '')
ret[comps[0]] = {
'value': comps[1],
}
if len(comps) > 2:
ret[comps[0]]['unit'] = comps[2]
return ret
def linux_meminfo():
'''
linux specific implementation of meminfo
'''
procf = '/proc/meminfo'
if not os.path.isfile(procf):
return {}
stats = salt.utils.fopen(procf, 'r').read().splitlines()
ret = {}
for line in stats:
if not line:
continue
comps = line.split()
comps[0] = comps[0].replace(':', '')
ret[comps[0]] = {
'value': comps[1],
}
if len(comps) > 2:
ret[comps[0]]['unit'] = comps[2]
return ret
def freebsd_meminfo():
'''
freebsd specific implementation of meminfo
'''
sysctlvm = __salt__['cmd.run']('sysctl vm').splitlines()
sysctlvm = [x for x in sysctlvm if x.startswith('vm')]
sysctlvm = [x.split(':') for x in sysctlvm]
sysctlvm = [[y.strip() for y in x] for x in sysctlvm]
sysctlvm = [x for x in sysctlvm if x[1]] # If x[1] not empty
ret = {}
for line in sysctlvm:
ret[line[0]] = line[1]
# Special handling for vm.total as it's especially important
sysctlvmtot = __salt__['cmd.run']('sysctl -n vm.vmtotal').splitlines()
sysctlvmtot = [x for x in sysctlvmtot if x]
ret['vm.vmtotal'] = sysctlvmtot
return ret
# dict that return a function that does the right thing per platform
get_version = {
'Linux': linux_meminfo,
'FreeBSD': freebsd_meminfo,
}
errmsg = 'This method is unsupported on the current operating system!'
return get_version.get(__grains__['kernel'], lambda: errmsg)()
def cpuinfo():
@ -223,21 +286,48 @@ def cpuinfo():
salt '*' status.cpuinfo
'''
procf = '/proc/cpuinfo'
if not os.path.isfile(procf):
return {}
stats = salt.utils.fopen(procf, 'r').read().splitlines()
ret = {}
for line in stats:
if not line:
continue
comps = line.split(':')
comps[0] = comps[0].strip()
if comps[0] == 'flags':
ret[comps[0]] = comps[1].split()
else:
def linux_cpuinfo():
'''
linux specific cpuinfo implementation
'''
procf = '/proc/cpuinfo'
if not os.path.isfile(procf):
return {}
stats = salt.utils.fopen(procf, 'r').read().splitlines()
ret = {}
for line in stats:
if not line:
continue
comps = line.split(':')
comps[0] = comps[0].strip()
if comps[0] == 'flags':
ret[comps[0]] = comps[1].split()
else:
ret[comps[0]] = comps[1].strip()
return ret
def freebsd_cpuinfo():
'''
freebds specific cpuinfo implementation
'''
freebsd_cmd = 'sysctl hw.model hw.ncpu'
ret = {}
for line in __salt__['cmd.run'](freebsd_cmd).splitlines():
if not line:
continue
comps = line.split(':')
comps[0] = comps[0].strip()
ret[comps[0]] = comps[1].strip()
return ret
return ret
# dict that returns a function that does the right thing per platform
get_version = {
'Linux': linux_cpuinfo,
'FreeBSD': freebsd_cpuinfo,
}
errmsg = 'This method is unsupported on the current operating system!'
return get_version.get(__grains__['kernel'], lambda: errmsg)()
def diskstats():
@ -431,7 +521,7 @@ def netdev():
comps = line.split()
# Fix lines like eth0:9999..'
comps[0] = line.split(':')[0].strip()
#Support lines both like eth0:999 and eth0: 9999
# Support lines both like eth0:999 and eth0: 9999
comps.insert(1, line.split(':')[1].strip().split()[0])
ret[comps[0]] = {'iface': comps[0],
'rx_bytes': _number(comps[1]),
@ -544,15 +634,18 @@ def version():
salt '*' status.version
'''
def linux_version():
'''
linux specific implementation of version
'''
procf = '/proc/version'
if not os.path.isfile(procf):
return {}
return salt.utils.fopen(procf, 'r').read().strip()
# dict that return a function that does the right thing per platform
# dict that returns a function that does the right thing per platform
get_version = {
'Linux': linux_version,
'FreeBSD': lambda: __salt__['cmd.run']('sysctl -n kern.version'),
'Linux': linux_version,
'FreeBSD': lambda: __salt__['cmd.run']('sysctl -n kern.version'),
}
errmsg = 'This method is unsupported on the current operating system!'

View file

@ -164,7 +164,6 @@ class Pillar(object):
saltenv = env
opts = dict(opts_in)
opts['file_roots'] = opts['pillar_roots']
opts['__pillar'] = True
opts['file_client'] = 'local'
if not grains:
opts['grains'] = {}

View file

@ -2414,13 +2414,15 @@ def replace(name,
if changes:
ret['changes'] = {'diff': changes}
ret['comment'] = ('Changes were made'
if not __opts__['test'] else 'Changes would have been made')
if __opts__['test']:
ret['result'] = None
ret['comment'] = 'Changes would have been made'
else:
ret['result'] = True
ret['comment'] = 'Changes were made'
else:
ret['comment'] = ('No changes were made'
if not __opts__['test'] else 'No changes would have been made')
ret['result'] = True
ret['comment'] = 'No changes needed to be made'
return ret

View file

@ -59,7 +59,7 @@ def mounted(name,
device
The device name, typically the device node, such as ``/dev/sdb1``
or ``UUID=066e0200-2867-4ebe-b9e6-f30026ca2314``
or ``UUID=066e0200-2867-4ebe-b9e6-f30026ca2314`` or ``LABEL=DATA``
fstype
The filesystem type, this will be ``xfs``, ``ext2/3/4`` in the case of classic
@ -170,10 +170,13 @@ def mounted(name,
device_list.append(os.path.realpath(device_list[0]))
alt_device = active[real_name]['alt_device'] if 'alt_device' in active[real_name] else None
uuid_device = active[real_name]['device_uuid'] if 'device_uuid' in active[real_name] else None
label_device = active[real_name]['device_label'] if 'device_label' in active[real_name] else None
if alt_device and alt_device not in device_list:
device_list.append(alt_device)
if uuid_device and uuid_device not in device_list:
device_list.append(uuid_device)
if label_device and label_device not in device_list:
device_list.append(label_device)
if opts:
mount_invisible_options = [
'_netdev',
@ -197,6 +200,7 @@ def mounted(name,
'password',
'retry',
]
for opt in opts:
keyval_option = opt.split('=')[0]
if keyval_option in mount_invisible_keys:

View file

@ -80,7 +80,7 @@ def present(name, value, config=None):
'The value {0} is set to be changed to {1} '
return ret
elif name in configured and name in current:
if str(value) == __salt__['sysctl.get'](name):
if str(value).split() == __salt__['sysctl.get'](name).split():
ret['result'] = True
ret['comment'] = 'Sysctl value {0} = {1} is already set'.format(
name,

View file

@ -65,7 +65,7 @@ class SaltCacheLoader(BaseLoader):
self.opts = opts
self.saltenv = saltenv
self.encoding = encoding
if self.opts.get('__pillar', False):
if self.opts['file_roots'] is self.opts['pillar_roots']:
self.searchpath = opts['file_roots'][saltenv]
else:
self.searchpath = [path.join(opts['cachedir'], 'files', saltenv)]

View file

@ -7,6 +7,7 @@ from __future__ import absolute_import
# Import python libs
import socket
import subprocess
import shlex
import re
import logging
import os
@ -1011,7 +1012,8 @@ def _freebsd_remotes_on(port, which_end):
remotes = set()
try:
data = subprocess.check_output(['sockstat', '-4', '-c', '-p {0}'.format(port)])
cmd = shlex.split('sockstat -4 -c -p {0}'.format(port))
data = subprocess.check_output(cmd)
except subprocess.CalledProcessError as ex:
log.error('Failed "sockstat" with returncode = {0}'.format(ex.returncode))
raise

View file

@ -1172,12 +1172,13 @@ class ShellCase(AdaptedConfigurationTestCaseMixIn, ShellTestCase):
arg_str = '-c {0} -i --priv {1} --roster-file {2} --out=json localhost {3}'.format(self.get_config_dir(), os.path.join(TMP_CONF_DIR, 'key_test'), os.path.join(TMP_CONF_DIR, 'roster'), arg_str)
return self.run_script('salt-ssh', arg_str, with_retcode=with_retcode, catch_stderr=catch_stderr, raw=True)
def run_run(self, arg_str, with_retcode=False, catch_stderr=False, async=False):
def run_run(self, arg_str, with_retcode=False, catch_stderr=False, async=False, timeout=60):
'''
Execute salt-run
'''
arg_str = '-c {0}{async_flag} {1}'.format(self.get_config_dir(),
arg_str = '-c {0}{async_flag} -t {timeout} {1}'.format(self.get_config_dir(),
arg_str,
timeout=timeout,
async_flag=' --async' if async else '')
return self.run_script('salt-run', arg_str, with_retcode=with_retcode, catch_stderr=catch_stderr)

View file

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
# Import python libs
import copy
import os
import tempfile
import json
@ -57,12 +58,26 @@ class MockFileClient(object):
class TestSaltCacheLoader(TestCase):
def __init__(self, *args, **kws):
TestCase.__init__(self, *args, **kws)
self.opts = {
'cachedir': TEMPLATES_DIR,
'file_roots': {
'test': [os.path.join(TEMPLATES_DIR, 'files', 'test')]
},
'pillar_roots': {
'test': [os.path.join(TEMPLATES_DIR, 'files', 'test')]
}
}
def test_searchpath(self):
'''
The searchpath is based on the cachedir option and the saltenv parameter
'''
tmp = tempfile.gettempdir()
loader = SaltCacheLoader({'cachedir': tmp}, saltenv='test')
opts = copy.deepcopy(self.opts)
opts.update({'cachedir': tmp})
loader = SaltCacheLoader(opts, saltenv='test')
assert loader.searchpath == [os.path.join(tmp, 'files', 'test')]
def test_mockclient(self):
@ -70,7 +85,7 @@ class TestSaltCacheLoader(TestCase):
A MockFileClient is used that records all file requests normally sent
to the master.
'''
loader = SaltCacheLoader({'cachedir': TEMPLATES_DIR}, 'test')
loader = SaltCacheLoader(self.opts, 'test')
fc = MockFileClient(loader)
res = loader.get_source(None, 'hello_simple')
assert len(res) == 3
@ -86,7 +101,7 @@ class TestSaltCacheLoader(TestCase):
'''
Setup a simple jinja test environment
'''
loader = SaltCacheLoader({'cachedir': TEMPLATES_DIR}, 'test')
loader = SaltCacheLoader(self.opts, 'test')
fc = MockFileClient(loader)
jinja = Environment(loader=loader)
return fc, jinja
@ -134,6 +149,9 @@ class TestGetTemplate(TestCase):
'file_roots': {
'test': [os.path.join(TEMPLATES_DIR, 'files', 'test')]
},
'pillar_roots': {
'test': [os.path.join(TEMPLATES_DIR, 'files', 'test')]
},
'fileserver_backend': ['roots'],
'hash_type': 'md5',
'extension_modules': os.path.join(
@ -178,7 +196,9 @@ class TestGetTemplate(TestCase):
filename = os.path.join(TEMPLATES_DIR, 'files', 'test', 'hello_import')
out = render_jinja_tmpl(
salt.utils.fopen(filename).read(),
dict(opts={'cachedir': TEMPLATES_DIR, 'file_client': 'remote'},
dict(opts={'cachedir': TEMPLATES_DIR, 'file_client': 'remote',
'file_roots': self.local_opts['file_roots'],
'pillar_roots': self.local_opts['pillar_roots']},
a='Hi', b='Salt', saltenv='test'))
self.assertEqual(out, 'Hey world !Hi Salt !\n')
self.assertEqual(fc.requests[0]['path'], 'salt://macro')
@ -267,7 +287,9 @@ class TestGetTemplate(TestCase):
filename = os.path.join(TEMPLATES_DIR, 'files', 'test', 'hello_import')
out = render_jinja_tmpl(
salt.utils.fopen(filename).read(),
dict(opts={'cachedir': TEMPLATES_DIR, 'file_client': 'remote'},
dict(opts={'cachedir': TEMPLATES_DIR, 'file_client': 'remote',
'file_roots': self.local_opts['file_roots'],
'pillar_roots': self.local_opts['pillar_roots']},
a='Hi', b='Sàlt', saltenv='test'))
self.assertEqual(out, u'Hey world !Hi Sàlt !\n')
self.assertEqual(fc.requests[0]['path'], 'salt://macro')
@ -278,7 +300,9 @@ class TestGetTemplate(TestCase):
filename = os.path.join(TEMPLATES_DIR, 'files', 'test', 'non_ascii')
out = render_jinja_tmpl(
salt.utils.fopen(filename).read(),
dict(opts={'cachedir': TEMPLATES_DIR, 'file_client': 'remote'},
dict(opts={'cachedir': TEMPLATES_DIR, 'file_client': 'remote',
'file_roots': self.local_opts['file_roots'],
'pillar_roots': self.local_opts['pillar_roots']},
a='Hi', b='Sàlt', saltenv='test'))
self.assertEqual(u'Assunção\n', out)
self.assertEqual(fc.requests[0]['path'], 'salt://macro')