This repository has been archived by the owner on May 1, 2020. It is now read-only.
forked from dwighthubbard/sshmap
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8ea9437
commit 9a8c022
Showing
2 changed files
with
204 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
#!/usr/bin/env python | ||
|
||
""" | ||
Copyright (c) 2012 Yahoo! Inc. All rights reserved. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. See accompanying LICENSE file. | ||
""" | ||
|
||
|
||
import sys | ||
import socket | ||
import json | ||
|
||
# Default socket filename | ||
socket_file = '/tmp/haproxy_socket' | ||
|
||
def get_haproxy_socket_filename(): | ||
socket_file=None | ||
# Open the haproxy config and see if we can find the socket file | ||
for line in open('/etc/haproxy/haproxy.cfg'): | ||
splitline=line.strip().split() | ||
if len(splitline) > 2 and splitline[0] == 'stats' and splitline[1] == 'socket': | ||
socket_file=splitline[2] | ||
break | ||
return socket_file | ||
|
||
def query_haproxy_socket(socket_file='/tmp/haproxy',command='show stat'): | ||
if not command.endswith('\n'): | ||
command=command+'\n' | ||
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) | ||
s.connect(socket_file) | ||
s.send(command) | ||
data="" | ||
d=s.recv(1024) | ||
while d: | ||
data=data+d | ||
d=s.recv(1024) | ||
#data = s.recv() | ||
s.close() | ||
return data | ||
|
||
def get_backends(vip,state='ALL'): | ||
hosts=[] | ||
for line in query_haproxy_socket(get_haproxy_socket_filename(),'show stat').split('\n'): | ||
if not line.startswith('#') and len(line.strip()): | ||
splitline=line.strip().split(',') | ||
if splitline[0]==vip and splitline[1] != 'BACKEND': | ||
if state.upper() == 'ALL' or (splitline[17]==state): | ||
hosts.append(splitline[1]) | ||
return hosts | ||
|
||
state='ALL' | ||
if len(sys.argv) > 2 and sys.argv[2].upper() in ['UP','DOWN']: | ||
state=sys.argv[2].upper() | ||
print json.dumps(get_backends(sys.argv[1],state),indent=4) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
#!/usr/bin/env python | ||
""" haproxy host plugin """ | ||
|
||
""" | ||
Copyright (c) 2012 Yahoo! Inc. All rights reserved. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. See accompanying LICENSE file. | ||
""" | ||
|
||
""" | ||
NOTE: | ||
This script is primarily intended as a proof of concept of adding a load | ||
balancer as the host IP address source. | ||
THEORY OF OPERATION: | ||
Since haproxy does not provide an externally accessible means of accessing | ||
the backend names and states for hosts it is proxying this module uses ssh | ||
to call a helper script on the haproxy server to get the information. | ||
USAGE: | ||
This plugin requires a signifcant amount of pre-configuration on the haproxy | ||
server in order to work. This requires a configuration change to enable | ||
the stats socket in haproxy, setting permissions, and copying the get_haproxy_phys | ||
script into place. | ||
The setup steps are: | ||
1. Enable the haproxy status socket, the script expects it to be /tmp/haproxy | ||
by adding: | ||
stats socket /tmp/haproxy | ||
to the global section of the /etc/haproxy/haproxy.cfg file | ||
2. Restart haproxy to create the socket | ||
3. Make sure the socket file is owned by the user that will be connecting | ||
to the haproxy server. | ||
4. Copy the get_haproxy_phys from the sshmap hostlists_plugins directory | ||
into the root of the home directory of the user that will be connecing | ||
to the haproxy server. | ||
5. Set up the user's ~/.ssh/authorized_keys file to allow access via ssh | ||
without password. | ||
""" | ||
import os | ||
import urllib2 | ||
import base64 | ||
import json | ||
import hostlists | ||
|
||
def name(): | ||
""" Name of plugins this plugin responds to """ | ||
return ['haproxy','haproxy_all','haproxy_up','haproxy_down'] | ||
|
||
def type(): | ||
""" Type of plugin this is """ | ||
return ['vip'] | ||
|
||
def server_setting(server='default',setting=None): | ||
if not setting: | ||
return None | ||
settings=hostlists.get_setting('haproxy_plugin') | ||
if not settings: | ||
return None | ||
if server in settings.keys(): | ||
if setting in settings[server].keys(): | ||
return settings[server][setting] | ||
return None | ||
|
||
def expand(value,name='haproxy',method=None): | ||
state='ALL' | ||
if name in ['haproxy_up']: | ||
state='UP' | ||
if name in ['haproxy_down']: | ||
state='DOWN' | ||
temp=value.split(':') | ||
if len(temp): | ||
haproxy=temp[0] | ||
backend=temp[1] | ||
else: | ||
return [] | ||
# Determine settings | ||
# the last setting that is found is the setting so we go | ||
# from most generic to least | ||
# first some reasonable hardwired defaults | ||
timeout=2 | ||
userid=None | ||
password=None | ||
# Next try and get setting defaults from the config file | ||
if server_setting('default','userid'): | ||
userid=server_setting('default','userid') | ||
if server_setting('default','password'): | ||
password=server_setting('default','password') | ||
if server_setting('default','timeout'): | ||
timeout=server_setting('default','timeout') | ||
if haproxy and not method and server_setting(haproxy,'method'): | ||
method=server_setting(haproxy,'method') | ||
if not method and server_setting('default','method'): | ||
method=server_setting('default','method') | ||
# Finally try settings specific to the server | ||
if haproxy: | ||
if server_setting(haproxy,'userid'): | ||
userid=server_setting(haproxy,'userid') | ||
if server_setting(haproxy,'password'): | ||
password=server_setting(haproxy,'password') | ||
if server_setting(haproxy,'timeout'): | ||
timeout=server_setting(haproxy,'timeout') | ||
tmplist=[] | ||
if method == 'ssh': | ||
command='ssh "%s" ./get_haproxy_phys "%s" "%s"'% (haproxy,backend,state) | ||
try: | ||
hosts=json.loads(os.popen(command).read()) | ||
return hosts | ||
except: | ||
return [] | ||
else: | ||
url="http://%s/haproxy?stats;csv" % (haproxy) | ||
request = urllib2.Request(url) | ||
if userid and password: | ||
base64string = base64.encodestring('%s:%s' % (userid, password)).replace('\n', '') | ||
request.add_header("Authorization", "Basic %s" % base64string) | ||
try: | ||
result = urllib2.urlopen(request,timeout=timeout).read() | ||
for line in result.split('\n'): | ||
if not line.startswith('#') and len(line.strip()): | ||
splitline=line.strip().split(',') | ||
if splitline[0]==backend and splitline[1] != 'BACKEND': | ||
if state.upper() == 'ALL' or (splitline[17]==state): | ||
tmplist.append(splitline[1]) | ||
return tmplist | ||
except urllib2.URLError: | ||
return [] |