diff --git a/doc/topics/releases/2016.3.7.rst b/doc/topics/releases/2016.3.7.rst new file mode 100644 index 000000000000..ccde8c40db7a --- /dev/null +++ b/doc/topics/releases/2016.3.7.rst @@ -0,0 +1,5 @@ +=========================== +Salt 2016.3.7 Release Notes +=========================== + +Version 2016.3.7 is a bugfix release for :ref:`2016.3.0 `. diff --git a/salt/cloud/clouds/vmware.py b/salt/cloud/clouds/vmware.py index 6ba4be86473d..e3fec5de28bc 100644 --- a/salt/cloud/clouds/vmware.py +++ b/salt/cloud/clouds/vmware.py @@ -137,6 +137,7 @@ # Import 3rd-party libs import salt.ext.six as six try: + # Attempt to import pyVmomi libs from pyVmomi import vim HAS_PYVMOMI = True except Exception: @@ -149,7 +150,6 @@ except Exception: pass -# Attempt to import pyVim and pyVmomi libs ESX_5_5_NAME_PORTION = 'VMware ESXi 5.5' SAFE_ESX_5_5_CONTROLLER_KEY_INDEX = 200 FLATTEN_DISK_FULL_CLONE = 'moveAllDiskBackingsAndDisallowSharing' diff --git a/salt/crypt.py b/salt/crypt.py index bd7ddac52c74..f1f0dd6a2b29 100644 --- a/salt/crypt.py +++ b/salt/crypt.py @@ -886,7 +886,8 @@ def verify_master(self, payload, master_pub=True): m_pub_fn = os.path.join(self.opts['pki_dir'], self.mpub) m_pub_exists = os.path.isfile(m_pub_fn) if m_pub_exists and master_pub and not self.opts['open_mode']: - local_master_pub = salt.utils.fopen(m_pub_fn).read() + with salt.utils.fopen(m_pub_fn) as fp_: + local_master_pub = fp_.read() if payload['pub_key'].replace('\n', '').replace('\r', '') != \ local_master_pub.replace('\n', '').replace('\r', ''): @@ -936,9 +937,8 @@ def verify_master(self, payload, master_pub=True): if not m_pub_exists: # the minion has not received any masters pubkey yet, write # the newly received pubkey to minion_master.pub - salt.utils.fopen(m_pub_fn, 'wb+').write( - salt.utils.to_bytes(payload['pub_key']) - ) + with salt.utils.fopen(m_pub_fn, 'wb+') as fp_: + fp_.write(salt.utils.to_bytes(payload['pub_key'])) return self.extract_aes(payload, master_pub=False) def _finger_fail(self, finger, master_key): diff --git a/salt/modules/djangomod.py b/salt/modules/djangomod.py index f20405d8ca5d..76cb536d91e3 100644 --- a/salt/modules/djangomod.py +++ b/salt/modules/djangomod.py @@ -161,18 +161,19 @@ def loaddata(settings_module, salt '*' django.loaddata ''' - + args = [] kwargs = {} if database: kwargs['database'] = database + cmd = '{0} {1}'.format('loaddata', ' '.join(fixtures.split(','))) + return command(settings_module, - 'loaddata', + cmd, bin_env, pythonpath, env, - *fixtures.split(','), - **kwargs) + *args, **kwargs) def collectstatic(settings_module, diff --git a/salt/modules/rabbitmq.py b/salt/modules/rabbitmq.py index 60116f8ce7b8..b55f2dd17370 100644 --- a/salt/modules/rabbitmq.py +++ b/salt/modules/rabbitmq.py @@ -439,7 +439,7 @@ def check_password(name, password, runas=None): if server_version is None: raise ValueError - server_version = server_version.group(1) + server_version = server_version.group(1).split('-')[0] version = [int(i) for i in server_version.split('.')] except ValueError: version = (0, 0, 0) diff --git a/salt/modules/temp.py b/salt/modules/temp.py index 30c08bdc14f9..3eb29172cb52 100644 --- a/salt/modules/temp.py +++ b/salt/modules/temp.py @@ -10,6 +10,7 @@ from __future__ import absolute_import import logging +import os import tempfile log = logging.getLogger(__name__) @@ -40,4 +41,6 @@ def file(suffix='', prefix='tmp', parent=None): salt '*' temp.file salt '*' temp.file prefix='mytemp-' parent='/var/run/' ''' - return tempfile.mkstemp(suffix, prefix, parent)[1] + fh_, tmp_ = tempfile.mkstemp(suffix, prefix, parent) + os.close(fh_) + return tmp_ diff --git a/salt/modules/tuned.py b/salt/modules/tuned.py index 33a1485c9934..45d54b512b40 100644 --- a/salt/modules/tuned.py +++ b/salt/modules/tuned.py @@ -51,7 +51,7 @@ def list_(): result.pop() # Output can be : " - - " (v2.7.1) # or " - " (v2.4.1) - result = [i.split('-')[1].strip() for i in result] + result = [i.split('- ')[1].strip() for i in result] return result diff --git a/salt/modules/win_dsc.py b/salt/modules/win_dsc.py index 859be0169003..6de6d13722e3 100644 --- a/salt/modules/win_dsc.py +++ b/salt/modules/win_dsc.py @@ -40,15 +40,18 @@ def __virtual__(): ''' # Verify Windows if not salt.utils.is_windows(): + log.debug('Module DSC: Only available on Windows systems') return False, 'Module DSC: Only available on Windows systems' - # Verify PowerShell 5.0 + # Verify PowerShell powershell_info = __salt__['cmd.shell_info']('powershell') if not powershell_info['installed']: - return False, 'Module DSC: PowerShell not available' + log.debug('Module DSC: Requires PowerShell') + return False, 'Module DSC: Requires PowerShell' - if _StrictVersion(powershell_info['version']) < \ - _StrictVersion('5.0'): + # Verify PowerShell 5.0 or greater + if salt.utils.compare_versions(powershell_info['version'], '<', '5.0'): + log.debug('Module DSC: Requires PowerShell 5 or later') return False, 'Module DSC: Requires PowerShell 5 or later' return __virtualname__ diff --git a/salt/modules/win_file.py b/salt/modules/win_file.py index 1ea43d58e132..84d7138dee2e 100644 --- a/salt/modules/win_file.py +++ b/salt/modules/win_file.py @@ -56,7 +56,9 @@ RE_FLAG_TABLE, blockreplace, prepend, seek_read, seek_write, rename, lstat, path_exists_glob, write, pardir, join, HASHES, HASHES_REVMAP, comment, uncomment, _add_flags, comment_line, _regex_to_static, - _get_line_indent, apply_template_on_contents) + _get_line_indent, apply_template_on_contents, dirname, basename, + list_backups_dir) +from salt.modules.file import normpath as normpath_ from salt.utils import namespaced_function as _namespaced_function @@ -104,7 +106,8 @@ def __virtual__(): global blockreplace, prepend, seek_read, seek_write, rename, lstat global write, pardir, join, _add_flags, apply_template_on_contents global path_exists_glob, comment, uncomment, _mkstemp_copy - global _regex_to_static, _get_line_indent + global _regex_to_static, _get_line_indent, dirname, basename + global list_backups_dir, normpath_ replace = _namespaced_function(replace, globals()) search = _namespaced_function(search, globals()) @@ -161,6 +164,10 @@ def __virtual__(): _mkstemp_copy = _namespaced_function(_mkstemp_copy, globals()) _add_flags = _namespaced_function(_add_flags, globals()) apply_template_on_contents = _namespaced_function(apply_template_on_contents, globals()) + dirname = _namespaced_function(dirname, globals()) + basename = _namespaced_function(basename, globals()) + list_backups_dir = _namespaced_function(list_backups_dir, globals()) + normpath_ = _namespaced_function(normpath_, globals()) else: return False, 'Module win_file: Missing Win32 modules' @@ -176,7 +183,8 @@ def __virtual__(): } __func_alias__ = { - 'makedirs_': 'makedirs' + 'makedirs_': 'makedirs', + 'normpath_': 'normpath', } diff --git a/salt/modules/win_psget.py b/salt/modules/win_psget.py index 1671e0e421ac..12e5c23f81a4 100644 --- a/salt/modules/win_psget.py +++ b/salt/modules/win_psget.py @@ -31,16 +31,21 @@ def __virtual__(): ''' Set the system module of the kernel is Windows ''' + # Verify Windows if not salt.utils.is_windows(): - return False, 'Module PSGet: Module only works on Windows systems' + log.debug('Module PSGet: Only available on Windows systems') + return False, 'Module PSGet: Only available on Windows systems' - # Verify PowerShell 5.0 + # Verify PowerShell powershell_info = __salt__['cmd.shell_info']('powershell') - if not powershell_info['installed'] or \ - _StrictVersion( - powershell_info['version']) >= _StrictVersion('5.0'): - return False, 'Module DSC: Module only works with PowerShell 5 or ' \ - 'newer.' + if not powershell_info['installed']: + log.debug('Module PSGet: Requires PowerShell') + return False, 'Module PSGet: Requires PowerShell' + + # Verify PowerShell 5.0 or greater + if salt.utils.compare_versions(powershell_info['version'], '<', '5.0'): + log.debug('Module PSGet: Requires PowerShell 5 or newer') + return False, 'Module PSGet: Requires PowerShell 5 or newer.' return __virtualname__ diff --git a/salt/version.py b/salt/version.py index 810a57a588ea..2bf12b384ed9 100644 --- a/salt/version.py +++ b/salt/version.py @@ -600,6 +600,7 @@ def dependency_information(include_salt_cloud=False): ('python-gnupg', 'gnupg', '__version__'), ('mysql-python', 'MySQLdb', '__version__'), ('cherrypy', 'cherrypy', '__version__'), + ('docker-py', 'docker', '__version__'), ] if include_salt_cloud: diff --git a/tests/unit/modules/tuned_test.py b/tests/unit/modules/tuned_test.py new file mode 100644 index 000000000000..a5b65ee54065 --- /dev/null +++ b/tests/unit/modules/tuned_test.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import + +from salt.modules import tuned + +from salttesting import skipIf, TestCase +from salttesting.mock import NO_MOCK, NO_MOCK_REASON, MagicMock, patch + + +tuned.__salt__ = {} + + +@skipIf(NO_MOCK, NO_MOCK_REASON) +class TunedListTestCase(TestCase): + """ + Test the tuned.list_() method for different versions of tuned-adm + """ + def test_v_241(self): + """ + Test the list_ function for older tuned-adm (v2.4.1) + as shipped with CentOS-6 + """ + tuned_list = '''Available profiles: +- throughput-performance +- virtual-guest +- latency-performance +- laptop-battery-powersave +- laptop-ac-powersave +- virtual-host +- desktop-powersave +- server-powersave +- spindown-disk +- sap +- enterprise-storage +- default +Current active profile: throughput-performance''' + mock_cmd = MagicMock(return_value=tuned_list) + with patch.dict(tuned.__salt__, {'cmd.run': mock_cmd}): + self.assertEqual( + tuned.list_(), + ['throughput-performance', 'virtual-guest', + 'latency-performance', 'laptop-battery-powersave', + 'laptop-ac-powersave', 'virtual-host', + 'desktop-powersave', 'server-powersave', + 'spindown-disk', 'sap', 'enterprise-storage', 'default']) + + def test_v_271(self): + """ + Test the list_ function for newer tuned-adm (v2.7.1) + as shipped with CentOS-7 + """ + tuned_list = '''Available profiles: +- balanced - General non-specialized tuned profile +- desktop - Optmize for the desktop use-case +- latency-performance - Optimize for deterministic performance +- network-latency - Optimize for deterministic performance +- network-throughput - Optimize for streaming network throughput. +- powersave - Optimize for low power-consumption +- throughput-performance - Broadly applicable tuning that provides-- +- virtual-guest - Optimize for running inside a virtual-guest. +- virtual-host - Optimize for running KVM guests +Current active profile: virtual-guest +''' + mock_cmd = MagicMock(return_value=tuned_list) + with patch.dict(tuned.__salt__, {'cmd.run': mock_cmd}): + self.assertEqual( + tuned.list_(), + ['balanced', 'desktop', 'latency-performance', + 'network-latency', 'network-throughput', 'powersave', + 'throughput-performance', 'virtual-guest', + 'virtual-host'])