Merge pull request #47929 from rallytime/merge-develop

[develop] Merge forward from 2018.3 to develop
This commit is contained in:
Nicole Thomas 2018-06-04 10:37:30 -04:00 committed by GitHub
commit b004a1ace7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 5834 additions and 602 deletions

View File

@ -5,6 +5,16 @@ In Progress: Salt 2017.7.6 Release Notes
Version 2017.7.6 is an **unreleased** bugfix release for :ref:`2017.7.0 <release-2017-7-0>`.
This release is still in progress and has not been released yet.
Tornado 5.0 Support for Python 2 Only
-------------------------------------
Tornado 5.0 moves to using asyncio for all python3 versions. Because of this
and changes in asyncio between python 3.4 and 3.5 to only be able to use one
ioloop, which requires some rearchitecting, support for tornado 5.0 and python3
versions of salt has been delayed to a later release.
For now, to use tornado 5.0, the python 2 version of salt must be used.
Option to Return to Previous Pillar Include Behavior
----------------------------------------------------

View File

@ -0,0 +1,17 @@
===========================
In Progress: Salt 2017.7.7 Release Notes
===========================
Version 2017.7.7 is an **unreleased** bugfix release for :ref:`2017.7.0 <release-2017-7-0>`.
This release is still in progress and has not been released yet.
New win_snmp behavior
---------------------
`win_snmp.get_community_names` now returns the SNMP settings actually in effect
on the box. If settings are managed via GroupPolicy, those settings will be
returned. Otherwise, normal settings are returned.
`win_snmp.set_community_names` now raises a CommandExecutionError when SNMP
settings are being managed by GroupPolicy

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
========================================
In Progress: Salt 2018.3.2 Release Notes
========================================
Version 2018.3.2 is an **unreleased** bugfix release for :ref:`2018.3.0 <release-2018-3-0>`.
This release is still in progress and has not been released yet.
Changes to win_timezone
=======================
Improves timezone detection by using the pytz module.
``timezone.get_offset`` and ``timezone.get_zonecode`` now work properly.
Adds ``timezone.list`` to list supported timezones in either Windows or Unix
format.

View File

@ -4,7 +4,7 @@ Documentation=man:salt-master(1) file:///usr/share/doc/salt/html/contents.html h
After=network.target
[Service]
LimitNOFILE=16384
LimitNOFILE=100000
Type=simple
ExecStart=/usr/bin/salt-master
TasksMax=infinity

165
pkg/windows/sign.bat Normal file
View File

@ -0,0 +1,165 @@
:: ############################################################################
::
:: FILE: sign.bat
::
:: DESCRIPTION: Signing and Hashing script for Salt builds on Windows.
:: Requires an official Code Signing Certificate and drivers
:: installed to sign the files. Generates hashes in MD5 and
:: SHA256 in a file of the same name with a `.md5` or
:: `.sha256` extension.
::
:: NOTE: This script is used internally by SaltStack to sign and
:: hash Windows Installer builds and uses resources not
:: available to the community, such as SaltStack's Code
:: Signing Certificate. It is placed here for version
:: control.
::
:: COPYRIGHT: (c) 2012-2018 by the SaltStack Team
::
:: LICENSE: Apache 2.0
:: ORGANIZATION: SaltStack, Inc (saltstack.com)
:: CREATED: 2017
::
:: ############################################################################
::
:: USAGE: The script must be located in a directory that has the installer
:: files in a subfolder named with the major version, ie: `2018.3`.
:: Insert the key fob that contains the code signing certificate. Run
:: the script passing the full version: `.\sign.bat 2018.3.1`.
::
:: The script will sign the installers and generate the corresponding
:: hash files. These can then be uploaded to the salt repo.
::
:: The files must be in the following format:
:: <Series>\Salt-Minion-<Version>-<Python Version>-<System Architecture>-Setup.exe
:: So, for a Salt Minion installer for 2018.3.1 on AMD64 for Python 3
:: file would be placed in a subdirectory named `2018.3` and the file
:: would be named: `Salt-Minion-2018.3.1-Py3-AMD64-Setup.exe`. This
:: is how the file is created by the NSI Script anyway.
::
:: ############################################################################
@ echo off
if [%1]==[] (
echo You must pass a version
goto quit
) else (
set "Version=%~1"
)
for /F "tokens=1,2 delims=." %%a in ("%Version%") do (set Series=%%a.%%b)
:: Sign Installer Files
echo ===========================================================================
echo Signing...
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
signtool.exe sign /t http://timestamp.digicert.com ^
"%Series%\Salt-Minion-%Version%-AMD64-Setup.exe" ^
"%Series%\Salt-Minion-%Version%-x86-Setup.exe" ^
"%Series%\Salt-%Version%-AMD64-Setup.exe" ^
"%Series%\Salt-%Version%-x86-Setup.exe" ^
"%Series%\Salt-%Version%-Py2-AMD64-Setup.exe" ^
"%Series%\Salt-%Version%-Py2-x86-Setup.exe" ^
"%Series%\Salt-%Version%-Py3-AMD64-Setup.exe" ^
"%Series%\Salt-%Version%-Py3-x86-Setup.exe" ^
"%Series%\Salt-Minion-%Version%-Py2-AMD64-Setup.exe" ^
"%Series%\Salt-Minion-%Version%-Py2-x86-Setup.exe" ^
"%Series%\Salt-Minion-%Version%-Py3-AMD64-Setup.exe" ^
"%Series%\Salt-Minion-%Version%-Py3-x86-Setup.exe"
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Signing Complete
echo ===========================================================================
:: Create Hash files
echo ===========================================================================
echo Creating Hashes...
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
set "file_name=Salt-Minion-%Version%-AMD64-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
set "file_name=Salt-Minion-%Version%-x86-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
set "file_name=Salt-%Version%-AMD64-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
set "file_name=Salt-%Version%-x86-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
set "file_name=Salt-%Version%-Py2-AMD64-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
set "file_name=Salt-%Version%-Py2-x86-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
set "file_name=Salt-%Version%-Py3-AMD64-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
set "file_name=Salt-%Version%-Py3-x86-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
set "file_name=Salt-Minion-%Version%-Py2-AMD64-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
set "file_name=Salt-Minion-%Version%-Py2-x86-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
set "file_name=Salt-Minion-%Version%-Py3-AMD64-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
set "file_name=Salt-Minion-%Version%-Py3-x86-Setup.exe"
set "file=.\%Series%\%file_name%"
if exist "%file%" (
echo - %file_name%
powershell -c "$hash = (Get-FileHash -Algorithm MD5 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.md5\""
powershell -c "$hash = (Get-FileHash -Algorithm SHA256 \"%file%\").Hash; Out-File -InputObject $hash\" %file_name%\" -FilePath \"%file%.sha256\"")
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Hashing Complete
echo ===========================================================================
:quit

View File

@ -5,6 +5,8 @@ msgpack>=0.5,!=0.5.5
PyYAML
MarkupSafe
requests>=1.0.0
tornado>=4.2.1,<6.0
tornado>=4.2.1,<6.0; python_version < '3'
tornado>=4.2.1,<5.0; python_version >= '3.4'
# Required by Tornado to handle threads stuff.
futures>=2.0; python_version < '3.0'

View File

@ -2499,9 +2499,9 @@ def _hw_data(osdata):
product_regexes = [
re.compile(r) for r in [
r'(?im)^\s*System\s+Configuration:\s*.*?sun\d\S+\s(.*)', # prtdiag
r'(?im)^\s*banner-name:\s*(.*)', # prtconf
r'(?im)^\s*product-name:\s*(.*)', # prtconf
r'(?im)^\s*System\s+Configuration:\s*.*?sun\d\S+[^\S\r\n]*(.*)', # prtdiag
r'(?im)^[^\S\r\n]*banner-name:[^\S\r\n]*(.*)', # prtconf
r'(?im)^[^\S\r\n]*product-name:[^\S\r\n]*(.*)', # prtconf
]
]
@ -2568,8 +2568,11 @@ def _hw_data(osdata):
for regex in product_regexes:
res = regex.search(data)
if res and len(res.groups()) >= 1:
grains['product'] = res.group(1).strip().replace("'", "")
break
t_productname = res.group(1).strip().replace("'", "")
if t_productname:
grains['product'] = t_productname
grains['productname'] = t_productname
break
elif osdata['kernel'] == 'AIX':
cmd = salt.utils.path.which('prtconf')

View File

@ -74,8 +74,7 @@ def _atrun_enabled():
# Collect information on service: will raise an error if it fails
salt.utils.mac_utils.launchctl('list',
label,
return_stdout=True,
output_loglevel='quiet')
return_stdout=True)
return True
except CommandExecutionError:
return False
@ -111,9 +110,8 @@ def _enable_atrun():
return False
salt.utils.mac_utils.launchctl('enable',
'system/{0}'.format(label),
output_loglevel='quiet')
salt.utils.mac_utils.launchctl('load', path, output_loglevel='quiet')
'system/{0}'.format(label))
salt.utils.mac_utils.launchctl('load', path)
return _atrun_enabled()

View File

@ -35,7 +35,7 @@ Current known limitations
- lxml
- uuid
- struct
- salt.modules.reg
- salt.utils.win_reg
'''
# Import Python libs
from __future__ import absolute_import, unicode_literals, print_function
@ -98,7 +98,7 @@ try:
import lxml
import struct
from lxml import etree
from salt.modules.reg import Registry as Registry
from salt.utils.win_reg import Registry
HAS_WINDOWS_MODULES = True
TRUE_VALUE_XPATH = etree.XPath('.//*[local-name() = "trueValue"]')
FALSE_VALUE_XPATH = etree.XPath('.//*[local-name() = "falseValue"]')
@ -3345,9 +3345,11 @@ def __virtual__():
'''
Only works on Windows systems
'''
if salt.utils.platform.is_windows() and HAS_WINDOWS_MODULES:
return __virtualname__
return False
if not salt.utils.platform.is_windows():
return False, 'win_lgpo: Not a Windows System'
if not HAS_WINDOWS_MODULES:
return False, 'win_lgpo: Required modules failed to load'
return __virtualname__
def _updateNamespace(item, new_namespace):
@ -6045,7 +6047,7 @@ def set_(computer_policy=None, user_policy=None,
else:
raise SaltInvocationError(msg)
if policy_namespace and policy_name in _admTemplateData[policy_namespace] and the_policy is not None:
log.debug('setting == %s', _admTemplateData[policy_namespace][policy_name].lower())
log.debug('setting == %s', six.text_type(_admTemplateData[policy_namespace][policy_name]).lower())
log.debug(six.text_type(_admTemplateData[policy_namespace][policy_name]).lower())
if six.text_type(_admTemplateData[policy_namespace][policy_name]).lower() != 'disabled' \
and six.text_type(_admTemplateData[policy_namespace][policy_name]).lower() != 'not configured':

View File

@ -9,16 +9,20 @@ import logging
# Import Salt libs
import salt.utils.platform
from salt.exceptions import SaltInvocationError
from salt.exceptions import SaltInvocationError, CommandExecutionError
# Import 3rd party libs
from salt.ext import six
_HKEY = 'HKLM'
_SNMP_KEY = r'SYSTEM\CurrentControlSet\Services\SNMP\Parameters'
_AGENT_KEY = r'{0}\RFC1156Agent'.format(_SNMP_KEY)
_COMMUNITIES_KEY = r'{0}\ValidCommunities'.format(_SNMP_KEY)
_SNMP_GPO_KEY = r'SOFTWARE\Policies\SNMP\Parameters'
_COMMUNITIES_GPO_KEY = r'{0}\ValidCommunities'.format(_SNMP_GPO_KEY)
_PERMISSION_TYPES = {'None': 1,
'Notify': 2,
'Read Only': 4,
@ -284,6 +288,21 @@ def get_community_names():
'''
Get the current accepted SNMP community names and their permissions.
If community names are being managed by Group Policy, those values will be
returned instead like this:
.. code-block:: bash
TestCommunity:
Managed by GPO
Community names managed normally will denote the permission instead:
.. code-block:: bash
TestCommunity:
Read Only
Returns:
dict: A dictionary of community names and permissions.
@ -294,25 +313,69 @@ def get_community_names():
salt '*' win_snmp.get_community_names
'''
ret = dict()
current_values = __salt__['reg.list_values'](
_HKEY, _COMMUNITIES_KEY, include_default=False)
# The communities are stored as the community name with a numeric permission
# value. Convert the numeric value to the text equivalent, as present in the
# Windows SNMP service GUI.
if isinstance(current_values, list):
for current_value in current_values:
# Look in GPO settings first
if __salt__['reg.key_exists'](_HKEY, _COMMUNITIES_GPO_KEY):
# Ignore error values
if not isinstance(current_value, dict):
continue
_LOG.debug('Loading communities from Group Policy settings')
permissions = six.text_type()
for permission_name in _PERMISSION_TYPES:
if current_value['vdata'] == _PERMISSION_TYPES[permission_name]:
permissions = permission_name
break
ret[current_value['vname']] = permissions
current_values = __salt__['reg.list_values'](
_HKEY, _COMMUNITIES_GPO_KEY, include_default=False)
# GPO settings are different in that they do not designate permissions
# They are a numbered list of communities like so:
#
# {1: "community 1",
# 2: "community 2"}
#
# Denote that it is being managed by Group Policy.
#
# community 1:
# Managed by GPO
# community 2:
# Managed by GPO
if isinstance(current_values, list):
for current_value in current_values:
# Ignore error values
if not isinstance(current_value, dict):
continue
ret[current_value['vdata']] = 'Managed by GPO'
if not ret:
_LOG.debug('Loading communities from SNMP settings')
current_values = __salt__['reg.list_values'](
_HKEY, _COMMUNITIES_KEY, include_default=False)
# The communities are stored as the community name with a numeric
# permission value. Like this (4 = Read Only):
#
# {"community 1": 4,
# "community 2": 4}
#
# Convert the numeric value to the text equivalent, as present in the
# Windows SNMP service GUI.
#
# community 1:
# Read Only
# community 2:
# Read Only
if isinstance(current_values, list):
for current_value in current_values:
# Ignore error values
if not isinstance(current_value, dict):
continue
permissions = six.text_type()
for permission_name in _PERMISSION_TYPES:
if current_value['vdata'] == _PERMISSION_TYPES[permission_name]:
permissions = permission_name
break
ret[current_value['vname']] = permissions
if not ret:
_LOG.debug('Unable to find existing communities.')
@ -323,6 +386,11 @@ def set_community_names(communities):
'''
Manage the SNMP accepted community names and their permissions.
.. note::
Settings managed by Group Policy will always take precedence over those
set using the SNMP interface. Therefore if this function finds Group
Policy settings it will raise a CommandExecutionError
Args:
communities (dict): A dictionary of SNMP community names and
permissions. The possible permissions can be found via
@ -331,6 +399,10 @@ def set_community_names(communities):
Returns:
bool: True if successful, otherwise False
Raises:
CommandExecutionError:
If SNMP settings are being managed by Group Policy
CLI Example:
.. code-block:: bash
@ -339,6 +411,11 @@ def set_community_names(communities):
'''
values = dict()
if __salt__['reg.key_exists'](_HKEY, _COMMUNITIES_GPO_KEY):
_LOG.debug('Communities on this system are managed by Group Policy')
raise CommandExecutionError(
'Communities on this system are managed by Group Policy')
current_communities = get_community_names()
if communities == current_communities:

View File

@ -6,487 +6,224 @@ from __future__ import absolute_import, unicode_literals, print_function
# Import Python libs
import logging
import re
from datetime import datetime
# Import Salt libs
import salt.utils.path
import salt.utils.platform
from salt.exceptions import CommandExecutionError
# Import 3rd party libs
try:
import pytz
HAS_PYTZ = True
except ImportError:
HAS_PYTZ = False
log = logging.getLogger(__name__)
# Maybe put in a different file ... ? %-0
# http://unicode.org/repos/cldr/trunk/common/supplemental/windowsZones.xml
LINTOWIN = {
'Africa/Abidjan': 'Greenwich Standard Time',
'Africa/Accra': 'Greenwich Standard Time',
'Africa/Addis_Ababa': 'E. Africa Standard Time',
'Africa/Algiers': 'W. Central Africa Standard Time',
'Africa/Asmera': 'E. Africa Standard Time',
'Africa/Bamako': 'Greenwich Standard Time',
'Africa/Bangui': 'W. Central Africa Standard Time',
'Africa/Banjul': 'Greenwich Standard Time',
'Africa/Bissau': 'Greenwich Standard Time',
'Africa/Blantyre': 'South Africa Standard Time',
'Africa/Brazzaville': 'W. Central Africa Standard Time',
'Africa/Bujumbura': 'South Africa Standard Time',
'Africa/Cairo': 'Egypt Standard Time',
'Africa/Casablanca': 'Morocco Standard Time',
'Africa/Conakry': 'Greenwich Standard Time',
'Africa/Dakar': 'Greenwich Standard Time',
'Africa/Dar_es_Salaam': 'E. Africa Standard Time',
'Africa/Djibouti': 'E. Africa Standard Time',
'Africa/Douala': 'W. Central Africa Standard Time',
'Africa/El_Aaiun': 'Greenwich Standard Time',
'Africa/Freetown': 'Greenwich Standard Time',
'Africa/Gaborone': 'South Africa Standard Time',
'Africa/Harare': 'South Africa Standard Time',
'Africa/Johannesburg': 'South Africa Standard Time',
'Africa/Juba': 'E. Africa Standard Time',
'Africa/Kampala': 'E. Africa Standard Time',
'Africa/Khartoum': 'E. Africa Standard Time',
'Africa/Kigali': 'South Africa Standard Time',
'Africa/Kinshasa': 'W. Central Africa Standard Time',
'Africa/Lagos': 'W. Central Africa Standard Time',
'Africa/Libreville': 'W. Central Africa Standard Time',
'Africa/Lome': 'Greenwich Standard Time',
'Africa/Luanda': 'W. Central Africa Standard Time',
'Africa/Lubumbashi': 'South Africa Standard Time',
'Africa/Lusaka': 'South Africa Standard Time',
'Africa/Malabo': 'W. Central Africa Standard Time',
'Africa/Maputo': 'South Africa Standard Time',
'Africa/Maseru': 'South Africa Standard Time',
'Africa/Mbabane': 'South Africa Standard Time',
'Africa/Mogadishu': 'E. Africa Standard Time',
'Africa/Monrovia': 'Greenwich Standard Time',
'Africa/Nairobi': 'E. Africa Standard Time',
'Africa/Ndjamena': 'W. Central Africa Standard Time',
'Africa/Niamey': 'W. Central Africa Standard Time',
'Africa/Nouakchott': 'Greenwich Standard Time',
'Africa/Ouagadougou': 'Greenwich Standard Time',
'Africa/Porto-Novo': 'W. Central Africa Standard Time',
'Africa/Sao_Tome': 'Greenwich Standard Time',
'Africa/Tripoli': 'W. Europe Standard Time',
'Africa/Tunis': 'W. Central Africa Standard Time',
'Africa/Windhoek': 'Namibia Standard Time',
'America/Anchorage': 'Alaskan Standard Time',
'America/Juneau': 'Alaskan Standard Time',
'America/Nome': 'Alaskan Standard Time',
'America/Sitka': 'Alaskan Standard Time',
'America/Yakutat': 'Alaskan Standard Time',
'America/Anguilla': 'SA Western Standard Time',
'America/Antigua': 'SA Western Standard Time',
'America/Aruba': 'SA Western Standard Time',
'America/Asuncion': 'Paraguay Standard Time',
'America/Bahia': 'Bahia Standard Time',
'America/Barbados': 'SA Western Standard Time',
'America/Belize': 'Central America Standard Time',
'America/Blanc-Sablon': 'SA Western Standard Time',
'America/Bogota': 'SA Pacific Standard Time',
'America/Buenos_Aires': 'Argentina Standard Time',
'America/Argentina/La_Rioja': 'Argentina Standard Time',
'America/Argentina/Rio_Gallegos': 'Argentina Standard Time',
'America/Argentina/Salta': 'Argentina Standard Time',
'America/Argentina/San_Juan': 'Argentina Standard Time',
'America/Argentina/San_Luis': 'Argentina Standard Time',
'America/Argentina/Tucuman': 'Argentina Standard Time',
'America/Argentina/Ushuaia': 'Argentina Standard Time',
'America/Catamarca': 'Argentina Standard Time',
'America/Cordoba': 'Argentina Standard Time',
'America/Jujuy': 'Argentina Standard Time',
'America/Mendoza': 'Argentina Standard Time',
'America/Caracas': 'Venezuela Standard Time',
'America/Cayenne': 'SA Eastern Standard Time',
'America/Cayman': 'SA Pacific Standard Time',
'America/Chicago': 'Central Standard Time',
'America/Indiana/Knox': 'Central Standard Time',
'America/Indiana/Tell_City': 'Central Standard Time',
'America/Menominee': 'Central Standard Time',
'America/North_Dakota/Beulah': 'Central Standard Time',
'America/North_Dakota/Center': 'Central Standard Time',
'America/North_Dakota/New_Salem': 'Central Standard Time',
'America/Chihuahua': 'Mountain Standard Time (Mexico)',
'America/Mazatlan': 'Mountain Standard Time (Mexico)',
'America/Coral_Harbour': 'SA Pacific Standard Time',
'America/Costa_Rica': 'Central America Standard Time',
'America/Cuiaba': 'Central Brazilian Standard Time',
'America/Campo_Grande': 'Central Brazilian Standard Time',
'America/Curacao': 'SA Western Standard Time',
'America/Danmarkshavn': 'UTC',
'America/Dawson_Creek': 'US Mountain Standard Time',
'America/Creston': 'US Mountain Standard Time',
'America/Denver': 'Mountain Standard Time',
'America/Boise': 'Mountain Standard Time',
'America/Shiprock': 'Mountain Standard Time',
'America/Dominica': 'SA Western Standard Time',
'America/Edmonton': 'Mountain Standard Time',
'America/Cambridge_Bay': 'Mountain Standard Time',
'America/Inuvik': 'Mountain Standard Time',
'America/Yellowknife': 'Mountain Standard Time',
'America/El_Salvador': 'Central America Standard Time',
'America/Fortaleza': 'SA Eastern Standard Time',
'America/Belem': 'SA Eastern Standard Time',
'America/Maceio': 'SA Eastern Standard Time',
'America/Recife': 'SA Eastern Standard Time',
'America/Santarem': 'SA Eastern Standard Time',
'America/Godthab': 'Greenland Standard Time',
'America/Grand_Turk': 'Eastern Standard Time',
'America/Grenada': 'SA Western Standard Time',
'America/Guadeloupe': 'SA Western Standard Time',
'America/Guatemala': 'Central America Standard Time',
'America/Guayaquil': 'SA Pacific Standard Time',
'America/Guyana': 'SA Western Standard Time',
'America/Halifax': 'Atlantic Standard Time',
'America/Glace_Bay': 'Atlantic Standard Time',
'America/Goose_Bay': 'Atlantic Standard Time',
'America/Moncton': 'Atlantic Standard Time',
'America/Hermosillo': 'US Mountain Standard Time',
'America/Indianapolis': 'US Eastern Standard Time',
'America/Indiana/Marengo': 'US Eastern Standard Time',
'America/Indiana/Vevay': 'US Eastern Standard Time',
'America/Jamaica': 'SA Pacific Standard Time',
'America/Kralendijk': 'SA Western Standard Time',
'America/La_Paz': 'SA Western Standard Time',
'America/Lima': 'SA Pacific Standard Time',
'America/Los_Angeles': 'Pacific Standard Time',
'America/Lower_Princes': 'SA Western Standard Time',
'America/Managua': 'Central America Standard Time',
'America/Manaus': 'SA Western Standard Time',
'America/Boa_Vista': 'SA Western Standard Time',
'America/Eirunepe': 'SA Western Standard Time',
'America/Porto_Velho': 'SA Western Standard Time',
'America/Rio_Branco': 'SA Western Standard Time',
'America/Marigot': 'SA Western Standard Time',
'America/Martinique': 'SA Western Standard Time',
'America/Matamoros': 'Central Standard Time',
'America/Mexico_City': 'Central Standard Time (Mexico)',
'America/Bahia_Banderas': 'Central Standard Time (Mexico)',
'America/Cancun': 'Central Standard Time (Mexico)',
'America/Merida': 'Central Standard Time (Mexico)',
'America/Monterrey': 'Central Standard Time (Mexico)',
'America/Montevideo': 'Montevideo Standard Time',
'America/Montserrat': 'SA Western Standard Time',
'America/Nassau': 'Eastern Standard Time',
'America/New_York': 'Eastern Standard Time',
'America/Detroit': 'Eastern Standard Time',
'America/Indiana/Petersburg': 'Eastern Standard Time',
'America/Indiana/Vincennes': 'Eastern Standard Time',
'America/Indiana/Winamac': 'Eastern Standard Time',
'America/Kentucky/Monticello': 'Eastern Standard Time',
'America/Louisville': 'Eastern Standard Time',
'America/Noronha': 'UTC-02',
'America/Ojinaga': 'Mountain Standard Time',
'America/Panama': 'SA Pacific Standard Time',
'America/Paramaribo': 'SA Eastern Standard Time',
'America/Phoenix': 'US Mountain Standard Time',
'America/Port-au-Prince': 'SA Pacific Standard Time',
'America/Port_of_Spain': 'SA Western Standard Time',
'America/Puerto_Rico': 'SA Western Standard Time',
'America/Regina': 'Canada Central Standard Time',
'America/Swift_Current': 'Canada Central Standard Time',
'America/Santa_Isabel': 'Pacific Standard Time (Mexico)',
'America/Santiago': 'Pacific SA Standard Time',
'America/Santo_Domingo': 'SA Western Standard Time',
'America/Sao_Paulo': 'E. South America Standard Time',
'America/Araguaina': 'E. South America Standard Time',
'America/Scoresbysund': 'Azores Standard Time',
'America/St_Barthelemy': 'SA Western Standard Time',
'America/St_Johns': 'Newfoundland Standard Time',
'America/St_Kitts': 'SA Western Standard Time',
'America/St_Lucia': 'SA Western Standard Time',
'America/St_Thomas': 'SA Western Standard Time',
'America/St_Vincent': 'SA Western Standard Time',
'America/Tegucigalpa': 'Central America Standard Time',
'America/Thule': 'Atlantic Standard Time',
'America/Tijuana': 'Pacific Standard Time',
'America/Toronto': 'Eastern Standard Time',
'America/Iqaluit': 'Eastern Standard Time',
'America/Montreal': 'Eastern Standard Time',
'America/Nipigon': 'Eastern Standard Time',
'America/Pangnirtung': 'Eastern Standard Time',
'America/Thunder_Bay': 'Eastern Standard Time',
'America/Tortola': 'SA Western Standard Time',
'America/Whitehorse': 'Pacific Standard Time',
'America/Vancouver': 'Pacific Standard Time',
'America/Dawson': 'Pacific Standard Time',
'America/Winnipeg': 'Central Standard Time',
'America/Rainy_River': 'Central Standard Time',
'America/Rankin_Inlet': 'Central Standard Time',
'America/Resolute': 'Central Standard Time',
'Antarctica/Casey': 'W. Australia Standard Time',
'Antarctica/Davis': 'SE Asia Standard Time',
'Antarctica/DumontDUrville': 'West Pacific Standard Time',
'Antarctica/Macquarie': 'Central Pacific Standard Time',
'Antarctica/Mawson': 'West Asia Standard Time',
'Antarctica/Palmer': 'Pacific SA Standard Time',
'Antarctica/Rothera': 'SA Eastern Standard Time',
'Antarctica/South_Pole': 'New Zealand Standard Time',
'Antarctica/McMurdo': 'New Zealand Standard Time',
'Antarctica/Syowa': 'E. Africa Standard Time',
'Antarctica/Vostok': 'Central Asia Standard Time',
'Arctic/Longyearbyen': 'W. Europe Standard Time',
'Asia/Aden': 'Arab Standard Time',
'Asia/Almaty': 'Central Asia Standard Time',
'Asia/Qyzylorda': 'Central Asia Standard Time',
'Asia/Amman': 'Jordan Standard Time',
'Asia/Ashgabat': 'West Asia Standard Time',
'Asia/Baghdad': 'Arabic Standard Time',
'Asia/Bahrain': 'Arab Standard Time',
'Asia/Baku': 'Azerbaijan Standard Time',
'Asia/Bangkok': 'SE Asia Standard Time',
'Asia/Beirut': 'Middle East Standard Time',
'Asia/Bishkek': 'Central Asia Standard Time',
'Asia/Brunei': 'Singapore Standard Time',
'Asia/Calcutta': 'India Standard Time',
'Asia/Colombo': 'Sri Lanka Standard Time',
'Asia/Damascus': 'Syria Standard Time',
'Asia/Dhaka': 'Bangladesh Standard Time',
'Asia/Dili': 'Tokyo Standard Time',
'Asia/Dubai': 'Arabian Standard Time',
'Asia/Dushanbe': 'West Asia Standard Time',
'Asia/Gaza': 'Egypt Standard Time',
'Asia/Hebron': 'Egypt Standard Time',
'Asia/Hong_Kong': 'China Standard Time',
'Asia/Hovd': 'SE Asia Standard Time',
'Asia/Irkutsk': 'North Asia East Standard Time',
'Asia/Jakarta': 'SE Asia Standard Time',
'Asia/Pontianak': 'SE Asia Standard Time',
'Asia/Jayapura': 'Tokyo Standard Time',
'Asia/Jerusalem': 'Israel Standard Time',
'Asia/Kabul': 'Afghanistan Standard Time',
'Asia/Karachi': 'Pakistan Standard Time',
'Asia/Kathmandu': 'Nepal Standard Time',
'Asia/Katmandu': 'Nepal Standard Time',
'Asia/Krasnoyarsk': 'North Asia Standard Time',
'Asia/Kuala_Lumpur': 'Singapore Standard Time',
'Asia/Kuching': 'Singapore Standard Time',
'Asia/Kuwait': 'Arab Standard Time',
'Asia/Macau': 'China Standard Time',
'Asia/Magadan': 'Magadan Standard Time',
'Asia/Anadyr Asia/Kamchatka': 'Magadan Standard Time',
'Asia/Kamchatka': 'Magadan Standard Time',
'Asia/Makassar': 'Singapore Standard Time',
'Asia/Manila': 'Singapore Standard Time',
'Asia/Muscat': 'Arabian Standard Time',
'Asia/Nicosia': 'E. Europe Standard Time',
'Asia/Novosibirsk': 'N. Central Asia Standard Time',
'Asia/Novokuznetsk': 'N. Central Asia Standard Time',
'Asia/Omsk': 'N. Central Asia Standard Time',
'Asia/Oral': 'West Asia Standard Time',
'Asia/Aqtau': 'West Asia Standard Time',
'Asia/Aqtobe': 'West Asia Standard Time',
'Asia/Phnom_Penh': 'SE Asia Standard Time',
'Asia/Pyongyang': 'Korea Standard Time',
'Asia/Qatar': 'Arab Standard Time',
'Asia/Rangoon': 'Myanmar Standard Time',
'Asia/Riyadh': 'Arab Standard Time',
'Asia/Saigon': 'SE Asia Standard Time',
'Asia/Seoul': 'Korea Standard Time',
'Asia/Shanghai': 'China Standard Time',
'Asia/Chongqing': 'China Standard Time',
'Asia/Harbin': 'China Standard Time',
'Asia/Kashgar': 'China Standard Time',
'Asia/Urumqi': 'China Standard Time',
'Asia/Singapore': 'Singapore Standard Time',
'Asia/Taipei': 'Taipei Standard Time',
'Asia/Tashkent': 'West Asia Standard Time',
'Asia/Samarkand': 'West Asia Standard Time',
'Asia/Tbilisi': 'Georgian Standard Time',
'Asia/Tehran': 'Iran Standard Time',
'Asia/Thimphu': 'Bangladesh Standard Time',
'Asia/Tokyo': 'Tokyo Standard Time',
'Asia/Ulaanbaatar': 'Ulaanbaatar Standard Time',
'Asia/Choibalsan': 'Ulaanbaatar Standard Time',
'Asia/Vientiane': 'SE Asia Standard Time',
'Asia/Vladivostok': 'Vladivostok Standard Time',
'Asia/Ust-Nera': 'Vladivostok Standard Time',
'Asia/Sakhalin': 'Vladivostok Standard Time',
'Asia/Yakutsk': 'Yakutsk Standard Time',
'Asia/Khandyga': 'Yakutsk Standard Time',
'Asia/Yekaterinburg': 'Ekaterinburg Standard Time',
'Asia/Yerevan': 'Caucasus Standard Time',
'Atlantic/Azores': 'Azores Standard Time',
'Atlantic/Bermuda': 'Atlantic Standard Time',
'Atlantic/Canary': 'GMT Standard Time',
'Atlantic/Cape_Verde': 'Cape Verde Standard Time',
'Atlantic/Faeroe': 'GMT Standard Time',
'Atlantic/Reykjavik': 'Greenwich Standard Time',
'Atlantic/South_Georgia': 'UTC-02',
'Atlantic/St_Helena': 'Greenwich Standard Time',
'Atlantic/Stanley': 'SA Eastern Standard Time',
'Australia/Adelaide': 'Cen. Australia Standard Time',
'Australia/Broken_Hill': 'Cen. Australia Standard Time',
'Australia/Brisbane': 'E. Australia Standard Time',
'Australia/Lindeman': 'E. Australia Standard Time',
'Australia/Darwin': 'AUS Central Standard Time',
'Australia/Hobart': 'Tasmania Standard Time',
'Australia/Currie': 'Tasmania Standard Time',
'Australia/Perth': 'W. Australia Standard Time',
'Australia/Sydney': 'AUS Eastern Standard Time',
'Australia/Melbourne': 'AUS Eastern Standard Time',
'CST6CDT': 'Central Standard Time',
'EST5EDT': 'Eastern Standard Time',
'Etc/UTC': 'UTC',
'Etc/GMT': 'UTC',
'Etc/GMT+1': 'Cape Verde Standard Time',
'Etc/GMT+10': 'Hawaiian Standard Time',
'Etc/GMT+11': 'UTC-11',
'Etc/GMT+12': 'Dateline Standard Time',
'Etc/GMT+2': 'UTC-02',
'Etc/GMT+3': 'SA Eastern Standard Time',
'Etc/GMT+4': 'SA Western Standard Time',
'Etc/GMT+5': 'SA Pacific Standard Time',
'Etc/GMT+6': 'Central America Standard Time',
'Etc/GMT+7': 'US Mountain Standard Time',
'Etc/GMT-1': 'W. Central Africa Standard Time',
'Etc/GMT-10': 'West Pacific Standard Time',
'Etc/GMT-11': 'Central Pacific Standard Time',
'Etc/GMT-12': 'UTC+12',
'Etc/GMT-13': 'Tonga Standard Time',
'Etc/GMT-2': 'South Africa Standard Time',
'Etc/GMT-3': 'E. Africa Standard Time',
'Etc/GMT-4': 'Arabian Standard Time',
'Etc/GMT-5': 'West Asia Standard Time',
'Etc/GMT-6': 'Central Asia Standard Time',
'Etc/GMT-7': 'SE Asia Standard Time',
'Etc/GMT-8': 'Singapore Standard Time',
'Etc/GMT-9': 'Tokyo Standard Time',
'Europe/Amsterdam': 'W. Europe Standard Time',
'Europe/Andorra': 'W. Europe Standard Time',
'Europe/Athens': 'GTB Standard Time',
'Europe/Belgrade': 'Central Europe Standard Time',
'Europe/Berlin': 'W. Europe Standard Time',
'Europe/Busingen': 'W. Europe Standard Time',
'Europe/Bratislava': 'Central Europe Standard Time',
'Europe/Brussels': 'Romance Standard Time',
'Europe/Bucharest': 'GTB Standard Time',
'Europe/Budapest': 'Central Europe Standard Time',
'Europe/Chisinau': 'GTB Standard Time',
'Europe/Copenhagen': 'Romance Standard Time',
'Europe/Dublin': 'GMT Standard Time',
'Europe/Gibraltar': 'W. Europe Standard Time',
'Europe/Guernsey': 'GMT Standard Time',
'Europe/Helsinki': 'FLE Standard Time',
'Europe/Isle_of_Man': 'GMT Standard Time',
'Europe/Istanbul': 'Turkey Standard Time',
'Europe/Jersey': 'GMT Standard Time',
'Europe/Kaliningrad': 'Kaliningrad Standard Time',
'Europe/Kiev': 'FLE Standard Time',
'Europe/Simferopol': 'FLE Standard Time',
'Europe/Uzhgorod': 'FLE Standard Time',
'Europe/Zaporozhye': 'FLE Standard Time',
'Europe/Lisbon': 'GMT Standard Time',
'Atlantic/Madeira': 'GMT Standard Time',
'Europe/Ljubljana': 'Central Europe Standard Time',
'Europe/London': 'GMT Standard Time',
'Europe/Luxembourg': 'W. Europe Standard Time',
'Europe/Madrid': 'Romance Standard Time',
'Africa/Ceuta': 'Romance Standard Time',
'Europe/Malta': 'W. Europe Standard Time',
'Europe/Mariehamn': 'FLE Standard Time',
'Europe/Minsk': 'Kaliningrad Standard Time',
'Europe/Monaco': 'W. Europe Standard Time',
'Europe/Moscow': 'Russian Standard Time',
'Europe/Volgograd': 'Russian Standard Time',
'Europe/Samara': 'Russian Standard Time',
'Europe/Oslo': 'W. Europe Standard Time',
'Europe/Paris': 'Romance Standard Time',
'Europe/Podgorica': 'Central Europe Standard Time',
'Europe/Prague': 'Central Europe Standard Time',
'Europe/Riga': 'FLE Standard Time',
'Europe/Rome': 'W. Europe Standard Time',
'Europe/San_Marino': 'W. Europe Standard Time',
'Europe/Sarajevo': 'Central European Standard Time',
'Europe/Skopje': 'Central European Standard Time',
'Europe/Sofia': 'FLE Standard Time',
'Europe/Stockholm': 'W. Europe Standard Time',
'Europe/Tallinn': 'FLE Standard Time',
'Europe/Tirane': 'Central Europe Standard Time',
'Europe/Vaduz': 'W. Europe Standard Time',
'Europe/Vatican': 'W. Europe Standard Time',
'Europe/Vienna': 'W. Europe Standard Time',
'Europe/Vilnius': 'FLE Standard Time',
'Europe/Warsaw': 'Central European Standard Time',
'Europe/Zagreb': 'Central European Standard Time',
'Europe/Zurich': 'W. Europe Standard Time',
'Indian/Antananarivo': 'E. Africa Standard Time',
'Indian/Chagos': 'Central Asia Standard Time',
'Indian/Christmas': 'SE Asia Standard Time',
'Indian/Cocos': 'Myanmar Standard Time',
'Indian/Comoro': 'E. Africa Standard Time',
'Indian/Kerguelen': 'West Asia Standard Time',
'Indian/Mahe': 'Mauritius Standard Time',
'Indian/Maldives': 'West Asia Standard Time',
'Indian/Mauritius': 'Mauritius Standard Time',
'Indian/Mayotte': 'E. Africa Standard Time',
'Indian/Reunion': 'Mauritius Standard Time',
'MST7MDT': 'Mountain Standard Time',
'PST8PDT': 'Pacific Standard Time',
'Pacific/Apia': 'Samoa Standard Time',
'Pacific/Auckland': 'New Zealand Standard Time',
'Pacific/Efate': 'Central Pacific Standard Time',
'Pacific/Enderbury': 'Tonga Standard Time',
'Pacific/Fakaofo': 'Tonga Standard Time',
'Pacific/Fiji': 'Fiji Standard Time',
'Pacific/Funafuti': 'UTC+12',
'Pacific/Galapagos': 'Central America Standard Time',
'Pacific/Guadalcanal': 'Central Pacific Standard Time',
'Pacific/Guam': 'West Pacific Standard Time',
'Pacific/Honolulu': 'Hawaiian Standard Time',
'Pacific/Johnston': 'Hawaiian Standard Time',
'Pacific/Majuro Pacific/Kwajalein': 'UTC+12',
'Pacific/Midway': 'UTC-11',
'Pacific/Nauru': 'UTC+12',
'Pacific/Niue': 'UTC-11',
'Pacific/Noumea': 'Central Pacific Standard Time',
'Pacific/Pago_Pago': 'UTC-11',
'Pacific/Palau': 'Tokyo Standard Time',
'Pacific/Ponape': 'Central Pacific Standard Time',
'Pacific/Kosrae': 'Central Pacific Standard Time',
'Pacific/Port_Moresby': 'West Pacific Standard Time',
'Pacific/Rarotonga': 'Hawaiian Standard Time',
'Pacific/Saipan': 'West Pacific Standard Time',
'Pacific/Tahiti': 'Hawaiian Standard Time',
'Pacific/Tarawa': 'UTC+12',
'Pacific/Tongatapu': 'Tonga Standard Time',
'Pacific/Truk': 'West Pacific Standard Time',
'Pacific/Wake': 'UTC+12',
'Pacific/Wallis': 'UTC+12'
}
# Define the module's virtual name
__virtualname__ = 'timezone'
class TzMapper(object):
def __init__(self, unix_to_win):
self.win_to_unix = {k.lower(): v for k, v in unix_to_win.items()}
self.unix_to_win = {v.lower(): k for k, v in unix_to_win.items()}
def add(self, k, v):
self.unix_to_win[k.lower()] = v
self.win_to_unix[v.lower()] = k
def remove(self, k):
self.win_to_unix.pop(self.unix_to_win.pop(k.lower()).lower())
def get_win(self, key, default=None):
return self.unix_to_win.get(key.lower(), default)
def get_unix(self, key, default=None):
return self.win_to_unix.get(key.lower(), default)
def list_win(self):
return sorted(self.unix_to_win.values())
def list_unix(self):
return sorted(self.win_to_unix.values())
mapper = TzMapper({
'AUS Central Standard Time': 'Australia/Darwin',
'AUS Eastern Standard Time': 'Australia/Sydney',
'Afghanistan Standard Time': 'Asia/Kabul',
'Alaskan Standard Time': 'America/Anchorage',
'Aleutian Standard Time': 'America/Adak',
'Altai Standard Time': 'Asia/Barnaul',
'Arab Standard Time': 'Asia/Riyadh',
'Arabian Standard Time': 'Asia/Dubai',
'Arabic Standard Time': 'Asia/Baghdad',
'Argentina Standard Time': 'America/Buenos_Aires',
'Astrakhan Standard Time': 'Europe/Astrakhan',
'Atlantic Standard Time': 'America/Halifax',
'Aus Central W. Standard Time': 'Australia/Eucla',
'Azerbaijan Standard Time': 'Asia/Baku',
'Azores Standard Time': 'Atlantic/Azores',
'Bahia Standard Time': 'America/Bahia',
'Bangladesh Standard Time': 'Asia/Dhaka',
'Belarus Standard Time': 'Europe/Minsk',
'Bougainville Standard Time': 'Pacific/Bougainville',
'Canada Central Standard Time': 'America/Regina',
'Cape Verde Standard Time': 'Atlantic/Cape_Verde',
'Caucasus Standard Time': 'Asia/Yerevan',
'Cen. Australia Standard Time': 'Australia/Adelaide',
'Central America Standard Time': 'America/Guatemala',
'Central Asia Standard Time': 'Asia/Almaty',
'Central Brazilian Standard Time': 'America/Cuiaba',
'Central Europe Standard Time': 'Europe/Budapest',
'Central European Standard Time': 'Europe/Warsaw',
'Central Pacific Standard Time': 'Pacific/Guadalcanal',
'Central Standard Time': 'America/Chicago',
'Central Standard Time (Mexico)': 'America/Mexico_City',
'Chatham Islands Standard Time': 'Pacific/Chatham',
'China Standard Time': 'Asia/Shanghai',
'Cuba Standard Time': 'America/Havana',
'Dateline Standard Time': 'Etc/GMT+12',
'E. Africa Standard Time': 'Africa/Nairobi',
'E. Australia Standard Time': 'Australia/Brisbane',
'E. Europe Standard Time': 'Europe/Chisinau',
'E. South America Standard Time': 'America/Sao_Paulo',
'Easter Island Standard Time': 'Pacific/Easter',
'Eastern Standard Time': 'America/New_York',
'Eastern Standard Time (Mexico)': 'America/Cancun',
'Egypt Standard Time': 'Africa/Cairo',
'Ekaterinburg Standard Time': 'Asia/Yekaterinburg',
'FLE Standard Time': 'Europe/Kiev',
'Fiji Standard Time': 'Pacific/Fiji',
'GMT Standard Time': 'Europe/London',
'GTB Standard Time': 'Europe/Bucharest',
'Georgian Standard Time': 'Asia/Tbilisi',
'Greenland Standard Time': 'America/Godthab',
'Greenwich Standard Time': 'Atlantic/Reykjavik',
'Haiti Standard Time': 'America/Port-au-Prince',
'Hawaiian Standard Time': 'Pacific/Honolulu',
'India Standard Time': 'Asia/Calcutta',
'Iran Standard Time': 'Asia/Tehran',
'Israel Standard Time': 'Asia/Jerusalem',
'Jordan Standard Time': 'Asia/Amman',
'Kaliningrad Standard Time': 'Europe/Kaliningrad',
'Korea Standard Time': 'Asia/Seoul',
'Libya Standard Time': 'Africa/Tripoli',
'Line Islands Standard Time': 'Pacific/Kiritimati',
'Lord Howe Standard Time': 'Australia/Lord_Howe',
'Magadan Standard Time': 'Asia/Magadan',
'Magallanes Standard Time': 'America/Punta_Arenas',
'Marquesas Standard Time': 'Pacific/Marquesas',
'Mauritius Standard Time': 'Indian/Mauritius',
'Middle East Standard Time': 'Asia/Beirut',
'Montevideo Standard Time': 'America/Montevideo',
'Morocco Standard Time': 'Africa/Casablanca',
'Mountain Standard Time': 'America/Denver',
'Mountain Standard Time (Mexico)': 'America/Chihuahua',
'Myanmar Standard Time': 'Asia/Rangoon',
'N. Central Asia Standard Time': 'Asia/Novosibirsk',
'Namibia Standard Time': 'Africa/Windhoek',
'Nepal Standard Time': 'Asia/Katmandu',
'New Zealand Standard Time': 'Pacific/Auckland',
'Newfoundland Standard Time': 'America/St_Johns',
'Norfolk Standard Time': 'Pacific/Norfolk',
'North Asia East Standard Time': 'Asia/Irkutsk',
'North Asia Standard Time': 'Asia/Krasnoyarsk',
'North Korea Standard Time': 'Asia/Pyongyang',
'Omsk Standard Time': 'Asia/Omsk',
'Pacific SA Standard Time': 'America/Santiago',
'Pacific Standard Time': 'America/Los_Angeles',
'Pacific Standard Time (Mexico)': 'America/Tijuana',
'Pakistan Standard Time': 'Asia/Karachi',
'Paraguay Standard Time': 'America/Asuncion',
'Romance Standard Time': 'Europe/Paris',
'Russia Time Zone 10': 'Asia/Srednekolymsk',
'Russia Time Zone 11': 'Asia/Kamchatka',
'Russia Time Zone 3': 'Europe/Samara',
'Russian Standard Time': 'Europe/Moscow',
'SA Eastern Standard Time': 'America/Cayenne',
'SA Pacific Standard Time': 'America/Bogota',
'SA Western Standard Time': 'America/La_Paz',
'SE Asia Standard Time': 'Asia/Bangkok',
'Saint Pierre Standard Time': 'America/Miquelon',
'Sakhalin Standard Time': 'Asia/Sakhalin',
'Samoa Standard Time': 'Pacific/Apia',
'Saratov Standard Time': 'Europe/Saratov',
'Singapore Standard Time': 'Asia/Singapore',
'South Africa Standard Time': 'Africa/Johannesburg',
'Sri Lanka Standard Time': 'Asia/Colombo',
'Syria Standard Time': 'Asia/Damascus',
'Taipei Standard Time': 'Asia/Taipei',
'Tasmania Standard Time': 'Australia/Hobart',
'Tocantins Standard Time': 'America/Araguaina',
'Tokyo Standard Time': 'Asia/Tokyo',
'Tomsk Standard Time': 'Asia/Tomsk',
'Tonga Standard Time': 'Pacific/Tongatapu',
'Transbaikal Standard Time': 'Asia/Chita',
'Turkey Standard Time': 'Europe/Istanbul',
'Turks And Caicos Standard Time': 'America/Grand_Turk',
'US Eastern Standard Time': 'America/Indianapolis',
'US Mountain Standard Time': 'America/Phoenix',
'UTC': 'Etc/GMT',
'UTC+12': 'Etc/GMT-12',
'UTC+13': 'Etc/GMT-13',
'UTC-02': 'Etc/GMT+2',
'UTC-08': 'Etc/GMT+8',
'UTC-09': 'Etc/GMT+9',
'UTC-11': 'Etc/GMT+11',
'Ulaanbaatar Standard Time': 'Asia/Ulaanbaatar',
'Venezuela Standard Time': 'America/Caracas',
'Vladivostok Standard Time': 'Asia/Vladivostok',
'W. Australia Standard Time': 'Australia/Perth',
'W. Central Africa Standard Time': 'Africa/Lagos',
'W. Europe Standard Time': 'Europe/Berlin',
'W. Mongolia Standard Time': 'Asia/Hovd',
'West Asia Standard Time': 'Asia/Tashkent',
'West Bank Standard Time': 'Asia/Hebron',
'West Pacific Standard Time': 'Pacific/Port_Moresby',
'Yakutsk Standard Time': 'Asia/Yakutsk'})
def __virtual__():
'''
Only load on windows
'''
if salt.utils.platform.is_windows() and salt.utils.path.which('tzutil'):
return __virtualname__
return (False, "Module win_timezone: tzutil not found or is not on Windows client")
if not __utils__['platform.is_windows']():
return False, "Module win_timezone: Not on Windows client"
if not HAS_PYTZ:
return False, "Module win_timezone: pytz not found"
if not __utils__['path.which']('tzutil'):
return False, "Module win_timezone: tzutil not found"
return __virtualname__
def get_zone():
'''
Get current timezone (i.e. America/Denver)
Returns:
str: Timezone in unix format
CLI Example:
.. code-block:: bash
salt '*' timezone.get_zone
'''
winzone = __salt__['cmd.run'](['tzutil', '/g'], python_shell=False)
for key in LINTOWIN:
if LINTOWIN[key] == winzone:
return key
return False
win_zone = __utils__['reg.read_value'](
hive='HKLM',
key='SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation',
vname='TimeZoneKeyName')['vdata']
return mapper.get_unix(win_zone.lower(), 'Unknown')
def get_offset():
'''
Get current numeric timezone offset from UCT (i.e. -0700)
Get current numeric timezone offset from UTC (i.e. -0700)
Returns:
str: Offset from UTC
CLI Example:
@ -494,52 +231,44 @@ def get_offset():
salt '*' timezone.get_offset
'''
string = False
zone = __salt__['cmd.run'](['tzutil', '/g'], python_shell=False)
prev = ''
zone_list = __salt__['cmd.run'](['tzutil', '/l'],
python_shell=False,
output_loglevel='trace').splitlines()
for line in zone_list:
if zone == line:
string = prev
break
else:
prev = line
if not string:
return False
reg = re.search(r"\(UTC(.\d\d:\d\d)\) .*", string, re.M)
if not reg:
ret = '0000'
else:
ret = reg.group(1).replace(':', '')
return ret
# http://craigglennie.com/programming/python/2013/07/21/working-with-timezones-using-Python-and-pytz-localize-vs-normalize/
tz_object = pytz.timezone(get_zone())
utc_time = pytz.utc.localize(datetime.utcnow())
loc_time = utc_time.astimezone(tz_object)
norm_time = tz_object.normalize(loc_time)
return norm_time.strftime('%z')
def get_zonecode():
'''
Get current timezone (i.e. PST, MDT, etc)
Returns:
str: An abbreviated timezone code
CLI Example:
.. code-block:: bash
salt '*' timezone.get_zonecode
'''
# Still not implemented on windows
return False
tz_object = pytz.timezone(get_zone())
loc_time = tz_object.localize(datetime.utcnow())
return loc_time.tzname()
def set_zone(timezone):
'''
Unlinks, then symlinks /etc/localtime to the set timezone.
Sets the timezone using the tzutil.
The timezone is crucial to several system processes, each of which SHOULD
be restarted (for instance, whatever you system uses as its cron and
syslog daemons). This will not be magically done for you!
Args:
timezone (str): A valid timezone
Returns:
bool: ``True`` if successful, otherwise ``False``
Raises:
CommandExecutionError: If invalid timezone is passed
CLI Example:
@ -547,15 +276,40 @@ def set_zone(timezone):
salt '*' timezone.set_zone 'America/Denver'
'''
cmd = ['tzutil', '/s', LINTOWIN[timezone]]
return __salt__['cmd.retcode'](cmd, python_shell=False) == 0
# if it's one of the key's just use it
if timezone.lower() in mapper.win_to_unix:
win_zone = timezone
elif timezone.lower() in mapper.unix_to_win:
# if it's one of the values, use the key
win_zone = mapper.get_win(timezone)
else:
# Raise error because it's neither key nor value
raise CommandExecutionError('Invalid timezone passed: {0}'.format(timezone))
# Set the value
cmd = ['tzutil', '/s', win_zone]
res = __salt__['cmd.run_all'](cmd, python_shell=False)
if res['retcode']:
raise CommandExecutionError('tzutil encountered an error setting '
'timezone: {0}'.format(timezone),
info=res)
return zone_compare(timezone)
def zone_compare(timezone):
'''
Checks the md5sum between the given timezone, and the one set in
/etc/localtime. Returns True if they match, and False if not. Mostly useful
for running state checks.
Compares the given timezone with the machine timezone. Mostly useful for
running state checks.
Args:
timezone (str):
The timezone to compare. This can be in Windows or Unix format. Can
be any of the values returned by the ``timezone.list`` function
Returns:
bool: ``True`` if they match, otherwise ``False``
Example:
@ -563,21 +317,68 @@ def zone_compare(timezone):
salt '*' timezone.zone_compare 'America/Denver'
'''
cmd = ['tzutil', '/g']
return __salt__['cmd.run'](cmd, python_shell=False) == LINTOWIN[timezone]
# if it's one of the key's just use it
if timezone.lower() in mapper.win_to_unix:
check_zone = timezone
elif timezone.lower() in mapper.unix_to_win:
# if it's one of the values, use the key
check_zone = mapper.get_win(timezone)
else:
# Raise error because it's neither key nor value
raise CommandExecutionError('Invalid timezone passed: {0}'
''.format(timezone))
return get_zone() == mapper.get_unix(check_zone, 'Unknown')
def list(unix_style=True):
'''
Return a list of Timezones that this module supports. These can be in either
Unix or Windows format.
.. version-added:: 2018.3.2
Args:
unix_style (bool):
``True`` returns Unix-style timezones. ``False`` returns
Windows-style timezones. Default is ``True``
Returns:
list: A list of supported timezones
CLI Example:
.. code-block:: bash
# Unix-style timezones
salt '*' timezone.list
# Windows-style timezones
salt '*' timezone.list unix_style=False
'''
if unix_style:
return mapper.list_unix()
else:
return mapper.list_win()
def get_hwclock():
'''
Get current hardware clock setting (UTC or localtime)
.. note::
The hardware clock is always local time on Windows so this will always
return "localtime"
CLI Example:
.. code-block:: bash
salt '*' timezone.get_hwclock
'''
# Need to search for a way to figure it out ...
# The hardware clock is always localtime on Windows
return 'localtime'
@ -585,11 +386,15 @@ def set_hwclock(clock):
'''
Sets the hardware clock to be either UTC or localtime
.. note::
The hardware clock is always local time on Windows so this will always
return ``False``
CLI Example:
.. code-block:: bash
salt '*' timezone.set_hwclock UTC
'''
# Need to search for a way to figure it out ...
# The hardware clock is always localtime on Windows
return False

View File

@ -1,6 +1,17 @@
# -*- coding: utf-8 -*-
'''
A convenience system to manage reactors
Beginning in the 2017.7 release, the reactor runner requires that the reactor
system is running. This is accomplished one of two ways, either
by having reactors configured or by including ``reactor`` in the
engine configuration for the Salt master.
.. code-block:: yaml
engines:
- reactor
'''
# Import python libs
from __future__ import absolute_import, print_function, unicode_literals

View File

@ -551,6 +551,9 @@ def function(
m_ret = mdata['ret']
m_func = (not fail_function and True) or __salt__[fail_function](m_ret)
if m_ret is False:
m_func = False
if not m_func:
if minion not in fail_minions:
fail.add(minion)

View File

@ -467,7 +467,7 @@ def query(params=None, setname=None, requesturl=None, location=None,
log.debug('AWS Response Status Code: %s', result.status_code)
log.trace(
'AWS Response Text: %s',
result.text.encode(result.encoding if result.encoding else 'utf-8')
result.text
)
result.raise_for_status()
break
@ -503,11 +503,7 @@ def query(params=None, setname=None, requesturl=None, location=None,
return {'error': data}, requesturl
return {'error': data}
response = result.text.encode(
result.encoding if result.encoding else 'utf-8'
)
root = ET.fromstring(response)
root = ET.fromstring(result.text)
items = root[1]
if return_root is True:
items = root

View File

@ -124,6 +124,18 @@ def _run_all(cmd):
return ret
def _check_launchctl_stderr(ret):
'''
helper class to check the launchctl stderr.
launchctl does not always return bad exit code
if there is a failure
'''
err = ret['stderr'].lower()
if 'service is disabled' in err:
return True
return False
def execute_return_success(cmd):
'''
Executes the passed command. Returns True if successful
@ -279,9 +291,10 @@ def launchctl(sub_cmd, *args, **kwargs):
kwargs['python_shell'] = False
kwargs = salt.utils.args.clean_kwargs(**kwargs)
ret = __salt__['cmd.run_all'](cmd, **kwargs)
error = _check_launchctl_stderr(ret)
# Raise an error or return successful result
if ret['retcode']:
if ret['retcode'] or error:
out = 'Failed to {0} service:\n'.format(sub_cmd)
out += 'stdout: {0}\n'.format(ret['stdout'])
out += 'stderr: {0}\n'.format(ret['stderr'])

View File

@ -1124,6 +1124,7 @@ class SaltDistribution(distutils.dist.Distribution):
'wmi',
'site',
'psutil',
'pytz',
])
elif IS_SMARTOS_PLATFORM:
# we have them as requirements in pkg/smartos/esky/requirements.txt

View File

@ -24,7 +24,7 @@ from tests.support import win_installer
INSTANCE_NAME = generate_random_name('CLOUD-TEST-')
PROVIDER_NAME = 'ec2'
HAS_WINRM = salt.utils.cloud.HAS_WINRM and salt.utils.cloud.HAS_SMB
TIMEOUT = 1000
TIMEOUT = 1200
class EC2Test(ShellCase):

View File

@ -1,12 +1,12 @@
ec2-test:
provider: ec2-config
image: ami-98aa1cf0
size: m1.small
size: m1.large
sh_username: ec2-user
script_args: '-P -Z'
ec2-win2012r2-test:
provider: ec2-config
size: m1.small
size: m1.large
image: ami-eb1ecd96
smb_port: 445
win_installer: ''
@ -19,7 +19,7 @@ ec2-win2012r2-test:
deploy: True
ec2-win2016-test:
provider: ec2-config
size: m1.small
size: m1.large
image: ami-ed14c790
smb_port: 445
win_installer: ''

View File

@ -0,0 +1,4 @@
deploy_check:
salt.function:
- name: test.false
- tgt: minion

View File

@ -0,0 +1,24 @@
{% set versions = {'18':['05', '03', '01'], '16':['04', '03', '02', '00'], '9':['20']} %}
Zzip:
{% for major, subversions in versions.items() %}
{% for minor in subversions %}
'{{major}}.{{minor}}.00.0':
{% if grains['cpuarch'] == 'AMD64' %}
full_name: '7-Zip {{major}}.{{minor}} (x64 edition)'
installer: 'http://d.7-zip.org/a/7z{{major}}{{minor}}-x64.msi'
uninstaller: 'http://d.7-zip.org/a/7z{{major}}{{minor}}-x64.msi'
arch: x64
{% else %}
full_name: '7-Zip {{major}}.{{minor}}'
installer: 'http://d.7-zip.org/a/7z{{major}}{{minor}}.msi'
uninstaller: 'http://d.7-zip.org/a/7z{{major}}{{minor}}.msi'
arch: x86
{% endif %}
install_flags: '/qn /norestart'
uninstall_flags: '/qn /norestart'
msiexec: True
locale: en_US
reboot: False
{% endfor %}
{% endfor %}

View File

@ -12,7 +12,8 @@ from tests.support.case import ModuleCase
from tests.support.helpers import (
destructiveTest,
skip_if_binaries_missing,
skip_if_not_root
skip_if_not_root,
this_user,
)
from tests.support.paths import TMP
from tests.support.unit import skipIf
@ -280,12 +281,7 @@ class CMDModuleTest(ModuleCase):
cmd = '''echo 'SELECT * FROM foo WHERE bar="baz"' '''
expected_result = 'SELECT * FROM foo WHERE bar="baz"'
try:
runas = os.getlogin()
except: # pylint: disable=W0702
# On some distros (notably Gentoo) os.getlogin() fails
import pwd
runas = pwd.getpwuid(os.getuid())[0]
runas = this_user()
result = self.run_function('cmd.run_stdout', [cmd],
runas=runas).strip()

View File

@ -40,8 +40,10 @@ class MacServiceModuleTest(ModuleCase):
'''
if self.SERVICE_ENABLED:
self.run_function('service.start', [self.SERVICE_NAME])
self.run_function('service.enable', [self.SERVICE_NAME])
else:
self.run_function('service.stop', [self.SERVICE_NAME])
self.run_function('service.disable', [self.SERVICE_NAME])
def test_show(self):
'''

View File

@ -198,7 +198,18 @@ class SaltUtilSyncPillarTest(ModuleCase):
'''))
self.run_function('saltutil.refresh_pillar')
self.run_function('test.sleep', [5])
pillar = False
timeout = time.time() + 30
while not pillar:
post_pillar = self.run_function('pillar.raw')
try:
self.assertIn(pillar_key, post_pillar.get(pillar_key, 'didnotwork'))
pillar = True
except AssertionError:
if time.time() > timeout:
self.assertIn(pillar_key, post_pillar.get(pillar_key, 'didnotwork'))
continue
post_pillar = self.run_function('pillar.raw')
self.assertIn(pillar_key, post_pillar.get(pillar_key, 'didnotwork'))

View File

@ -120,7 +120,7 @@ class ServiceModuleTest(ModuleCase):
systemd = salt.utils.systemd.booted()
# check service was not enabled
if systemd:
if systemd or salt.utils.platform.is_windows():
self.assertIn('ERROR', enable)
else:
self.assertFalse(enable)

View File

@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
# Import Python libs
from __future__ import absolute_import
# Import Salt Testing libs
from tests.support.case import ModuleCase
from tests.support.unit import skipIf
from tests.support.helpers import destructiveTest
# Import Salt libs
import salt.utils.platform
@skipIf(not salt.utils.platform.is_windows(), 'windows test only')
class WinDNSTest(ModuleCase):
'''
Test for salt.modules.win_dns_client
'''
@destructiveTest
def test_add_remove_dns(self):
'''
Test add and removing a dns server
'''
dns = '8.8.8.8'
interface = 'Ethernet'
# add dns server
self.assertTrue(self.run_function('win_dns_client.add_dns', [dns, interface], index=42))
srvs = self.run_function('win_dns_client.get_dns_servers', interface=interface)
self.assertIn(dns, srvs)
# remove dns server
self.assertTrue(self.run_function('win_dns_client.rm_dns', [dns], interface=interface))
srvs = self.run_function('win_dns_client.get_dns_servers', interface=interface)
self.assertNotIn(dns, srvs)

View File

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# Import Python libs
from __future__ import absolute_import
# Import Salt Testing libs
from tests.support.case import ModuleCase
from tests.support.unit import skipIf
# Import Salt libs
import salt.utils.platform
@skipIf(not salt.utils.platform.is_windows(), 'windows test only')
class WinServermanagerTest(ModuleCase):
'''
Test for salt.modules.win_servermanager
'''
def test_list_available(self):
'''
Test list available features to install
'''
cmd = self.run_function('win_servermanager.list_available')
self.assertIn('DNS', cmd)
self.assertIn('NetworkController', cmd)
self.assertIn('RemoteAccess', cmd)

View File

@ -257,6 +257,33 @@ class StateRunnerTest(ShellCase):
self.assertEqual(count('Succeeded: 1', ret), 1)
self.assertEqual(count('Failed: 0', ret), 1)
def test_orchestrate_salt_function_return_false_failure(self):
'''
Ensure that functions that only return False in the return
are flagged as failed when run as orchestrations.
See https://github.com/saltstack/salt/issues/30367
'''
self.run_run('saltutil.sync_modules')
ret = salt.utils.json.loads(
'\n'.join(
self.run_run('state.orchestrate orch.issue30367 --out=json')
)
)
# Drill down to the changes dict
state_result = ret['data']['master']['salt_|-deploy_check_|-test.false_|-function']['result']
func_ret = ret['data']['master']['salt_|-deploy_check_|-test.false_|-function']['changes']
self.assertEqual(
state_result,
False,
)
self.assertEqual(
func_ret,
{'out': 'highstate', 'ret': {'minion': False}}
)
@skipIf(salt.utils.platform.is_windows(), '*NIX-only test')
class OrchEventTest(ShellCase):

View File

@ -408,7 +408,7 @@ class CallTest(ShellCase, testprogram.TestProgramCase, ShellCaseCommonTestsMixin
with salt.utils.files.set_umask(0o077):
try:
# Let's create an initial output file with some data
self.run_script(
stdout, stderr, retcode = self.run_script(
'salt-call',
'-c {0} --output-file={1} -g'.format(
self.get_config_dir(),
@ -417,7 +417,20 @@ class CallTest(ShellCase, testprogram.TestProgramCase, ShellCaseCommonTestsMixin
catch_stderr=True,
with_retcode=True
)
stat1 = os.stat(output_file)
try:
stat1 = os.stat(output_file)
except OSError:
log.error(
'run_script failed to generate output file:\n'
'return code %d\n'
'stdout:\n'
'%s\n\n'
'stderr\n'
'%s',
retcode, stdout, stderr
)
self.fail(
'Failed to generate output file, see log for details')
# Let's change umask
os.umask(0o777) # pylint: disable=blacklisted-function

View File

@ -40,7 +40,7 @@ _PKG_TARGETS = {
'FreeBSD': ['aalib', 'pth'],
'Suse': ['aalib', 'rpm-python'],
'MacOS': ['libpng', 'jpeg'],
'Windows': ['firefox', '7zip'],
'Windows': ['putty', '7zip'],
}
_PKG_CAP_TARGETS = {
@ -167,7 +167,6 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin):
self.run_function('pkg.refresh_db')
__testcontext__['refresh'] = True
@skipIf(salt.utils.platform.is_windows(), 'minion is windows')
@requires_system_grains
def test_pkg_001_installed(self, grains=None):
'''
@ -198,7 +197,6 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin):
ret = self.run_state('pkg.removed', name=target)
self.assertSaltTrueReturn(ret)
@skipIf(salt.utils.platform.is_windows(), 'minion is windows')
@requires_system_grains
def test_pkg_002_installed_with_version(self, grains=None):
'''
@ -246,7 +244,6 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin):
ret = self.run_state('pkg.removed', name=target)
self.assertSaltTrueReturn(ret)
@skipIf(salt.utils.platform.is_windows(), 'minion is windows')
@requires_system_grains
def test_pkg_003_installed_multipkg(self, grains=None):
'''
@ -268,7 +265,10 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin):
# If this assert fails, we need to find new targets, this test needs to
# be able to test successful installation of packages, so these
# packages need to not be installed before we run the states below
self.assertFalse(any(version.values()))
try:
self.assertFalse(any(version.values()))
except AssertionError:
self.assertSaltTrueReturn(self.run_state('pkg.removed', name=None, pkgs=pkg_targets))
ret = self.run_state('pkg.installed',
name=None,
@ -278,7 +278,6 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin):
ret = self.run_state('pkg.removed', name=None, pkgs=pkg_targets)
self.assertSaltTrueReturn(ret)
@skipIf(salt.utils.platform.is_windows(), 'minion is windows')
@requires_system_grains
def test_pkg_004_installed_multipkg_with_version(self, grains=None):
'''
@ -327,7 +326,6 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin):
ret = self.run_state('pkg.removed', name=None, pkgs=pkg_targets)
self.assertSaltTrueReturn(ret)
@skipIf(salt.utils.platform.is_windows(), 'minion is windows')
@requires_system_grains
def test_pkg_005_installed_32bit(self, grains=None):
'''
@ -364,7 +362,6 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin):
ret = self.run_state('pkg.removed', name=target)
self.assertSaltTrueReturn(ret)
@skipIf(salt.utils.platform.is_windows(), 'minion is windows')
@requires_system_grains
def test_pkg_006_installed_32bit_with_version(self, grains=None):
'''
@ -412,7 +409,6 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin):
ret = self.run_state('pkg.removed', name=target)
self.assertSaltTrueReturn(ret)
@skipIf(salt.utils.platform.is_windows(), 'minion is windows')
@requires_system_grains
def test_pkg_007_with_dot_in_pkgname(self, grains=None):
'''
@ -443,7 +439,6 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin):
ret = self.run_state('pkg.removed', name=target)
self.assertSaltTrueReturn(ret)
@skipIf(salt.utils.platform.is_windows(), 'minion is windows')
@requires_system_grains
def test_pkg_008_epoch_in_version(self, grains=None):
'''
@ -494,7 +489,6 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin):
refresh=False)
self.assertSaltTrueReturn(ret)
@skipIf(salt.utils.platform.is_windows(), 'minion is windows')
@requires_salt_modules('pkg.info_installed')
def test_pkg_010_latest_with_epoch_and_info_installed(self):
'''
@ -514,7 +508,6 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin):
ret = self.run_function('pkg.info_installed', [package])
self.assertTrue(pkgquery in six.text_type(ret))
@skipIf(salt.utils.platform.is_windows(), 'minion is windows')
@requires_system_grains
def test_pkg_011_latest(self, grains=None):
'''
@ -546,7 +539,6 @@ class PkgTest(ModuleCase, SaltReturnAssertsMixin):
ret = self.run_state('pkg.removed', name=target)
self.assertSaltTrueReturn(ret)
@skipIf(salt.utils.platform.is_windows(), 'minion is windows')
@requires_system_grains
def test_pkg_012_latest_only_upgrade(self, grains=None):
'''

View File

@ -13,6 +13,7 @@ from tests.support.mixins import SaltReturnAssertsMixin
# Import salt libs
import salt.utils.path
import salt.utils.platform
INIT_DELAY = 5
@ -62,10 +63,15 @@ class ServiceTest(ModuleCase, SaltReturnAssertsMixin):
'''
test service.running state module
'''
stop_service = self.run_function('service.stop', self.service_name)
self.assertTrue(stop_service)
if self.run_function('service.status', name=self.service_name):
stop_service = self.run_function('service.stop', name=self.service_name)
self.assertTrue(stop_service)
self.check_service_status(self.stopped)
if salt.utils.platform.is_darwin():
# make sure the service is enabled on macosx
enable = self.run_function('service.enable', name=self.service_name)
start_service = self.run_state('service.running',
name=self.service_name)
self.assertTrue(start_service)

View File

@ -98,10 +98,15 @@ class ShellTestCase(TestCase, AdaptedConfigurationTestCaseMixin):
script_name
)
)
sfh.write(
contents = (
'#!{0}\n'.format(sys.executable) +
'\n'.join(script_template).format(script_name.replace('salt-', ''))
)
sfh.write(contents)
log.debug(
'Wrote the following contents to temp script %s:\n%s',
script_path, contents
)
st = os.stat(script_path)
os.chmod(script_path, st.st_mode | stat.S_IEXEC)

View File

@ -59,8 +59,12 @@ from tests.support.paths import FILES, TMP
import salt.utils.files
import salt.utils.platform
log = logging.getLogger(__name__)
if salt.utils.platform.is_windows():
import salt.utils.win_functions
else:
import pwd
log = logging.getLogger(__name__)
HAS_SYMLINKS = None
@ -1159,7 +1163,6 @@ def skip_if_not_root(func):
func.__unittest_skip__ = True
func.__unittest_skip_why__ = 'You must be logged in as root to run this test'
else:
import salt.utils.win_functions
current_user = salt.utils.win_functions.get_current_user()
if current_user != 'SYSTEM':
if not salt.utils.win_functions.is_admin(current_user):
@ -1592,3 +1595,12 @@ def win32_kill_process_tree(pid, sig=signal.SIGTERM, include_parent=True,
gone, alive = psutil.wait_procs(children, timeout=timeout,
callback=on_terminate)
return (gone, alive)
def this_user():
'''
Get the user associated with the current process.
'''
if salt.utils.platform.is_windows():
return salt.utils.win_functions.get_current_user()
return pwd.getpwuid(os.getuid())[0]

View File

@ -49,7 +49,6 @@
# Import Python modules
from __future__ import absolute_import, print_function
import os
import sys
import shutil
import logging
import multiprocessing
@ -58,6 +57,7 @@ import salt.utils.json
# Import tests support libs
import tests.support.paths as paths
import tests.support.helpers
# Import 3rd-party libs
from salt.ext import six
@ -104,12 +104,9 @@ try:
except ImportError:
pass
if sys.platform.startswith('win'):
import win32api # pylint: disable=import-error
RUNNING_TESTS_USER = win32api.GetUserName()
else:
import pwd
RUNNING_TESTS_USER = pwd.getpwuid(os.getuid()).pw_name
RUNNING_TESTS_USER = tests.support.helpers.this_user()
log = logging.getLogger(__name__)

View File

@ -54,7 +54,8 @@ def latest_version(repo=REPO):
'''
Return the latest version found on the salt repository webpage.
'''
for name, md5 in iter_installers(requests.get(repo).content):
content = requests.get(repo).content.decode('utf-8')
for name, md5 in iter_installers(content):
pass
return split_installer(name)[0]

View File

@ -15,7 +15,7 @@ import tornado.ioloop
import logging
import stat
try:
import pwd
import pwd # pylint: disable=unused-import
except ImportError:
pass

View File

@ -0,0 +1,3 @@
Oracle Solaris 11.3 SPARC
Copyright (c) 1983, 2017, Oracle and/or its affiliates. All rights reserved.
Assembled 05 October 2017

View File

@ -0,0 +1,24 @@
System Configuration: Oracle Corporation sun4v
Memory size: 16384 Megabytes
System Peripherals (PROM Nodes):
Node 0xfffffffff
scsi-initiator-id: 00000007
idprom: 00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000
pcie-ari-supported:
#priqs-per-pcibus: 00000010
#priqs-per-cpu: 00000010
priq-eq-sizes: 00000003
non-ios-perf-counters: 'ORCL,sn-non-ios-pr'
ios-perf-counters: 'ORCL,sn-ios-pr'
storage-variant: '8dbp'
product-name: 'SPARC S7-2'
banner-name: 'SPARC S7-2'
name: 'ORCL,SPARC-S7-2'
stick-frequency: 3b9aca00
hv-api-groups: 00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.000000060.00000000.00000000
breakpoint-trap: 0000007f
device_type: 'sun4v'
compatible: 'sun4v'
#address-cells: 00000002
#size-cells: 00000002

View File

@ -0,0 +1,16 @@
System Configuration: Oracle Corporation sun4v
Memory size: 8192 Megabytes
System Peripherals (PROM Nodes):
Node 0xffffffff
idprom: 11111111.11111111.00000000.11111111.00000000.00000000.00000000.00000000
scsi-initiator-id: 00000007
banner-name: 'SPARC Enterprise T5220'
name: 'SUNW,SPARC-Enterprise-T5220'
stick-frequency: 5458c3a0
hv-api-groups: 00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000
breakpoint-trap: 0000007f
device_type: 'sun4v'
compatible: 'sun4v'
#address-cells: 00000002
#size-cells: 00000002

View File

@ -0,0 +1,24 @@
System Configuration: Oracle Corporation sun4v SPARC S7-2
Memory size: 16384 Megabytes
================================ Virtual CPUs ================================
CPU ID Frequency Implementation Status
------ --------- ---------------------- -------
0 4267 MHz SPARC-S7 on-line
1 4267 MHz SPARC-S7 on-line
2 4267 MHz SPARC-S7 on-line
3 4267 MHz SPARC-S7 on-line
4 4267 MHz SPARC-S7 on-line
5 4267 MHz SPARC-S7 on-line
6 4267 MHz SPARC-S7 on-line
7 4267 MHz SPARC-S7 on-line
8 4267 MHz SPARC-S7 on-line
9 4267 MHz SPARC-S7 on-line
10 4267 MHz SPARC-S7 on-line
11 4267 MHz SPARC-S7 on-line
12 4267 MHz SPARC-S7 on-line
13 4267 MHz SPARC-S7 on-line
14 4267 MHz SPARC-S7 on-line
15 4267 MHz SPARC-S7 on-line

View File

@ -0,0 +1,16 @@
System Configuration: Oracle Corporation sun4v SPARC Enterprise T5220
Memory size: 8192 Megabytes
================================ Virtual CPUs ================================
CPU ID Frequency Implementation Status
------ --------- ---------------------- -------
0 1415 MHz SUNW,UltraSPARC-T2 on-line
1 1415 MHz SUNW,UltraSPARC-T2 on-line
2 1415 MHz SUNW,UltraSPARC-T2 on-line
3 1415 MHz SUNW,UltraSPARC-T2 on-line
4 1415 MHz SUNW,UltraSPARC-T2 on-line
5 1415 MHz SUNW,UltraSPARC-T2 on-line
6 1415 MHz SUNW,UltraSPARC-T2 on-line
7 1415 MHz SUNW,UltraSPARC-T2 on-line

View File

@ -30,6 +30,7 @@ import salt.utils.dns
import salt.utils.files
import salt.utils.network
import salt.utils.platform
import salt.utils.path
import salt.grains.core as core
# Import 3rd-party libs
@ -52,6 +53,7 @@ IP6_ADD1 = '2001:4860:4860::8844'
IP6_ADD2 = '2001:4860:4860::8888'
IP6_ADD_SCOPE = 'fe80::6238:e0ff:fe06:3f6b%enp2s0'
OS_RELEASE_DIR = os.path.join(os.path.dirname(__file__), "os-releases")
SOLARIS_DIR = os.path.join(os.path.dirname(__file__), 'solaris')
@skipIf(NO_MOCK, NO_MOCK_REASON)
@ -901,3 +903,98 @@ SwapTotal: 4789244 kB'''
osdata = {'kernel': 'test', }
ret = core._virtual(osdata)
self.assertEqual(ret['virtual'], virt)
def test_solaris_sparc_s7zone(self):
'''
verify productname grain for s7 zone
'''
expectation = {
'productname': 'SPARC S7-2',
'product': 'SPARC S7-2',
}
with salt.utils.files.fopen(os.path.join(SOLARIS_DIR, 'prtconf.s7-zone')) as sparc_return_data:
this_sparc_return_data = '\n'.join(sparc_return_data.readlines())
this_sparc_return_data += '\n'
self._check_solaris_sparc_productname_grains(this_sparc_return_data, expectation)
def test_solaris_sparc_s7(self):
'''
verify productname grain for s7
'''
expectation = {
'productname': 'SPARC S7-2',
'product': 'SPARC S7-2',
}
with salt.utils.files.fopen(os.path.join(SOLARIS_DIR, 'prtdiag.s7')) as sparc_return_data:
this_sparc_return_data = '\n'.join(sparc_return_data.readlines())
this_sparc_return_data += '\n'
self._check_solaris_sparc_productname_grains(this_sparc_return_data, expectation)
def test_solaris_sparc_t5220(self):
'''
verify productname grain for t5220
'''
expectation = {
'productname': 'SPARC Enterprise T5220',
'product': 'SPARC Enterprise T5220',
}
with salt.utils.files.fopen(os.path.join(SOLARIS_DIR, 'prtdiag.t5220')) as sparc_return_data:
this_sparc_return_data = '\n'.join(sparc_return_data.readlines())
this_sparc_return_data += '\n'
self._check_solaris_sparc_productname_grains(this_sparc_return_data, expectation)
def test_solaris_sparc_t5220zone(self):
'''
verify productname grain for t5220 zone
'''
expectation = {
'productname': 'SPARC Enterprise T5220',
'product': 'SPARC Enterprise T5220',
}
with salt.utils.files.fopen(os.path.join(SOLARIS_DIR, 'prtconf.t5220-zone')) as sparc_return_data:
this_sparc_return_data = '\n'.join(sparc_return_data.readlines())
this_sparc_return_data += '\n'
self._check_solaris_sparc_productname_grains(this_sparc_return_data, expectation)
def _check_solaris_sparc_productname_grains(self, prtdata, expectation):
'''
verify product grains on solaris sparc
'''
import platform
path_isfile_mock = MagicMock(side_effect=lambda x: x in ['/etc/release'])
with patch.object(platform, 'uname',
MagicMock(return_value=('SunOS', 'testsystem', '5.11', '11.3', 'sunv4', 'sparc'))):
with patch.object(salt.utils.platform, 'is_proxy',
MagicMock(return_value=False)):
with patch.object(salt.utils.platform, 'is_linux',
MagicMock(return_value=False)):
with patch.object(salt.utils.platform, 'is_windows',
MagicMock(return_value=False)):
with patch.object(salt.utils.platform, 'is_smartos',
MagicMock(return_value=False)):
with patch.object(salt.utils.path, 'which_bin',
MagicMock(return_value=None)):
with patch.object(os.path, 'isfile', path_isfile_mock):
with salt.utils.files.fopen(os.path.join(OS_RELEASE_DIR, "solaris-11.3")) as os_release_file:
os_release_content = os_release_file.readlines()
with patch("salt.utils.files.fopen", mock_open()) as os_release_file:
os_release_file.return_value.__iter__.return_value = os_release_content
with patch.object(core, '_sunos_cpudata',
MagicMock(return_value={'cpuarch': 'sparcv9',
'num_cpus': '1',
'cpu_model': 'MOCK_CPU_MODEL',
'cpu_flags': []})):
with patch.object(core, '_memdata',
MagicMock(return_value={'mem_total': 16384})):
with patch.object(core, '_virtual',
MagicMock(return_value={})):
with patch.object(core, '_ps',
MagicMock(return_value={})):
with patch.object(salt.utils.path, 'which',
MagicMock(return_value=True)):
sparc_return_mock = MagicMock(return_value=prtdata)
with patch.dict(core.__salt__, {'cmd.run': sparc_return_mock}):
os_grains = core.os_data()
grains = {k: v for k, v in os_grains.items()
if k in set(['product', 'productname'])}
self.assertEqual(grains, expectation)

View File

@ -11,6 +11,7 @@ from __future__ import absolute_import, unicode_literals, print_function
# Import Salt Libs
import salt.modules.win_snmp as win_snmp
from salt.exceptions import CommandExecutionError
# Import Salt Testing Libs
from tests.support.mixins import LoaderModuleMockMixin
@ -70,19 +71,47 @@ class WinSnmpTestCase(TestCase, LoaderModuleMockMixin):
'''
Test - Get the current accepted SNMP community names and their permissions.
'''
mock_value = MagicMock(return_value=[{'vdata': 16,
'vname': 'TestCommunity'}])
with patch.dict(win_snmp.__salt__, {'reg.list_values': mock_value}):
mock_ret = MagicMock(return_value=[{'vdata': 16,
'vname': 'TestCommunity'}])
mock_false = MagicMock(return_value=False)
with patch.dict(win_snmp.__salt__, {'reg.list_values': mock_ret,
'reg.key_exists': mock_false}):
self.assertEqual(win_snmp.get_community_names(),
COMMUNITY_NAMES)
def test_get_community_names_gpo(self):
'''
Test - Get the current accepted SNMP community names and their permissions.
'''
mock_ret = MagicMock(return_value=[{'vdata': 'TestCommunity',
'vname': 1}])
mock_false = MagicMock(return_value=True)
with patch.dict(win_snmp.__salt__, {'reg.list_values': mock_ret,
'reg.key_exists': mock_false}):
self.assertEqual(win_snmp.get_community_names(),
{'TestCommunity': 'Managed by GPO'})
def test_set_community_names(self):
'''
Test - Manage the SNMP accepted community names and their permissions.
'''
mock_value = MagicMock(return_value=True)
mock_true = MagicMock(return_value=True)
kwargs = {'communities': COMMUNITY_NAMES}
with patch.dict(win_snmp.__salt__, {'reg.set_value': mock_value}), \
mock_false = MagicMock(return_value=False)
with patch.dict(win_snmp.__salt__, {'reg.set_value': mock_true,
'reg.key_exists': mock_false}), \
patch('salt.modules.win_snmp.get_community_names',
MagicMock(return_value=COMMUNITY_NAMES)):
self.assertTrue(win_snmp.set_community_names(**kwargs))
def test_set_community_names_gpo(self):
'''
Test - Manage the SNMP accepted community names and their permissions.
'''
mock_true = MagicMock(return_value=True)
kwargs = {'communities': COMMUNITY_NAMES}
with patch.dict(win_snmp.__salt__, {'reg.set_value': mock_true,
'reg.key_exists': mock_true}), \
patch('salt.modules.win_snmp.get_community_names',
MagicMock(return_value=COMMUNITY_NAMES)):
self.assertRaises(CommandExecutionError, win_snmp.set_community_names, **kwargs)

View File

@ -2,13 +2,12 @@
'''
:codeauthor: :email:`Jayesh Kariya <jayeshk@saltstack.com>`
'''
# Import Python Libs
from __future__ import absolute_import, unicode_literals, print_function
# Import Salt Testing Libs
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.unit import TestCase
from tests.support.unit import TestCase, skipIf
from tests.support.mock import (
MagicMock,
patch
@ -18,6 +17,7 @@ from tests.support.mock import (
import salt.modules.win_timezone as win_timezone
@skipIf(not win_timezone.HAS_PYTZ, 'This test requires pytz')
class WinTimezoneTestCase(TestCase, LoaderModuleMockMixin):
'''
Test cases for salt.modules.win_timezone
@ -31,12 +31,13 @@ class WinTimezoneTestCase(TestCase, LoaderModuleMockMixin):
'''
Test if it get current timezone (i.e. Asia/Calcutta)
'''
mock_cmd = MagicMock(side_effect=['India Standard Time',
'Indian Standard Time'])
with patch.dict(win_timezone.__salt__, {'cmd.run': mock_cmd}):
mock_read = MagicMock(side_effect=[{'vdata': 'India Standard Time'},
{'vdata': 'Indian Standard Time'}])
with patch.dict(win_timezone.__utils__, {'reg.read_value': mock_read}):
self.assertEqual(win_timezone.get_zone(), 'Asia/Calcutta')
self.assertFalse(win_timezone.get_zone())
self.assertEqual(win_timezone.get_zone(), 'Unknown')
# 'get_offset' function tests: 1
@ -44,15 +45,15 @@ class WinTimezoneTestCase(TestCase, LoaderModuleMockMixin):
'''
Test if it get current numeric timezone offset from UCT (i.e. +0530)
'''
time = ('(UTC+05:30) Chennai, Kolkata, Mumbai, \
New Delhi\nIndia Standard Time')
mock_cmd = MagicMock(side_effect=['India Standard Time', time])
with patch.dict(win_timezone.__salt__, {'cmd.run': mock_cmd}):
self.assertEqual(win_timezone.get_offset(), '+0530')
# time = ('(UTC+05:30) Chennai, Kolkata, Mumbai, \
# New Delhi\nIndia Standard Time')
# mock_cmd = MagicMock(side_effect=['India Standard Time', time])
# with patch.dict(win_timezone.__salt__, {'cmd.run': mock_cmd}):
mock_cmd = MagicMock(return_value='India Standard Time')
with patch.dict(win_timezone.__salt__, {'cmd.run': mock_cmd}):
self.assertFalse(win_timezone.get_offset())
mock_read = MagicMock(return_value={'vdata': 'India Standard Time'})
with patch.dict(win_timezone.__utils__, {'reg.read_value': mock_read}):
self.assertEqual(win_timezone.get_offset(), '+0530')
# 'get_zonecode' function tests: 1
@ -60,7 +61,10 @@ class WinTimezoneTestCase(TestCase, LoaderModuleMockMixin):
'''
Test if it get current timezone (i.e. PST, MDT, etc)
'''
self.assertFalse(win_timezone.get_zonecode())
mock_read = MagicMock(return_value={'vdata': 'India Standard Time'})
with patch.dict(win_timezone.__utils__, {'reg.read_value': mock_read}):
self.assertEqual(win_timezone.get_zonecode(), 'IST')
# 'set_zone' function tests: 1
@ -68,8 +72,15 @@ class WinTimezoneTestCase(TestCase, LoaderModuleMockMixin):
'''
Test if it unlinks, then symlinks /etc/localtime to the set timezone.
'''
mock_cmd = MagicMock(return_value=0)
with patch.dict(win_timezone.__salt__, {'cmd.retcode': mock_cmd}):
mock_cmd = MagicMock(return_value={'pid': 78,
'retcode': 0,
'stderr': '',
'stdout': ''})
mock_read = MagicMock(return_value={'vdata': 'India Standard Time'})
with patch.dict(win_timezone.__salt__, {'cmd.run_all': mock_cmd}), \
patch.dict(win_timezone.__utils__, {'reg.read_value': mock_read}):
self.assertTrue(win_timezone.set_zone('Asia/Calcutta'))
# 'zone_compare' function tests: 1
@ -80,8 +91,9 @@ class WinTimezoneTestCase(TestCase, LoaderModuleMockMixin):
the one set in /etc/localtime. Returns True if they match,
and False if not. Mostly useful for running state checks.
'''
mock_cmd = MagicMock(return_value='India Standard Time')
with patch.dict(win_timezone.__salt__, {'cmd.run': mock_cmd}):
mock_read = MagicMock(return_value={'vdata': 'India Standard Time'})
with patch.dict(win_timezone.__utils__, {'reg.read_value': mock_read}):
self.assertTrue(win_timezone.zone_compare('Asia/Calcutta'))
# 'get_hwclock' function tests: 1

View File

@ -29,6 +29,7 @@ integration.modules.test_sysmod
integration.modules.test_system
integration.modules.test_test
integration.modules.test_useradd
integration.modules.test_win_dns_client
integration.reactor.test_reactor
integration.renderers.test_pydsl
integration.returners.test_librato_return
@ -38,6 +39,7 @@ integration.runners.test_salt
integration.sdb.test_env
integration.states.test_host
integration.states.test_pip_state
integration.states.test_pkg
integration.states.test_reg
integration.states.test_renderers
integration.utils.testprogram