Merge pull request #28155 from basepi/merge-forward-2015.8

[2015.8] Merge forward from 2015.5 to 2015.8
This commit is contained in:
Colton Myers 2015-10-20 17:48:41 -06:00
commit 053ad408c7
15 changed files with 218 additions and 105 deletions

View File

@ -402,7 +402,8 @@
# Set the file client. The client defaults to looking on the master server for
# files, but can be directed to look at the local file directory setting
# defined below by setting it to local.
# defined below by setting it to "local". Setting a local file_client runs the
# minion in masterless mode.
#file_client: remote
# The file directory works on environments passed to the minion, each environment

View File

@ -164,7 +164,7 @@ project = 'Salt'
copyright = '2015 SaltStack, Inc.'
version = salt.version.__version__
latest_release = '2015.8.1' # latest release
latest_release = '2015.8.1' # latest release
previous_release = '2015.5.6' # latest release from previous branch
previous_release_dir = '2015.5' # path on web server for previous branch
build_type = 'latest' # latest, previous, develop, inactive

View File

@ -307,7 +307,7 @@ https://github.com/saltstack-formulas/salt-formula
.. _faq-grain-security:
Is Targeting using Grain Data Secure?
=====================================
-------------------------------------
Because grains can be set by users that have access to the minion configuration
files on the local system, grains are considered less secure than other

View File

@ -85,6 +85,10 @@ by their ``os`` grain:
company: Foo Industries
.. important::
See :ref:`Is Targeting using Grain Data Secure? <faq-grain-security>` for
important security information.
The above pillar sets two key/value pairs. If a minion is running RedHat, then
the ``apache`` key is set to ``httpd`` and the ``git`` key is set to the value
of ``git``. If the minion is running Debian, those values are changed to

View File

@ -22,6 +22,10 @@ to a custom grain, grain data is refreshed.
Grains resolve to lowercase letters. For example, ``FOO``, and ``foo``
target the same grain.
.. important::
See :ref:`Is Targeting using Grain Data Secure? <faq-grain-security>` for
important security information.
Match all CentOS minions:
.. code-block:: bash

View File

@ -90,6 +90,8 @@ class SaltCloud(parsers.SaltCloudParser):
log.info('salt-cloud starting')
try:
mapper = salt.cloud.Map(self.config)
except SaltCloudSystemExit as exc:
self.handle_exception(exc.args, exc)
except SaltCloudException as exc:
msg = 'There was an error generating the mapper.'
self.handle_exception(msg, exc)
@ -374,7 +376,7 @@ class SaltCloud(parsers.SaltCloudParser):
def handle_exception(self, msg, exc):
if isinstance(exc, SaltCloudException):
# It's a know exception an we know own to handle it
# It's a known exception and we know how to handle it
if isinstance(exc, SaltCloudSystemExit):
# This is a salt cloud system exit
if exc.exit_code > 0:

View File

@ -134,19 +134,17 @@ except ImportError:
log = logging.getLogger(__name__)
SIZE_MAP = {
'Micro Instance': 't1.micro',
'Small Instance': 'm1.small',
'Medium Instance': 'm1.medium',
'Large Instance': 'm1.large',
'Extra Large Instance': 'm1.xlarge',
'High-CPU Medium Instance': 'c1.medium',
'High-CPU Extra Large Instance': 'c1.xlarge',
'High-Memory Extra Large Instance': 'm2.xlarge',
'High-Memory Double Extra Large Instance': 'm2.2xlarge',
'High-Memory Quadruple Extra Large Instance': 'm2.4xlarge',
'Cluster GPU Quadruple Extra Large Instance': 'cg1.4xlarge',
'Cluster Compute Quadruple Extra Large Instance': 'cc1.4xlarge',
'Cluster Compute Eight Extra Large Instance': 'cc2.8xlarge',
'Micro Instance': 't2.micro',
'Small Instance': 't2.small',
'Medium Instance': 'm3.medium',
'Large Instance': 'm4.large',
'Extra Large Instance': 'm4.xlarge',
'High-CPU Medium Instance': 'c4.large',
'High-CPU Extra Large Instance': 'c4.xlarge',
'High-Memory Extra Large Instance': 'r3.xlarge',
'High-Memory Double Extra Large Instance': 'r3.2xlarge',
'High-Memory Quadruple Extra Large Instance': 'r3.4xlarge',
'Cluster GPU Quadruple Extra Large Instance': 'g2.8xlarge'
}
@ -622,57 +620,93 @@ def avail_sizes(call=None):
'ram': '22.5 GiB'
},
},
'High CPU': {
'c1.xlarge': {
'id': 'c1.xlarge',
'cores': '8 (with 2.5 ECUs each)',
'disk': '1680 GiB (4 x 420 GiB)',
'ram': '8 GiB'
'Compute Optimized': {
'c4.large': {
'id': 'c4.large',
'cores': '2',
'disk': 'EBS - 500 Mbps',
'ram': '3.75 GiB'
},
'c1.medium': {
'id': 'c1.medium',
'cores': '2 (with 2.5 ECUs each)',
'disk': '340 GiB (1 x 340 GiB)',
'ram': '1.7 GiB'
'c4.xlarge': {
'id': 'c4.xlarge',
'cores': '4',
'disk': 'EBS - 750 Mbps',
'ram': '7.5 GiB'
},
'c4.2xlarge': {
'id': 'c4.2xlarge',
'cores': '8',
'disk': 'EBS - 1000 Mbps',
'ram': '15 GiB'
},
'c4.4xlarge': {
'id': 'c4.4xlarge',
'cores': '16',
'disk': 'EBS - 2000 Mbps',
'ram': '30 GiB'
},
'c4.8xlarge': {
'id': 'c4.8xlarge',
'cores': '36',
'disk': 'EBS - 4000 Mbps',
'ram': '60 GiB'
},
'c3.large': {
'id': 'c3.large',
'cores': '2 (with 3.5 ECUs each)',
'cores': '2',
'disk': '32 GiB (2 x 16 GiB SSD)',
'ram': '3.75 GiB'
},
'c3.xlarge': {
'id': 'c3.xlarge',
'cores': '4 (with 3.5 ECUs each)',
'cores': '4',
'disk': '80 GiB (2 x 40 GiB SSD)',
'ram': '7.5 GiB'
},
'c3.2xlarge': {
'id': 'c3.2xlarge',
'cores': '8 (with 3.5 ECUs each)',
'cores': '8',
'disk': '160 GiB (2 x 80 GiB SSD)',
'ram': '15 GiB'
},
'c3.4xlarge': {
'id': 'c3.4xlarge',
'cores': '16 (with 3.5 ECUs each)',
'disk': '320 GiB (2 x 80 GiB SSD)',
'cores': '16',
'disk': '320 GiB (2 x 160 GiB SSD)',
'ram': '30 GiB'
},
'c3.8xlarge': {
'id': 'c3.8xlarge',
'cores': '32 (with 3.5 ECUs each)',
'disk': '320 GiB (2 x 160 GiB SSD)',
'cores': '32',
'disk': '640 GiB (2 x 320 GiB SSD)',
'ram': '60 GiB'
}
},
'High I/O': {
'hi1.4xlarge': {
'id': 'hi1.4xlarge',
'cores': '8 (with 4.37 ECUs each)',
'disk': '2 TiB',
'ram': '60.5 GiB'
'i2.xlarge': {
'id': 'i2.xlarge',
'cores': '4',
'disk': 'SSD (1 x 800 GiB)',
'ram': '30.5 GiB'
},
'i2.2xlarge': {
'id': 'i2.2xlarge',
'cores': '8',
'disk': 'SSD (2 x 800 GiB)',
'ram': '61 GiB'
},
'i2.4xlarge': {
'id': 'i2.4xlarge',
'cores': '16',
'disk': 'SSD (4 x 800 GiB)',
'ram': '122 GiB'
},
'i2.8xlarge': {
'id': 'i2.8xlarge',
'cores': '32',
'disk': 'SSD (8 x 800 GiB)',
'ram': '244 GiB'
}
},
'High Memory': {
'm2.2xlarge': {
@ -740,51 +774,85 @@ def avail_sizes(call=None):
'ram': '117 GiB'
},
},
'Micro': {
't1.micro': {
'id': 't1.micro',
'General Purpose': {
't2.micro': {
'id': 't2.micro',
'cores': '1',
'disk': 'EBS',
'ram': '615 MiB'
'ram': '1 GiB'
},
},
'Standard': {
'm1.xlarge': {
'id': 'm1.xlarge',
'cores': '4 (with 2 ECUs each)',
'disk': '1680 GB (4 x 420 GiB)',
'ram': '15 GiB'
},
'm1.large': {
'id': 'm1.large',
'cores': '2 (with 2 ECUs each)',
'disk': '840 GiB (2 x 420 GiB)',
'ram': '7.5 GiB'
},
'm1.medium': {
'id': 'm1.medium',
't2.small': {
'id': 't2.small',
'cores': '1',
'disk': '400 GiB',
'disk': 'EBS',
'ram': '2 GiB'
},
't2.medium': {
'id': 't2.medium',
'cores': '2',
'disk': 'EBS',
'ram': '4 GiB'
},
't2.large': {
'id': 't2.large',
'cores': '2',
'disk': 'EBS',
'ram': '8 GiB'
},
'm4.large': {
'id': 'm4.large',
'cores': '2',
'disk': 'EBS - 450 Mbps',
'ram': '8 GiB'
},
'm4.xlarge': {
'id': 'm4.xlarge',
'cores': '4',
'disk': 'EBS - 750 Mbps',
'ram': '16 GiB'
},
'm4.2xlarge': {
'id': 'm4.2xlarge',
'cores': '8',
'disk': 'EBS - 1000 Mbps',
'ram': '32 GiB'
},
'm4.4xlarge': {
'id': 'm4.4xlarge',
'cores': '16',
'disk': 'EBS - 2000 Mbps',
'ram': '64 GiB'
},
'm4.10xlarge': {
'id': 'm4.10xlarge',
'cores': '40',
'disk': 'EBS - 4000 Mbps',
'ram': '160 GiB'
},
'm3.medium': {
'id': 'm3.medium',
'cores': '1',
'disk': 'SSD (1 x 4)',
'ram': '3.75 GiB'
},
'm1.small': {
'id': 'm1.small',
'cores': '1',
'disk': '150 GiB',
'ram': '1.7 GiB'
},
'm3.2xlarge': {
'id': 'm3.2xlarge',
'cores': '8 (with 3.25 ECUs each)',
'disk': 'EBS',
'ram': '30 GiB'
'm3.large': {
'id': 'm3.large',
'cores': '2',
'disk': 'SSD (1 x 32)',
'ram': '7.5 GiB'
},
'm3.xlarge': {
'id': 'm3.xlarge',
'cores': '4 (with 3.25 ECUs each)',
'disk': 'EBS',
'cores': '4',
'disk': 'SSD (2 x 40)',
'ram': '15 GiB'
},
'm3.2xlarge': {
'id': 'm3.2xlarge',
'cores': '8',
'disk': 'SSD (2 x 80)',
'ram': '30 GiB'
},
}
}
return sizes

View File

@ -467,6 +467,18 @@ def create(vm_, call=None):
__opts__['internal_lxc_profile'] = __opts__['profile']
del __opts__['profile']
salt.utils.cloud.fire_event(
'event',
'created instance',
'salt/cloud/{0}/created'.format(vm_['name']),
{
'name': vm_['name'],
'profile': vm_['profile'],
'provider': vm_['driver'],
},
transport=__opts__['transport']
)
return ret
@ -532,13 +544,10 @@ def get_configured_provider(vm_=None):
{}).get(dalias, {}).get(driver, {})
# in all cases, verify that the linked saltmaster is alive.
if data:
try:
ret = _salt('test.ping', salt_target=data['target'])
if not ret:
raise Exception('error')
return data
except Exception:
ret = _salt('test.ping', salt_target=data['target'])
if not ret:
raise SaltCloudSystemExit(
'Configured provider {0} minion: {1} is unreachable'.format(
__active_provider_name__, data['target']))
return data
return False

View File

@ -123,10 +123,9 @@ def _authenticate():
'password', get_configured_provider(), __opts__, search_global=False
)
verify_ssl = config.get_cloud_config_value(
'verify_ssl', get_configured_provider(), __opts__, search_global=False
'verify_ssl', get_configured_provider(), __opts__,
default=True, search_global=False
)
if verify_ssl is None:
verify_ssl = True
connect_data = {'username': username, 'password': passwd}
full_url = 'https://{0}:8006/api2/json/access/ticket'.format(url)

View File

@ -10,6 +10,7 @@ import logging
import hashlib
import os
import shutil
import ftplib
# Import salt libs
from salt.exceptions import (
@ -572,6 +573,15 @@ class Client(object):
return dest
except Exception:
raise MinionError('Could not fetch from {0}'.format(url))
if url_data.scheme == 'ftp':
try:
ftp = ftplib.FTP(url_data.hostname)
ftp.login()
with salt.utils.fopen(dest, 'wb') as fp_:
ftp.retrbinary('RETR {0}'.format(url_data.path), fp_.write)
return dest
except Exception as exc:
raise MinionError('Could not retrieve {0} from FTP server. Exception: {1}'.format(url, exc))
if url_data.scheme == 'swift':
try:

View File

@ -159,15 +159,15 @@ def set_host(ip, alias):
comps = tmpline.split()
if comps[0] == ip:
if not ovr:
lines[ind] = ip + '\t\t' + alias + '\n'
lines[ind] = ip + '\t\t' + alias + os.linesep
ovr = True
else: # remove other entries
lines[ind] = ''
if not ovr:
# make sure there is a newline
if lines and not lines[-1].endswith(('\n', '\r')):
lines[-1] = '{0}\n'.format(lines[-1])
line = ip + '\t\t' + alias + '\n'
if lines and not lines[-1].endswith(os.linesep):
lines[-1] += os.linesep
line = ip + '\t\t' + alias + os.linesep
lines.append(line)
with salt.utils.fopen(hfn, 'w+') as ofile:
ofile.writelines(lines)
@ -206,7 +206,7 @@ def rm_host(ip, alias):
lines[ind] = ''
else:
# Only an alias was removed
lines[ind] = '{0}\n'.format(newline)
lines[ind] = newline + os.linesep
with salt.utils.fopen(hfn, 'w+') as ofile:
ofile.writelines(lines)
return True
@ -262,4 +262,4 @@ def _write_hosts(hosts):
if line.strip():
# /etc/hosts needs to end with EOL so that some utils that read
# it do not break
ofile.write('{0}\n'.format(line.strip()))
ofile.write(line.strip() + os.linesep)

View File

@ -6,14 +6,16 @@ Author: Anthony Stanton <anthony.stanton@gmail.com>
Inspired by the S3 and Nova modules
:depends: - swiftclient Python module
:configuration: This module is not usable until the user, password, tenant, and
auth URL are specified either in a pillar or in the minion's config file.
:configuration: This module is not usable until the user, tenant, auth URL, and password or auth_key
are specified either in a pillar or in the minion's config file.
For example::
keystone.user: admin
keystone.password: verybadpass
keystone.tenant: admin
keystone.auth_url: 'http://127.0.0.1:5000/v2.0/'
keystone.password: verybadpass
# or
keystone.auth_key: 203802934809284k2j34lkj2l3kj43k
If configuration for multiple OpenStack accounts is required, they can be
set up as different configuration profiles:
@ -21,21 +23,27 @@ Inspired by the S3 and Nova modules
openstack1:
keystone.user: admin
keystone.password: verybadpass
keystone.tenant: admin
keystone.auth_url: 'http://127.0.0.1:5000/v2.0/'
keystone.password: verybadpass
# or
keystone.auth_key: 203802934809284k2j34lkj2l3kj43k
openstack2:
keystone.user: admin
keystone.password: verybadpass
keystone.tenant: admin
keystone.auth_url: 'http://127.0.0.2:5000/v2.0/'
keystone.password: verybadpass
# or
keystone.auth_key: 303802934809284k2j34lkj2l3kj43k
With this configuration in place, any of the swift functions can make use of
a configuration profile by declaring it explicitly.
For example::
salt '*' swift.get mycontainer myfile /tmp/file profile=openstack1
NOTE: For Rackspace cloud files setting keystone.auth_version = 1 is recommended.
'''
from __future__ import absolute_import
@ -67,26 +75,29 @@ def _auth(profile=None):
if profile:
credentials = __salt__['config.option'](profile)
user = credentials['keystone.user']
password = credentials['keystone.password']
password = credentials.get('keystone.password', None)
tenant = credentials['keystone.tenant']
auth_url = credentials['keystone.auth_url']
auth_version = credentials.get('keystone.auth_version', 2)
region_name = credentials.get('keystone.region_name', None)
api_key = credentials.get('keystone.api_key', None)
os_auth_system = credentials.get('keystone.os_auth_system', None)
else:
user = __salt__['config.option']('keystone.user')
password = __salt__['config.option']('keystone.password')
password = __salt__['config.option']('keystone.password', None)
tenant = __salt__['config.option']('keystone.tenant')
auth_url = __salt__['config.option']('keystone.auth_url')
auth_version = __salt__['config.option']('keystone.auth_version', 2)
region_name = __salt__['config.option']('keystone.region_name')
api_key = __salt__['config.option']('keystone.api_key')
os_auth_system = __salt__['config.option']('keystone.os_auth_system')
kwargs = {
'user': user,
'password': password,
'api_key': api_key,
'key': api_key,
'tenant_name': tenant,
'auth_url': auth_url,
'auth_version': auth_version,
'region_name': region_name
}

View File

@ -75,11 +75,7 @@ def get_path():
'''
ret = __salt__['reg.read_value']('HKEY_LOCAL_MACHINE',
'SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment',
'PATH')
if isinstance(ret, dict):
ret = ret['vdata'].split(';')
if isinstance(ret, str):
ret = ret.split(';')
'PATH')['vdata'].split(';')
# Trim ending backslash
return list(map(_normalize_dir, ret))

View File

@ -704,7 +704,12 @@ def installed(name,
trusted_host=trusted_host
)
if pip_install_call and (pip_install_call.get('retcode', 1) == 0):
# Check the retcode for success, but don't fail if using pip1 and the package is
# already present. Pip1 returns a retcode of 1 (instead of 0 for pip2) if you run
# "pip install" without any arguments. See issue #21845.
if pip_install_call and \
(pip_install_call.get('retcode', 1) == 0 or pip_install_call.get('stdout', '').startswith(
'You must give at least one requirement to install')):
ret['result'] = True
if requirements or editable:

View File

@ -243,8 +243,12 @@ def state(
if mdata.get('failed', False):
m_state = False
else:
m_ret = mdata['ret']
m_state = salt.utils.check_state_result(m_ret)
try:
m_ret = mdata['ret']
except KeyError:
m_state = False
if not m_state:
m_state = salt.utils.check_state_result(m_ret)
if not m_state:
if minion not in fail_minions: