Merge remote-tracking branch 'upstream/2014.7' into merge-forward-2015.5

Conflicts:
    salt/modules/lxc.py
    salt/states/cloud.py
    salt/utils/validate/net.py
This commit is contained in:
Colton Myers 2015-05-15 13:40:26 -06:00
commit 51d23ed9d0
9 changed files with 138 additions and 12 deletions

View file

@ -351,7 +351,7 @@ class CloudClient(object):
'''
Destroy the named VMs
'''
mapper = salt.cloud.Map(self._opts_defaults())
mapper = salt.cloud.Map(self._opts_defaults(destroy=True))
if isinstance(names, str):
names = names.split(',')
return salt.utils.cloud.simple_types_filter(
@ -446,7 +446,7 @@ class CloudClient(object):
kwargs={'image': 'ami-10314d79'}
)
'''
mapper = salt.cloud.Map(self._opts_defaults(action=fun))
mapper = salt.cloud.Map(self._opts_defaults(action=fun, names=names))
if names and not provider:
self.opts['action'] = fun
return mapper.do_action(names, kwargs)

View file

@ -424,10 +424,22 @@ def create(vm_, call=None):
kwarg['host'] = prov['target']
cret = _runner().cmd('lxc.cloud_init', [vm_['name']], kwarg=kwarg)
ret['runner_return'] = cret
if cret['result']:
ret['result'] = False
ret['result'] = cret['result']
if not ret['result']:
ret['Error'] = 'Error while creating {0},'.format(vm_['name'])
else:
ret['changes']['created'] = 'created'
# When using cloud states to manage LXC containers
# __opts__['profile'] is not implicitly reset between operations
# on different containers. However list_nodes will hide container
# if profile is set in opts assuming that it have to be created.
# But in cloud state we do want to check at first if it really
# exists hence the need to remove profile from global opts once
# current container is created.
if 'profile' in __opts__:
del __opts__['profile']
return ret

85
salt/ext/win_inet_pton.py Normal file
View file

@ -0,0 +1,85 @@
# -*- coding: utf-8 -*-
# This software released into the public domain. Anyone is free to copy,
# modify, publish, use, compile, sell, or distribute this software,
# either in source code form or as a compiled binary, for any purpose,
# commercial or non-commercial, and by any means.
import socket
import ctypes
import os
class sockaddr(ctypes.Structure):
_fields_ = [("sa_family", ctypes.c_short),
("__pad1", ctypes.c_ushort),
("ipv4_addr", ctypes.c_byte * 4),
("ipv6_addr", ctypes.c_byte * 16),
("__pad2", ctypes.c_ulong)]
if hasattr(ctypes, 'windll'):
WSAStringToAddressA = ctypes.windll.ws2_32.WSAStringToAddressA
WSAAddressToStringA = ctypes.windll.ws2_32.WSAAddressToStringA
else:
def not_windows():
raise SystemError(
"Invalid platform. ctypes.windll must be available."
)
WSAStringToAddressA = not_windows
WSAAddressToStringA = not_windows
def inet_pton(address_family, ip_string):
addr = sockaddr()
addr.sa_family = address_family
addr_size = ctypes.c_int(ctypes.sizeof(addr))
if WSAStringToAddressA(
ip_string,
address_family,
None,
ctypes.byref(addr),
ctypes.byref(addr_size)
) != 0:
raise socket.error(ctypes.FormatError())
if address_family == socket.AF_INET:
return ctypes.string_at(addr.ipv4_addr, 4)
if address_family == socket.AF_INET6:
return ctypes.string_at(addr.ipv6_addr, 16)
raise socket.error('unknown address family')
def inet_ntop(address_family, packed_ip):
addr = sockaddr()
addr.sa_family = address_family
addr_size = ctypes.c_int(ctypes.sizeof(addr))
ip_string = ctypes.create_string_buffer(128)
ip_string_size = ctypes.c_int(ctypes.sizeof(ip_string))
if address_family == socket.AF_INET:
if len(packed_ip) != ctypes.sizeof(addr.ipv4_addr):
raise socket.error('packed IP wrong length for inet_ntoa')
ctypes.memmove(addr.ipv4_addr, packed_ip, 4)
elif address_family == socket.AF_INET6:
if len(packed_ip) != ctypes.sizeof(addr.ipv6_addr):
raise socket.error('packed IP wrong length for inet_ntoa')
ctypes.memmove(addr.ipv6_addr, packed_ip, 16)
else:
raise socket.error('unknown address family')
if WSAAddressToStringA(
ctypes.byref(addr),
addr_size,
None,
ip_string,
ctypes.byref(ip_string_size)
) != 0:
raise socket.error(ctypes.FormatError())
return ip_string[:ip_string_size.value - 1]
# Adding our two functions to the socket library
if os.name == 'nt':
socket.inet_pton = inet_pton
socket.inet_ntop = inet_ntop

View file

@ -157,11 +157,18 @@ def item(*args, **kwargs):
salt '*' grains.item host sanitize=True
'''
ret = {}
for arg in args:
try:
ret[arg] = __grains__[arg]
except KeyError:
pass
default = kwargs.get('default', '')
delimiter = kwargs.get('delimiter', ':')
try:
for arg in args:
ret[arg] = salt.utils.traverse_dict_and_list(__grains__,
arg,
default,
delimiter)
except KeyError:
pass
if salt.utils.is_true(kwargs.get('sanitize')):
for arg, func in _SANITIZERS.items():
if arg in ret:

View file

@ -49,7 +49,7 @@ def render(yaml_data, saltenv='base', sls='', argline='', **kws):
try:
data = load(yaml_data, Loader=get_yaml_loader(argline))
except ScannerError as exc:
err_type = _ERROR_MAP.get(exc.problem, 'Unknown yaml render error')
err_type = _ERROR_MAP.get(exc.problem, exc.problem)
line_num = exc.problem_mark.line + 1
raise SaltRenderError(err_type, line_num, exc.problem_mark.buffer)
except ConstructorError as exc:

View file

@ -78,7 +78,7 @@ class Roster(object):
try:
targets.update(self.rosters[f_str](tgt, tgt_type))
except salt.exceptions.SaltRenderError as exc:
log.debug('Unable to render roster file: {0}'.format(exc.error))
log.error('Unable to render roster file: {0}'.format(exc))
except IOError as exc:
pass

View file

@ -50,6 +50,15 @@ def _valid(name, comment='', changes=None):
'comment': comment}
def _get_instance(names):
# for some reason loader overwrites __opts__['test'] with default
# value of False, thus store and then load it again after action
test = __opts__['test']
instance = __salt__['cloud.action'](fun='show_instance', names=names)
__opts__['test'] = test
return instance
def present(name, cloud_provider, onlyif=None, unless=None, **kwargs):
'''
Spin up a single instance on a cloud provider, using salt-cloud. This state
@ -245,7 +254,7 @@ def profile(name, profile, onlyif=None, unless=None, **kwargs):
elif isinstance(unless, string_types):
if retcode(unless) == 0:
return _valid(name, comment='unless execution succeeded')
instance = __salt__['cloud.action'](fun='show_instance', names=[name])
instance = _get_instance([name])
prov = str(next(instance.iterkeys()))
if instance and 'Not Actioned' not in prov:
ret['result'] = True

View file

@ -1764,6 +1764,14 @@ def directory(name,
if not os.path.isdir(os.path.dirname(name)):
# The parent directory does not exist, create them
if makedirs:
# Make sure the drive is mapped before trying to create the
# path in windows
if salt.utils.is_windows():
drive, path = os.path.splitdrive(name)
if not os.path.isdir(drive):
return _error(
ret, 'Drive {0} is not mapped'.format(drive))
# Everything's good, create the path
__salt__['file.makedirs'](
name, user=user, group=group, mode=dir_mode
)

View file

@ -10,6 +10,11 @@ import socket
# Import salt libs
from salt.ext.six import string_types
import salt.utils
# Import third party libs
if salt.utils.is_windows():
from salt.ext import win_inet_pton # pylint: disable=unused-import
def mac(addr):