Added status.master capability for Windows

This fixes issue_21405, and allows Windows minions to auto-failover if configured
for multi-master mode and failover.
This commit is contained in:
Fred Reimer 2015-03-07 20:07:39 -05:00
parent e2f135a409
commit fa0953c50b
No known key found for this signature in database
GPG Key ID: CC615E6AD6D88E5E

View File

@ -7,8 +7,11 @@ These data can be useful for compiling into stats later.
- wmi
'''
import subprocess
import logging
import salt.utils
import salt.utils.event
from salt.utils.network import host_to_ip as _host_to_ip
log = logging.getLogger(__name__)
@ -94,3 +97,81 @@ def _get_process_owner(process):
log.warning('Error getting owner of process; PID=\'{0}\'; Error: {1}'
.format(process.ProcessId, error_code))
return owner
def master(master=None, connected=True):
'''
Fire an event if the minion gets disconnected from its master. This
function is meant to be run via a scheduled job from the minion. If
master_ip is an FQDN/Hostname, is must be resolvable to a valid IPv4
address.
CLI Example:
.. code-block:: bash
salt '*' status.master
'''
def _win_remotes_on(port):
'''
Windows specific helper function.
Returns set of ipv4 host addresses of remote established connections
on local or remote tcp port.
Parses output of shell 'netstat' to get connections
PS C:\> netstat -n -p TCP
Active Connections
Proto Local Address Foreign Address State
TCP 10.1.1.26:3389 10.1.1.1:4505 ESTABLISHED
TCP 10.1.1.26:56862 10.1.1.10:49155 TIME_WAIT
TCP 10.1.1.26:56868 169.254.169.254:80 CLOSE_WAIT
TCP 127.0.0.1:49197 127.0.0.1:49198 ESTABLISHED
TCP 127.0.0.1:49198 127.0.0.1:49197 ESTABLISHED
'''
remotes = set()
try:
data = subprocess.check_output(['netstat', '-n', '-p', 'TCP'])
except subprocess.CalledProcessError:
log.error('Failed netstat')
raise
lines = data.split('\n')
for line in lines:
if 'ESTABLISHED' not in line:
continue
chunks = line.split()
remote_host, remote_port = chunks[2].rsplit(':', 1)
if int(remote_port) != port:
continue
remotes.add(remote_host)
return remotes
# the default publishing port
port = 4505
master_ip = None
if __salt__['config.get']('publish_port') != '':
port = int(__salt__['config.get']('publish_port'))
# Check if we have FQDN/hostname defined as master
# address and try resolving it first. _remote_port_tcp
# only works with IP-addresses.
if master is not None:
tmp_ip = _host_to_ip(master)
if tmp_ip is not None:
master_ip = tmp_ip
ips = _win_remotes_on(port)
if connected:
if master_ip not in ips:
event = salt.utils.event.get_event('minion', opts=__opts__, listen=False)
event.fire_event({'master': master}, '__master_disconnected')
else:
if master_ip in ips:
event = salt.utils.event.get_event('minion', opts=__opts__, listen=False)
event.fire_event({'master': master}, '__master_connected')