Merge branch '2014.7' into merge-forward

Conflicts:
	doc/topics/releases/2014.7.1.rst
	salt/modules/mdadm.py
	salt/modules/mine.py
	salt/modules/win_firewall.py
	salt/modules/win_groupadd.py
	salt/modules/win_service.py
	salt/modules/win_system.py
	salt/modules/win_useradd.py
	salt/runners/jobs.py
	tests/unit/modules/mdadm_test.py
This commit is contained in:
Colton Myers 2014-12-22 13:33:53 -07:00
commit 7fc1cc2ba2
17 changed files with 309 additions and 317 deletions

View file

@ -21,7 +21,7 @@ minion exe>` should match the contents of the corresponding md5 file.
.. admonition:: Download here
* 2014.7.0
* `Salt-Minion-2014.7.0-x86-Setup.exe <http://docs.saltstack.com/downloads/Salt-Minion-2014.7.0-x86-Setup.exe>`__ | `md5 <http://docs.saltstack.com/downloads/Salt-Minion-2014.7.0-x86-Setup.exe.md5>`__
* `Salt-Minion-2014.7.0-1-win32-Setup.exe <http://docs.saltstack.com/downloads/Salt-Minion-2014.7.0-1-win32-Setup.exe>`__ | `md5 <http://docs.saltstack.com/downloads/Salt-Minion-2014.7.0-1-win32-Setup.exe.md5>`__
* `Salt-Minion-2014.7.0-AMD64-Setup.exe <http://docs.saltstack.com/downloads/Salt-Minion-2014.7.0-AMD64-Setup.exe>`__ | `md5 <http://docs.saltstack.com/downloads/Salt-Minion-2014.7.0-AMD64-Setup.exe.md5>`__
* 2014.1.13

View file

@ -12,4 +12,8 @@ Version 2014.7.1 is a bugfix release for :doc:`2014.7.0
- Fixed holding of multiple packages (YUM) when combined with version pinning
(:issue:`18468`)
- Fixed use of Jinja templates in masterless mode with non-roots fileserver
backend (:issue:`17963`)
backend (:issue:`17963`)
- Re-enabled pillar and compound matching for mine and publish calls. Note that
pillar globbing is still disabled for those modes, for security reasons.
(:issue:`17194`)
- Fix for ``tty: True`` in salt-ssh (:issue:`16847`)

View file

@ -428,8 +428,9 @@ def create(vm_):
conn = get_conn()
label = vm_.get('label', vm_['name'])
service_name = vm_.get('service_name', vm_['name'])
service_kwargs = {
'service_name': vm_['name'],
'service_name': service_name,
'label': label,
'description': vm_.get('desc', vm_['name']),
'location': vm_['location'],
@ -460,7 +461,7 @@ def create(vm_):
os_hd = azure.servicemanagement.OSVirtualHardDisk(vm_['image'], media_link)
vm_kwargs = {
'service_name': vm_['name'],
'service_name': service_name,
'deployment_name': vm_['name'],
'deployment_slot': vm_['slot'],
'label': label,
@ -681,9 +682,14 @@ def create(vm_):
return ret
def destroy(name, conn=None, call=None):
def destroy(name, conn=None, call=None, kwargs=None):
'''
Destroy a VM
CLI Examples::
salt-cloud -d myminion
salt-cloud -a destroy myminion service_name=myservice
'''
if call == 'function':
raise SaltCloudSystemExit(
@ -694,10 +700,12 @@ def destroy(name, conn=None, call=None):
if not conn:
conn = get_conn()
service_name = kwargs.get('service_name', name)
ret = {}
# TODO: Add the ability to delete or not delete a hosted service when
# deleting a VM
del_vm = conn.delete_deployment(service_name=name, deployment_name=name)
del_vm = conn.delete_deployment(service_name=service_name, deployment_name=name)
del_service = conn.delete_hosted_service
ret[name] = {
'request_id': del_vm.request_id,

View file

@ -81,7 +81,8 @@ def chocolatey_version():
try:
return __context__['chocolatey._version']
except KeyError:
out = __salt__['cmd.run']('{0} help'.format(_find_chocolatey()))
cmd = [_find_chocolatey(), 'help']
out = __salt__['cmd.run'](cmd, python_shell=False)
for line in out.splitlines():
if line.lower().startswith('version: '):
try:
@ -150,7 +151,8 @@ def bootstrap(force=False):
url = ps_downloads[(__grains__['osrelease'], __grains__['cpuarch'])]
dest = os.path.join(temp_dir, 'powershell.exe')
__salt__['cp.get_url'](url, dest)
result = __salt__['cmd.run_all'](dest + ' /quiet /norestart')
cmd = [dest, '/quiet', '/norestart']
result = __salt__['cmd.run_all'](cmd, python_shell=False)
if result['retcode'] != 0:
err = ('Installing Windows PowerShell failed. Please run the '
'installer GUI on the host to get a more specific '
@ -165,7 +167,8 @@ def bootstrap(force=False):
# Run the .NET Framework 4 web installer
dest = os.path.join(temp_dir, 'dotnet4.exe')
__salt__['cp.get_url'](net4_url, dest)
result = __salt__['cmd.run_all'](dest + ' /q /norestart')
cmd = [dest, '/q', '/norestart']
result = __salt__['cmd.run_all'](cmd, python_shell=False)
if result['retcode'] != 0:
err = ('Installing .NET v4.0 failed. Please run the installer GUI on '
'the host to get a more specific reason.')
@ -173,13 +176,14 @@ def bootstrap(force=False):
raise CommandExecutionError(err)
# Run the Chocolatey bootstrap.
result = __salt__['cmd.run_all'](
cmd = (
'{0} -NoProfile -ExecutionPolicy unrestricted '
'-Command "iex ((new-object net.webclient).'
'DownloadString(\'https://chocolatey.org/install.ps1\'))" '
'&& SET PATH=%PATH%;%systemdrive%\\chocolatey\\bin'
.format(ps_path)
)
result = __salt__['cmd.run_all'](cmd, python_shell=True)
if result['retcode'] != 0:
err = 'Bootstrapping Chocolatey failed: {0}'.format(result['stderr'])
@ -214,15 +218,15 @@ def list_(filter, all_versions=False, pre_versions=False, source=None):
salt '*' chocolatey.list <filter> all_versions=True
'''
choc_path = _find_chocolatey()
cmd = choc_path + ' list ' + filter
cmd = [choc_path, 'list', filter]
if salt.utils.is_true(all_versions):
cmd += ' -AllVersions'
cmd.append('-AllVersions')
if salt.utils.is_true(pre_versions):
cmd += ' -Prerelease'
cmd.append('-Prerelease')
if source:
cmd += ' -Source ' + source
cmd.extend(['-Source', source])
result = __salt__['cmd.run_all'](cmd)
result = __salt__['cmd.run_all'](cmd, python_shell=False)
if result['retcode'] != 0:
err = 'Running chocolatey failed: {0}'.format(result['stderr'])
@ -239,7 +243,6 @@ def list_(filter, all_versions=False, pre_versions=False, source=None):
ret[name] = []
ret[name].append(ver)
#log.info(repr(ret))
return ret
@ -254,8 +257,8 @@ def list_webpi():
salt '*' chocolatey.list_webpi
'''
choc_path = _find_chocolatey()
cmd = choc_path + ' list -Source webpi'
result = __salt__['cmd.run_all'](cmd)
cmd = [choc_path, 'list', '-Source', 'webpi']
result = __salt__['cmd.run_all'](cmd, python_shell=False)
if result['retcode'] != 0:
err = 'Running chocolatey failed: {0}'.format(result['stderr'])
@ -277,8 +280,8 @@ def list_windowsfeatures():
salt '*' chocolatey.list_windowsfeatures
'''
choc_path = _find_chocolatey()
cmd = choc_path + ' list -Source windowsfeatures'
result = __salt__['cmd.run_all'](cmd)
cmd = [choc_path, 'list', '-Source', 'windowsfeatures']
result = __salt__['cmd.run_all'](cmd, python_shell=False)
if result['retcode'] != 0:
err = 'Running chocolatey failed: {0}'.format(result['stderr'])
@ -314,14 +317,14 @@ def install(name, version=None, source=None, force=False):
'''
choc_path = _find_chocolatey()
# chocolatey helpfully only supports a single package argument
cmd = choc_path + ' install ' + name
cmd = [choc_path, 'install', name]
if version:
cmd += ' -Version ' + version
cmd.extend(['-Version', version])
if source:
cmd += ' -Source ' + source
cmd.extend(['-Source', source])
if salt.utils.is_true(force):
cmd += ' -Force'
result = __salt__['cmd.run_all'](cmd)
cmd.append('-Force')
result = __salt__['cmd.run_all'](cmd, python_shell=False)
if result['retcode'] != 0:
err = 'Running chocolatey failed: {0}'.format(result['stderr'])
@ -345,8 +348,8 @@ def install_cygwin(name):
salt '*' chocolatey.install_cygwin <package name>
'''
choc_path = _find_chocolatey()
cmd = choc_path + ' cygwin ' + name
result = __salt__['cmd.run_all'](cmd)
cmd = [choc_path, 'cygwin', name]
result = __salt__['cmd.run_all'](cmd, python_shell=False)
if result['retcode'] != 0:
err = 'Running chocolatey failed: {0}'.format(result['stderr'])
@ -375,10 +378,10 @@ def install_gem(name, version=None):
salt '*' chocolatey.install_gem <package name> version=<package version>
'''
choc_path = _find_chocolatey()
cmd = choc_path + ' gem ' + name
cmd = [choc_path, 'gem', name]
if version:
cmd += ' -Version ' + version
result = __salt__['cmd.run_all'](cmd)
cmd.extend(['-Version', version])
result = __salt__['cmd.run_all'](cmd, python_shell=False)
if result['retcode'] != 0:
err = 'Running chocolatey failed: {0}'.format(result['stderr'])
@ -422,12 +425,12 @@ def install_missing(name, version=None, source=None):
return install(name, version=version)
# chocolatey helpfully only supports a single package argument
cmd = choc_path + ' installmissing ' + name
cmd = [choc_path, 'installmissing', name]
if version:
cmd += ' -Version ' + version
cmd.extend(['-Version', version])
if source:
cmd += ' -Source ' + source
result = __salt__['cmd.run_all'](cmd)
cmd.extend(['-Source', source])
result = __salt__['cmd.run_all'](cmd, python_shell=False)
if result['retcode'] != 0:
err = 'Running chocolatey failed: {0}'.format(result['stderr'])
@ -456,10 +459,10 @@ def install_python(name, version=None):
salt '*' chocolatey.install_python <package name> version=<package version>
'''
choc_path = _find_chocolatey()
cmd = choc_path + ' python ' + name
cmd = [choc_path, 'python', name]
if version:
cmd += ' -Version ' + version
result = __salt__['cmd.run_all'](cmd)
cmd.extend(['-Version', version])
result = __salt__['cmd.run_all'](cmd, python_shell=False)
if result['retcode'] != 0:
err = 'Running chocolatey failed: {0}'.format(result['stderr'])
@ -484,8 +487,8 @@ def install_windowsfeatures(name):
salt '*' chocolatey.install_windowsfeatures <package name>
'''
choc_path = _find_chocolatey()
cmd = choc_path + ' windowsfeatures ' + name
result = __salt__['cmd.run_all'](cmd)
cmd = [choc_path, 'windowsfeatures', name]
result = __salt__['cmd.run_all'](cmd, python_shell=False)
if result['retcode'] != 0:
err = 'Running chocolatey failed: {0}'.format(result['stderr'])
@ -509,8 +512,8 @@ def install_webpi(name):
salt '*' chocolatey.install_webpi <package name>
'''
choc_path = _find_chocolatey()
cmd = choc_path + ' webpi ' + name
result = __salt__['cmd.run_all'](cmd)
cmd = [choc_path, 'webpi', name]
result = __salt__['cmd.run_all'](cmd, python_shell=False)
if result['retcode'] != 0:
err = 'Running chocolatey failed: {0}'.format(result['stderr'])
@ -540,10 +543,10 @@ def uninstall(name, version=None):
'''
choc_path = _find_chocolatey()
# chocolatey helpfully only supports a single package argument
cmd = choc_path + ' uninstall ' + name
cmd = [choc_path, 'uninstall', name]
if version:
cmd += ' -Version ' + version
result = __salt__['cmd.run_all'](cmd)
cmd.extend(['-Version', version])
result = __salt__['cmd.run_all'](cmd, python_shell=False)
if result['retcode'] != 0:
err = 'Running chocolatey failed: {0}'.format(result['stderr'])
@ -577,12 +580,12 @@ def update(name, source=None, pre_versions=False):
'''
# chocolatey helpfully only supports a single package argument
choc_path = _find_chocolatey()
cmd = choc_path + ' update ' + name
cmd = [choc_path, 'update', name]
if source:
cmd += ' -Source ' + source
cmd.extend(['-Source', source])
if salt.utils.is_true(pre_versions):
cmd += ' -PreRelease'
result = __salt__['cmd.run_all'](cmd)
cmd.append('-PreRelease')
result = __salt__['cmd.run_all'](cmd, python_shell=False)
if result['retcode'] != 0:
err = 'Running chocolatey failed: {0}'.format(result['stderr'])
@ -624,15 +627,15 @@ def version(name, check_remote=False, source=None, pre_versions=False):
log.error(err)
raise CommandExecutionError(err)
cmd = choc_path + ' version ' + name
cmd = [choc_path, 'version', name]
if not salt.utils.is_true(check_remote):
cmd += ' -LocalOnly'
cmd.append('-LocalOnly')
if salt.utils.is_true(pre_versions):
cmd += ' -Prerelease'
cmd.append('-Prerelease')
if source:
cmd += ' -Source ' + source
cmd.extend(['-Source', source])
result = __salt__['cmd.run_all'](cmd)
result = __salt__['cmd.run_all'](cmd, python_shell=False)
if result['retcode'] != 0:
err = 'Running chocolatey failed: {0}'.format(result['stderr'])

View file

@ -308,7 +308,8 @@ def _run(cmd,
env.setdefault('LC_ALL', 'C')
else:
# On Windows set the codepage to US English.
cmd = 'chcp 437 > nul & ' + cmd
if python_shell:
cmd = 'chcp 437 > nul & ' + cmd
if clean_env:
run_env = env

View file

@ -51,8 +51,8 @@ def list_():
winver = __grains__['osfullname']
for key in keys:
autoruns[key] = []
cmd = 'reg query ' + key
for line in __salt__['cmd.run'](cmd).splitlines():
cmd = ['reg', 'query', key]
for line in __salt__['cmd.run'](cmd, python_shell=False).splitlines():
if line and line[0:4] != "HKEY" and line[0:5] != "ERROR": # Remove junk lines
autoruns[key].append(line)

View file

@ -36,8 +36,8 @@ def get_config():
profiles = {}
curr = None
cmd = 'netsh advfirewall show allprofiles'
for line in __salt__['cmd.run'](cmd).splitlines():
cmd = ['netsh', 'advfirewall', 'show', 'allprofiles']
for line in __salt__['cmd.run'](cmd, python_shell=False).splitlines():
if not curr:
tmp = re.search('(.*) Profile Settings:', line)
if tmp:
@ -59,9 +59,8 @@ def disable(profile='allprofiles'):
salt '*' firewall.disable
'''
return __salt__['cmd.run'](
'netsh advfirewall set {0} state off'.format(profile)
) == 'Ok.'
cmd = ['netsh', 'advfirewall', 'set', 'allprofiles', 'state', 'off']
return __salt__['cmd.run'](cmd, python_shell=False) == 'Ok.'
def enable(profile='allprofiles'):
@ -90,8 +89,8 @@ def get_rule(name="all"):
salt '*' firewall.get_rule "MyAppPort"
'''
ret = {}
cmd = 'netsh advfirewall firewall show rule name="{0}"'.format(name)
ret[name] = __salt__['cmd.run'](cmd)
cmd = ['netsh', 'advfirewall', 'firewall', 'show', 'rule', 'name={0}'.format(name)]
ret[name] = __salt__['cmd.run'](cmd, python_shell=False)
if ret[name].strip() == "No rules match the specified criteria.":
ret = False
@ -109,5 +108,10 @@ def add_rule(name, localport, protocol="tcp", action="allow", dir="in"):
salt '*' firewall.add_rule "test" "tcp" "8080"
'''
cmd = 'netsh advfirewall firewall add rule name="{0}" protocol={1} dir={2} localport={3} action={4}'.format(name, protocol, dir, localport, action)
return __salt__['cmd.run'](cmd) == 'Ok.'
cmd = ['netsh', 'advfirewall', 'firewall', 'add', 'rule',
'name={0}'.format(name),
'protocol={0}'.format(protocol),
'dir={0}'.format(dir),
'localport={0}'.format(localport),
'action={0}'.format(action)]
return __salt__['cmd.run'](cmd, python_shell=False) == 'Ok.'

View file

@ -39,8 +39,8 @@ def _interface_configs():
'''
Return all interface configs
'''
cmd = 'netsh interface ip show config'
lines = __salt__['cmd.run'](cmd).splitlines()
cmd = ['netsh', 'interface', 'ip', 'show', 'config']
lines = __salt__['cmd.run'](cmd, python_shell=False).splitlines()
iface = ''
ip = 0
dns_flag = None
@ -110,8 +110,8 @@ def raw_interface_configs():
salt -G 'os_family:Windows' ip.raw_interface_configs
'''
cmd = 'netsh interface ip show config'
return __salt__['cmd.run'](cmd)
cmd = ['netsh', 'interface', 'ip', 'show', 'config']
return __salt__['cmd.run'](cmd, python_shell=False)
def get_all_interfaces():
@ -150,14 +150,14 @@ def is_enabled(iface):
salt -G 'os_family:Windows' ip.is_enabled 'Local Area Connection #2'
'''
cmd = 'netsh interface show interface name="{0}"'.format(iface)
cmd = ['netsh', 'interface', 'show', 'interface', 'name={0}'.format(iface)]
iface_found = False
for line in __salt__['cmd.run'](cmd).splitlines():
for line in __salt__['cmd.run'](cmd, python_shell=False).splitlines():
if 'Connect state:' in line:
iface_found = True
return line.split()[-1] == 'Connected'
if not iface_found:
raise CommandExecutionError('Interface {0!r} not found')
raise CommandExecutionError('Interface {0!r} not found'.format(iface))
return False
@ -186,9 +186,8 @@ def enable(iface):
'''
if is_enabled(iface):
return True
__salt__['cmd.run'](
'netsh interface set interface "{0}" admin=ENABLED'.format(iface)
)
cmd = ['netsh', 'interface', 'set', 'interface', iface, 'admin=ENABLED']
__salt__['cmd.run'](cmd, python_shell=False)
return is_enabled(iface)
@ -204,9 +203,8 @@ def disable(iface):
'''
if is_disabled(iface):
return True
__salt__['cmd.run'](
'netsh interface set interface "{0}" admin=DISABLED'.format(iface)
)
cmd = ['netsh', 'interface', 'set', 'interface', iface, 'admin=DISABLED']
__salt__['cmd.run'](cmd, python_shell=False)
return is_disabled(iface)
@ -280,19 +278,19 @@ def set_static_ip(iface, addr, gateway=None, append=False):
'{1!r}'.format(addr, iface)
)
# Do not use raw string formatting (ex. {1!r}) for interface name, as the
# windows command shell does not like single quotes.
cmd = (
'netsh interface ip {0} address name="{1}" {2} '
'address={3}{4}'.format(
'add' if append else 'set',
iface,
'' if append else 'source=static',
addr,
' gateway={0}'.format(gateway) if gateway else '',
)
)
result = __salt__['cmd.run_all'](cmd)
cmd = ['netsh', 'interface', 'ip']
if append:
cmd.append('add')
else:
cmd.append('set')
cmd.extend(['address', 'name={0}'.format(iface)])
if not append:
cmd.append('source=static')
cmd.append('address={0}'.format(addr))
if gateway:
cmd.append('gateway={0}'.format(gateway))
result = __salt__['cmd.run_all'](cmd, python_shell=False)
if result['retcode'] != 0:
raise CommandExecutionError(
'Unable to set IP address: {0}'.format(result['stderr'])
@ -318,8 +316,8 @@ def set_dhcp_ip(iface):
salt -G 'os_family:Windows' ip.set_dhcp_ip 'Local Area Connection'
'''
cmd = 'netsh interface ip set address "{0}" dhcp'.format(iface)
__salt__['cmd.run'](cmd)
cmd = ['netsh', 'interface', 'ip', 'set', 'address', iface, 'dhcp']
__salt__['cmd.run'](cmd, python_shell=False)
return {'Interface': iface, 'DHCP enabled': 'Yes'}
@ -337,15 +335,16 @@ def set_static_dns(iface, *addrs):
addr_index = 1
for addr in addrs:
if addr_index == 1:
cmd = 'netsh int ip set dns "{0}" static {1} primary'.format(
iface,
addrs[0],
)
__salt__['cmd.run'](cmd)
cmd = ['netsh', 'int', 'ip', 'set', 'dns',
iface, 'static', addrs[0], 'primary']
__salt__['cmd.run'](cmd, python_shell=False)
addr_index = addr_index + 1
else:
cmd = 'netsh interface ip add dns name="{0}" addr="{1}" index={2}'
__salt__['cmd.run'](cmd.format(iface, addr, addr_index))
cmd = ['netsh', 'interface', 'ip', 'add', 'dns',
'name={0}'.format(iface),
'addr={0}'.format(addr),
'index={0}'.format(addr_index)]
__salt__['cmd.run'](cmd, python_shell=False)
addr_index = addr_index + 1
return {'Interface': iface, 'DNS Server': addrs}
@ -360,8 +359,8 @@ def set_dhcp_dns(iface):
salt -G 'os_family:Windows' ip.set_dhcp_dns 'Local Area Connection'
'''
cmd = 'netsh interface ip set dns "{0}" dhcp'.format(iface)
__salt__['cmd.run'](cmd)
cmd = ['netsh', 'interface', 'ip', 'set', 'dns', iface, 'dhcp']
__salt__['cmd.run'](cmd, python_shell=False)
return {'Interface': iface, 'DNS Server': 'DHCP'}
@ -393,7 +392,8 @@ def get_default_gateway():
try:
return next(iter(
x.split()[-1] for x in __salt__['cmd.run'](
'netsh interface ip show config'
['netsh', 'interface', 'ip', 'show', 'config'],
python_shell=False
).splitlines()
if 'Default Gateway:' in x
))

View file

@ -42,8 +42,8 @@ def ping(host):
salt '*' network.ping archlinux.org
'''
cmd = 'ping -n 4 {0}'.format(salt.utils.network.sanitize_host(host))
return __salt__['cmd.run'](cmd)
cmd = ['ping', '-n', '4', salt.utils.network.sanitize_host(host)]
return __salt__['cmd.run'](cmd, python_shell=False)
def netstat():
@ -57,8 +57,8 @@ def netstat():
salt '*' network.netstat
'''
ret = []
cmd = 'netstat -nao'
lines = __salt__['cmd.run'](cmd).splitlines()
cmd = ['netstat', '-nao']
lines = __salt__['cmd.run'](cmd, python_shell=False).splitlines()
for line in lines:
comps = line.split()
if line.startswith(' TCP'):
@ -89,8 +89,8 @@ def traceroute(host):
salt '*' network.traceroute archlinux.org
'''
ret = []
cmd = 'tracert {0}'.format(salt.utils.network.sanitize_host(host))
lines = __salt__['cmd.run'](cmd).splitlines()
cmd = ['tracert', salt.utils.network.sanitize_host(host)]
lines = __salt__['cmd.run'](cmd, python_shell=False).splitlines()
for line in lines:
if ' ' not in line:
continue
@ -144,8 +144,8 @@ def nslookup(host):
'''
ret = []
addresses = []
cmd = 'nslookup {0}'.format(salt.utils.network.sanitize_host(host))
lines = __salt__['cmd.run'](cmd).splitlines()
cmd = ['nslookup', salt.utils.network.sanitize_host(host)]
lines = __salt__['cmd.run'](cmd, python_shell=False).splitlines()
for line in lines:
if addresses:
# We're in the last block listing addresses
@ -177,8 +177,8 @@ def dig(host):
salt '*' network.dig archlinux.org
'''
cmd = 'dig {0}'.format(salt.utils.network.sanitize_host(host))
return __salt__['cmd.run'](cmd)
cmd = ['dig', salt.utils.network.sanitize_host(host)]
return __salt__['cmd.run'](cmd, python_shell=False)
def interfaces_names():

View file

@ -41,13 +41,19 @@ def set_servers(*servers):
if not __salt__['service.status'](service_name):
if not __salt__['service.start'](service_name):
return False
ret = __salt__['cmd.run'](
'W32tm /config /syncfromflags:manual /manualpeerlist:"{0}" &&'
'W32tm /config /reliable:yes && W32tm /config /update'
.format(' '.join(servers))
)
server_cmd = ['W32tm', '/config', '/syncfromflags:manual',
'/manualpeerlist:{0}'.format(' '.join(servers))]
reliable_cmd = ['W32tm', '/config', '/reliable:yes']
update_cmd = ['W32tm', '/config', '/update']
for cmd in server_cmd, reliable_cmd, update_cmd:
ret = __salt__['cmd.run'](cmd, python_shell=False)
if 'command completed successfully' not in ret:
return False
__salt__['service.restart'](service_name)
return 'command completed successfully' in ret
return True
def get_servers():
@ -60,8 +66,8 @@ def get_servers():
salt '*' ntp.get_servers
'''
cmd = 'w32tm /query /configuration'
lines = __salt__['cmd.run'](cmd).splitlines()
cmd = ['w32tm', '/query', '/configuration']
lines = __salt__['cmd.run'](cmd, python_shell=False).splitlines()
for line in lines:
try:
if 'NtpServer' in line:

View file

@ -304,7 +304,7 @@ $msi.GetType().InvokeMember('ProductsEx', 'GetProperty', $null, $msi, ('', 's-1-
| Write-host
'''.replace('\n', ' ') # make this a one-liner
ret = __salt__['cmd.run_all'](ps, shell='powershell')
ret = __salt__['cmd.run_all'](ps, shell='powershell', python_shell=True)
# sometimes the powershell reflection fails on a single product,
# giving us a non-zero return code AND useful output. Ignore RC
# and just try to process stdout, which should empty if the cmd
@ -555,12 +555,14 @@ def install(name=None, refresh=False, pkgs=None, saltenv='base', **kwargs):
cached_pkg = cached_pkg.replace('/', '\\')
msiexec = pkginfo[version_num].get('msiexec')
install_flags = '{0} {1}'.format(pkginfo[version_num]['install_flags'], options and options.get('extra_install_flags') or "")
cmd = '{msiexec}"{cached_pkg}" {install_flags}'.format(
msiexec='msiexec /i ' if msiexec else '',
cached_pkg=cached_pkg,
install_flags=install_flags
)
__salt__['cmd.run'](cmd, output_loglevel='trace')
cmd = []
if msiexec:
cmd.extend('msiexec', '/i')
cmd.append(cached_pkg)
cmd.extend(install_flags.split())
__salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
__context__.pop('pkg.list_pkgs', None)
new = list_pkgs()
@ -652,11 +654,19 @@ def remove(name=None, pkgs=None, version=None, extra_uninstall_flags=None, **kwa
if not os.path.exists(os.path.expandvars(cached_pkg)) \
and '(x86)' in cached_pkg:
cached_pkg = cached_pkg.replace('(x86)', '')
cmd = '"' + str(os.path.expandvars(
cached_pkg)) + '"' + str(pkginfo[version].get('uninstall_flags', '') + " " + (extra_uninstall_flags or ''))
expanded_cached_pkg = str(os.path.expandvars(cached_pkg))
uninstall_flags = str(pkginfo[version].get('uninstall_flags', ''))
cmd = []
if pkginfo[version].get('msiexec'):
cmd = 'msiexec /x ' + cmd
__salt__['cmd.run'](cmd, output_loglevel='trace')
cmd.extend(['msiexec', '/x'])
cmd.append(expanded_cached_pkg)
cmd.extend(uninstall_flags.split())
if extra_uninstall_flags:
cmd.extend(str(extra_uninstall_flags).split())
__salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
__context__.pop('pkg.list_pkgs', None)
new = list_pkgs()

View file

@ -11,6 +11,10 @@ import logging
from subprocess import list2cmdline
from salt.ext.six.moves import zip
from salt.ext.six.moves import range
try:
from shlex import quote as _cmd_quote # pylint: disable=E0611
except ImportError:
from pipes import quote as _cmd_quote
log = logging.getLogger(__name__)
@ -41,7 +45,9 @@ def has_powershell():
salt '*' service.has_powershell
'''
return 'powershell' in __salt__['cmd.run']('where powershell')
return 'powershell' in __salt__['cmd.run'](
['where', 'powershell'], python_shell=False
)
def get_enabled():
@ -144,8 +150,8 @@ def get_service_name(*args):
ret = {}
services = []
display_names = []
cmd = list2cmdline(['sc', 'query', 'type=', 'service', 'state=', 'all', 'bufsize=', str(BUFFSIZE)])
lines = __salt__['cmd.run'](cmd).splitlines()
cmd = ['sc', 'query', 'type=', 'service', 'state=', 'all', 'bufsize=', str(BUFFSIZE)]
lines = __salt__['cmd.run'](cmd, python_shell=False).splitlines()
for line in lines:
if 'SERVICE_NAME:' in line:
comps = line.split(':', 1)
@ -179,8 +185,8 @@ def start(name):
salt '*' service.start <service name>
'''
cmd = list2cmdline(['net', 'start', name])
return not __salt__['cmd.retcode'](cmd)
cmd = ['net', 'start', name]
return not __salt__['cmd.retcode'](cmd, python_shell=False)
def stop(name):
@ -197,8 +203,8 @@ def stop(name):
# up if the service takes too long to stop with a misleading
# "service could not be stopped" message and RC 0.
cmd = list2cmdline(['net', 'stop', name])
res = __salt__['cmd.run'](cmd)
cmd = ['net', 'stop', name]
res = __salt__['cmd.run'](cmd, python_shell=False)
if 'service was stopped' in res:
return True
@ -225,8 +231,8 @@ def restart(name):
salt '*' service.restart <service name>
'''
if has_powershell():
cmd = 'Restart-Service {0}'.format(name)
return not __salt__['cmd.retcode'](cmd, shell='powershell')
cmd = 'Restart-Service {0}'.format(_cmd_quote(name))
return not __salt__['cmd.retcode'](cmd, shell='powershell', python_shell=True)
return stop(name) and start(name)
@ -242,8 +248,8 @@ def status(name, sig=None):
salt '*' service.status <service name> [service signature]
'''
cmd = list2cmdline(['sc', 'query', name])
statuses = __salt__['cmd.run'](cmd).splitlines()
cmd = ['sc', 'query', name]
statuses = __salt__['cmd.run'](cmd, python_shell=False).splitlines()
for line in statuses:
if 'RUNNING' in line:
return True
@ -262,8 +268,8 @@ def getsid(name):
salt '*' service.getsid <service name>
'''
cmd = list2cmdline(['sc', 'showsid', name])
lines = __salt__['cmd.run'](cmd).splitlines()
cmd = ['sc', 'showsid', name]
lines = __salt__['cmd.run'](cmd, python_shell=False).splitlines()
for line in lines:
if 'SERVICE SID:' in line:
comps = line.split(':', 1)
@ -283,8 +289,8 @@ def enable(name, **kwargs):
salt '*' service.enable <service name>
'''
cmd = list2cmdline(['sc', 'config', name, 'start=', 'auto'])
return not __salt__['cmd.retcode'](cmd)
cmd = ['sc', 'config', name, 'start=', 'auto']
return not __salt__['cmd.retcode'](cmd, python_shell=False)
def disable(name, **kwargs):
@ -297,8 +303,8 @@ def disable(name, **kwargs):
salt '*' service.disable <service name>
'''
cmd = list2cmdline(['sc', 'config', name, 'start=', 'demand'])
return not __salt__['cmd.retcode'](cmd)
cmd = ['sc', 'config', name, 'start=', 'demand']
return not __salt__['cmd.retcode'](cmd, python_shell=False)
def enabled(name, **kwargs):

View file

@ -52,7 +52,7 @@ def set_password(name, password):
salt '*' shadow.set_password root mysecretpassword
'''
cmd = 'net user {0} {1}'.format(name, password)
ret = __salt__['cmd.run_all'](cmd)
cmd = ['net', 'user', name, password]
ret = __salt__['cmd.run_all'](cmd, python_shell=False)
return not ret['retcode']

View file

@ -7,6 +7,11 @@ from __future__ import absolute_import
# Import python libs
import logging
import re
import datetime
try:
from shlex import quote as _cmd_quote # pylint: disable=E0611
except ImportError:
from pipes import quote as _cmd_quote
# Import salt libs
import salt.utils
@ -50,8 +55,8 @@ def init(runlevel):
salt '*' system.init 3
'''
#cmd = 'init {0}'.format(runlevel)
#ret = __salt__['cmd.run'](cmd)
#cmd = ['init', runlevel]
#ret = __salt__['cmd.run'](cmd, python_shell=False)
#return ret
# TODO: Create a mapping of runlevels to
@ -83,8 +88,8 @@ def reboot(timeout=5):
salt '*' system.reboot
'''
cmd = 'shutdown /r /t {0}'.format(timeout)
ret = __salt__['cmd.run'](cmd)
cmd = ['shutdown', '/r', '/t', '{0}'.format(timeout)]
ret = __salt__['cmd.run'](cmd, python_shell=False)
return ret
@ -98,8 +103,8 @@ def shutdown(timeout=5):
salt '*' system.shutdown
'''
cmd = 'shutdown /s /t {0}'.format(timeout)
ret = __salt__['cmd.run'](cmd)
cmd = ['shutdown', '/s', '/t', '{0}'.format(timeout)]
ret = __salt__['cmd.run'](cmd, python_shell=False)
return ret
@ -113,8 +118,8 @@ def shutdown_hard():
salt '*' system.shutdown_hard
'''
cmd = 'shutdown /p /f'
ret = __salt__['cmd.run'](cmd)
cmd = ['shutdown', '/p', '/f']
ret = __salt__['cmd.run'](cmd, python_shell=False)
return ret
@ -129,9 +134,9 @@ def set_computer_name(name):
salt 'minion-id' system.set_computer_name 'DavesComputer'
'''
cmd = ('wmic computersystem where name="%COMPUTERNAME%"'
' call rename name="{0}"')
' call rename name="{0}"'.format(name))
log.debug('Attempting to change computer name. Cmd is: {0}'.format(cmd))
ret = __salt__['cmd.run'](cmd.format(name))
ret = __salt__['cmd.run'](cmd, python_shell=True)
if 'ReturnValue = 0;' in ret:
ret = {'Computer Name': {'Current': get_computer_name()}}
pending = get_pending_computer_name()
@ -156,9 +161,10 @@ def get_pending_computer_name():
salt 'minion-id' system.get_pending_computer_name
'''
current = get_computer_name()
cmd = ('reg query HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control'
'\\ComputerName\\ComputerName /v ComputerName')
output = __salt__['cmd.run'](cmd)
cmd = ['reg', 'query',
'HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ComputerName',
'/v', 'ComputerName']
output = __salt__['cmd.run'](cmd, python_shell=False)
pending = None
for line in output.splitlines():
try:
@ -188,8 +194,8 @@ def get_computer_name():
salt 'minion-id' system.get_computer_name
'''
cmd = 'net config server'
lines = __salt__['cmd.run'](cmd).splitlines()
cmd = ['net', 'config', 'server']
lines = __salt__['cmd.run'](cmd, python_shell=False).splitlines()
for line in lines:
if 'Server Name' in line:
_, srv_name = line.split('Server Name', 1)
@ -207,8 +213,8 @@ def set_computer_desc(desc):
salt 'minion-id' system.set_computer_desc 'This computer belongs to Dave!'
'''
cmd = u'net config server /srvcomment:"{0}"'.format(salt.utils.sdecode(desc))
__salt__['cmd.run'](cmd)
cmd = ['net', 'config', 'server', u'/srvcomment:{0}'.format(salt.utils.sdecode(desc))]
__salt__['cmd.run'](cmd, python_shell=False)
return {'Computer Description': get_computer_desc()}
set_computer_description = set_computer_desc
@ -224,8 +230,8 @@ def get_computer_desc():
salt 'minion-id' system.get_computer_desc
'''
cmd = 'net config server'
lines = __salt__['cmd.run'](cmd).splitlines()
cmd = ['net', 'config', 'server']
lines = __salt__['cmd.run'](cmd, python_shell=False).splitlines()
for line in lines:
if 'Server Comment' in line:
_, desc = line.split('Server Comment', 1)
@ -247,12 +253,12 @@ def join_domain(
domain
The domain to which the computer should be joined, e.g.
`my-company.com`
``my-company.com``
username
Username of an account which is authorized to join computers to the
specified domain. Need to be either fully qualified like
`user@domain.tld` or simply `user`
``user@domain.tld`` or simply ``user``
password
Password of the specified user
@ -260,19 +266,19 @@ def join_domain(
account_ou : None
The DN of the OU below which the account for this computer should be
created when joining the domain, e.g.
`ou=computers,ou=departm_432,dc=my-company,dc=com`
``ou=computers,ou=departm_432,dc=my-company,dc=com``
account_exists : False
Needs to be set to `True` to allow re-using an existing account
Needs to be set to ``True`` to allow re-using an existing account
CLI Example:
.. code-block:: bash
salt 'minion-id' system.join_domain domain='domain.tld' \
username='joinuser' password='joinpassword' \
account_ou='ou=clients,ou=org,dc=domain,dc=tld' \
account_exists=False
salt 'minion-id' system.join_domain domain='domain.tld' \\
username='joinuser' password='joinpassword' \\
account_ou='ou=clients,ou=org,dc=domain,dc=tld' \\
account_exists=False
'''
if '@' not in username:
@ -288,8 +294,12 @@ def join_domain(
join_options = 1
cmd = ('wmic /interactive:off ComputerSystem Where '
'name="%computername%" call JoinDomainOrWorkgroup FJoinOptions={0} '
'Name="{1}" UserName="{2}" Password="{3}"'
).format(join_options, domain, username, password)
'Name={1} UserName={2} Password={3}'
).format(
join_options,
_cmd_quote(domain),
_cmd_quote(username),
_cmd_quote(password))
if account_ou:
# contrary to RFC#2253, 2.1, 'wmic' requires a ; as a RDN separator
# for the DN
@ -297,7 +307,7 @@ def join_domain(
add_ou = ' AccountOU="{0}"'.format(account_ou)
cmd = cmd + add_ou
ret = __salt__['cmd.run'](cmd)
ret = __salt__['cmd.run'](cmd, python_shell=True)
if 'ReturnValue = 0;' in ret:
return {'Domain': domain}
return_values = {
@ -317,6 +327,45 @@ def join_domain(
return False
def _validate_datetime(newdatetime, valid_formats):
'''
Validate `newdatetime` against list of date/time formats understood by
windows.
'''
for dt_format in valid_formats:
try:
datetime.datetime.strptime(newdatetime, dt_format)
return True
except ValueError:
continue
return False
def _validate_time(newtime):
'''
Validate `newtime` against list of time formats understood by windows.
'''
valid_time_formats = [
'%I:%M:%S %p',
'%I:%M %p',
'%H:%M:%S',
'%H:%M'
]
return _validate_datetime(newtime, valid_time_formats)
def _validate_date(newdate):
'''
Validate `newdate` against list of date formats understood by windows.
'''
valid_date_formats = [
'%Y-%m-%d',
'%m/%d/%y',
'%y/%m/%d'
]
return _validate_datetime(newdate, valid_date_formats)
def get_system_time():
'''
Get the Windows system time
@ -328,7 +377,7 @@ def get_system_time():
salt '*' system.get_system_time
'''
cmd = 'time /T'
return __salt__['cmd.run'](cmd)
return __salt__['cmd.run'](cmd, python_shell=True)
def set_system_time(newtime):
@ -341,8 +390,10 @@ def set_system_time(newtime):
salt '*' system.set_system_time '11:31:15 AM'
'''
if not _validate_time(newtime):
return False
cmd = 'time {0}'.format(newtime)
return not __salt__['cmd.retcode'](cmd)
return not __salt__['cmd.retcode'](cmd, python_shell=True)
def get_system_date():
@ -356,7 +407,7 @@ def get_system_date():
salt '*' system.get_system_date
'''
cmd = 'date /T'
return __salt__['cmd.run'](cmd)
return __salt__['cmd.run'](cmd, python_shell=True)
def set_system_date(newdate):
@ -369,8 +420,10 @@ def set_system_date(newdate):
salt '*' system.set_system_date '03-28-13'
'''
if not _validate_date(newdate):
return False
cmd = 'date {0}'.format(newdate)
return not __salt__['cmd.retcode'](cmd)
return not __salt__['cmd.retcode'](cmd, python_shell=True)
def start_time_service():

View file

@ -472,7 +472,7 @@ def get_zone():
salt '*' timezone.get_zone
'''
winzone = __salt__['cmd.run']('tzutil /g')
winzone = __salt__['cmd.run'](['tzutil', '/g'], python_shell=False)
for key in LINTOWIN:
if LINTOWIN[key] == winzone:
return key
@ -491,9 +491,9 @@ def get_offset():
salt '*' timezone.get_offset
'''
string = False
zone = __salt__['cmd.run']('tzutil /g')
zone = __salt__['cmd.run'](['tzutil', '/g'], python_shell=False)
prev = ''
for line in __salt__['cmd.run']('tzutil /l').splitlines():
for line in __salt__['cmd.run'](['tzutil', '/l'], python_shell=False).splitlines():
if zone == line:
string = prev
break
@ -540,7 +540,8 @@ def set_zone(timezone):
salt '*' timezone.set_zone 'America/Denver'
'''
return __salt__['cmd.retcode']('tzutil /s "{0}"'.format(LINTOWIN[timezone])) == 0
cmd = ['tzutil', '/s', LINTOWIN[timezone]]
return __salt__['cmd.retcode'](cmd, python_shell=False) == 0
def zone_compare(timezone):
@ -555,7 +556,8 @@ def zone_compare(timezone):
salt '*' timezone.zone_compare 'America/Denver'
'''
return __salt__['cmd.run']('tzutil /g') == LINTOWIN[timezone]
cmd = ['tzutil', '/g']
return __salt__['cmd.run'](cmd, python_shell=False) == LINTOWIN[timezone]
def get_hwclock():

View file

@ -114,7 +114,25 @@ def mounted(name,
active = __salt__['mount.active'](extended=True)
real_name = os.path.realpath(name)
if device.startswith('/'):
real_device = os.path.realpath(device)
if 'bind' in opts and real_name in active:
_device = device
if active[real_name]['device'].startswith('/'):
# Find the device that the bind really points at.
while True:
if _device in active:
_real_device = active[_device]['device']
opts = list(set(opts + active[_device]['opts'] + active[_device]['superopts']))
active[real_name]['opts'].append('bind')
break
_device = os.path.dirname(_device)
real_device = _real_device
else:
# Remote file systems act differently.
opts = list(set(opts + active[_device]['opts'] + active[_device]['superopts']))
active[real_name]['opts'].append('bind')
real_device = active[real_name]['device']
else:
real_device = os.path.realpath(device)
elif device.upper().startswith('UUID='):
real_device = device.split('=')[1].strip('"').lower()
else:
@ -166,14 +184,14 @@ def mounted(name,
if opt not in active[real_name]['opts'] and opt not in active[real_name]['superopts'] and opt not in mount_invisible_options:
if __opts__['test']:
ret['result'] = None
ret['comment'] = "Remount would be forced because options changed"
ret['comment'] = "Remount would be forced because options ({0}) changed".format(opt)
return ret
else:
# nfs requires umounting and mounting if options change
# add others to list that require similiar functionality
if fstype in ['nfs']:
ret['changes']['umount'] = "Forced unmount and mount because " \
+ "options changed"
+ "options ({0}) changed".format(opt)
unmount_result = __salt__['mount.umount'](real_name)
if unmount_result is True:
mount_result = __salt__['mount.mount'](real_name, device, mkmnt=mkmnt, fstype=fstype, opts=opts)
@ -182,7 +200,7 @@ def mounted(name,
raise SaltInvocationError('Unable to unmount {0}: {1}.'.format(real_name, unmount_result))
else:
ret['changes']['umount'] = "Forced remount because " \
+ "options changed"
+ "options ({0}) changed".format(opt)
remount_result = __salt__['mount.remount'](real_name, device, mkmnt=mkmnt, fstype=fstype, opts=opts)
ret['result'] = remount_result
# Cleanup after the remount, so we

View file

@ -1,123 +0,0 @@
# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Mike Place <mp@saltstack.com`
Tests to ensure that the file permissions are set correctly when
importing from the git repo.
'''
# Import python libs
import os
import stat
import pprint
# Import salt testing libs
from salttesting import TestCase, skipIf
from salttesting.helpers import ensure_in_syspath
ensure_in_syspath('..')
from integration import CODE_DIR
EXEMPT_DIRS = []
EXEMPT_FILES = [
'debian/rules',
'doc/.scripts/compile-translation-catalogs',
'doc/.scripts/download-translation-catalog',
'doc/.scripts/setup-transifex-config',
'doc/.scripts/update-transifex-source-translations',
'pkg/arch/Makefile',
'pkg/arch/PKGBUILD',
'pkg/arch/PKGBUILD-git',
'pkg/arch/PKGBUILD-local',
'pkg/arch/git/PKGBUILD',
'pkg/rpm/build.py',
'pkg/rpm/salt-master',
'pkg/rpm/salt-minion',
'pkg/rpm/salt-syndic',
'pkg/shar/build_shar.sh',
'pkg/smartos/esky/install.sh',
'salt/cloud/deploy/bootstrap-salt.sh',
'salt/templates/git/ssh-id-wrapper',
'salt/templates/lxc/salt_tarball',
'scripts/salt',
'scripts/salt-call',
'scripts/salt-cloud',
'scripts/salt-cp',
'scripts/salt-key',
'scripts/salt-master',
'scripts/salt-minion',
'scripts/salt-run',
'scripts/salt-ssh',
'scripts/salt-syndic',
'setup.py',
'tests/integration/mockbin/su',
'tests/runtests.py',
'tests/saltsh.py',
]
IGNORE_PATHS = [
'.git',
'.wti',
'build',
'dist',
'salt.egg-info',
'.ropeproject',
]
@skipIf(True, 'Need to adjust perms')
class GitPermTestCase(TestCase):
def test_perms(self):
suspect_entries = []
for root, dirnames, filenames in os.walk(CODE_DIR, topdown=True):
for dirname in dirnames:
entry = os.path.join(root, dirname)
if entry in IGNORE_PATHS:
continue
skip_entry = False
for ignore_path in IGNORE_PATHS:
if entry.startswith(ignore_path):
skip_entry = True
break
if skip_entry:
continue
fn_mode = stat.S_IMODE(os.stat(entry).st_mode)
if fn_mode != 493 and entry not in EXEMPT_DIRS: # In octal! 493 == 0755
suspect_entries.append(entry)
for filename in filenames:
entry = os.path.join(root, filename)
if entry in IGNORE_PATHS:
continue
skip_entry = False
for ignore_path in IGNORE_PATHS:
if entry.startswith(ignore_path):
skip_entry = True
break
if skip_entry:
continue
fn_mode = stat.S_IMODE(os.stat(entry).st_mode)
if fn_mode != 420 and entry not in EXEMPT_FILES: # In octal! 420 == 0644
suspect_entries.append(entry)
try:
self.assertEqual(suspect_entries, [])
except AssertionError:
self.fail(
'Found file(s) with incorrect permissions:\n{0}'.format(
pprint.pformat(sorted(suspect_entries))
)
)
if __name__ == '__main__':
from integration import run_tests
run_tests(GitPermTestCase, needs_daemon=False)