Permalink
Browse files

Added basic authentication support

- Fixed issue when adding resource/stonith and crm_mon error occurs
- Added ability to get cluster status xml
- Bumped version to 0.9.5
  • Loading branch information...
1 parent 7887f49 commit 02d848ac53cf0a61563ae8b27aff7ef3966f0783 @feist feist committed Jun 11, 2012
Showing with 101 additions and 4 deletions.
  1. +23 −0 pcs/cluster.py
  2. +2 −0 pcs/resource.py
  3. +9 −0 pcs/status.py
  4. +11 −2 pcs/usage.py
  5. +56 −2 pcs/utils.py
View
@@ -25,6 +25,8 @@ def cluster_cmd(argv):
sync_nodes(utils.getNodesFromCorosyncConf(),utils.getCorosyncConf())
elif (sub_cmd == "gui-status"):
cluster_gui_status(argv)
+ elif (sub_cmd == "auth"):
+ cluster_auth(argv)
elif (sub_cmd == "start"):
start_cluster(argv)
elif (sub_cmd == "stop"):
@@ -57,6 +59,25 @@ def sync_nodes(nodes,config):
for node in nodes:
utils.setCorosyncConfig(node,config)
+def cluster_auth(argv):
+ if len(argv) == 0:
+ auth_nodes(utils.getNodesFromCorosyncConf())
+ else:
+ auth_nodes(argv)
+
+def auth_nodes(nodes):
+ for node in nodes:
+ status = utils.checkStatus(node)
+ if status[0] == 0:
+ print node + ": Already authorized"
+ elif status[0] == 3:
+ utils.updateToken(node)
+ print "%s: Authorized" % (node)
+ else:
+ print "Unable to communicate with %s" % (node)
+ exit(1)
+
+
# If no arguments get current cluster node status, otherwise get listed
# nodes status
def cluster_gui_status(argv):
@@ -71,6 +92,8 @@ def check_nodes(nodes):
status = utils.checkStatus(node)
if status[0] == 0:
print node + ": Online"
+ elif status[0] == 3:
+ print node + ": Unable to authenticate"
else:
print node + ": Offline"
View
@@ -65,6 +65,8 @@ def resource_create(ra_id, ra_type, ra_values, op_values):
output,retval = utils.run(args)
if retval != 0:
print "ERROR: Unable to create resource/fence device"
+ print output.split('\n')[0]
+ sys.exit(1)
# Update a resource, removing any args that are empty and adding/updating
# args that are not empty
View
@@ -25,6 +25,8 @@ def status_cmd(argv):
nodes_status(argv)
elif (sub_cmd == "actions"):
actions_status(argv)
+ elif (sub_cmd == "xml"):
+ xml_status()
else:
usage.status()
sys.exit(1)
@@ -144,3 +146,10 @@ def cluster_status(argv):
break
print "",line
+def xml_status():
+ (output, retval) = utils.run(["/usr/sbin/crm_mon", "-1", "-r", "-X"])
+
+ if (retval != 0):
+ print "Error running crm_mon, is pacemaker running?"
+ sys.exit(1)
+ print output
View
@@ -61,9 +61,15 @@ def cluster():
stop Stop corosync & pacemaker
startall Start corosync & pacemaker on all nodes
stopall Stop corosync & pacemaker on all nodes
- gui-status [node] [...]
+
+ gui-status [node] [...]
Get current status of pcs-gui on nodes specified, or on all nodes
- configure in corosync.conf if no nodes are specified
+ configured in corosync.conf if no nodes are specified
+
+ auth [node] [...]
+ Authenticate pcs to pcs-gui on nodes specified, or on all nodes
+ configured in corosync.conf if no nodes are specified (authorization
+ tokens are stored in ~/.pcs/token)
sync
Sync corosync configuration to all nodes found from current
@@ -199,4 +205,7 @@ def status():
status actions
View failed actions
+
+ status xml
+ View xml version of status (output from crm_mon -r -1 -X)
"""
View
@@ -5,6 +5,8 @@
import urllib,urllib2
from xml.dom.minidom import parseString
import re
+import getpass
+import json
# usefile & filename variables are set in pcs module
@@ -16,6 +18,44 @@ def checkStatus(node):
out = sendHTTPRequest(node, 'remote/status', None, False)
return out
+def updateToken(node):
+ username = raw_input(node + " username: ")
+ password = getpass.getpass(node + " password: ")
+ data = urllib.urlencode({'username':username, 'password':password})
+ out = sendHTTPRequest(node, 'remote/auth', data, False)
+ if out[0] != 0:
+ print "ERROR: Unable to connect to pcs-gui on %s" % node
+ print out
+ exit(1)
+ token = out[1]
+ if token == "":
+ print "ERROR: Username and/or password is incorrect"
+ exit(1)
+
+ tokens = readTokens()
+ tokens[node] = token
+ writeTokens(tokens)
+
+ return True
+
+# Returns a dictionary {'nodeA':'tokenA'}
+def readTokens():
+ tokenfile = os.path.expanduser("~/.pcs/tokens")
+ if (os.path.isfile(tokenfile) == False):
+ return {}
+ tokens = json.load(open(tokenfile))
+ return tokens
+
+# Takes a dictionary {'nodeA':'tokenA'}
+def writeTokens(tokens):
+ tokenfile = os.path.expanduser("~/.pcs/tokens")
+ if (os.path.isfile(tokenfile) == False):
+ if not os.path.exists(os.path.expanduser("~/.pcs")):
+ os.mkdir(os.path.expanduser("~/.pcs"),0700);
+ f = os.fdopen (os.open(tokenfile, os.O_WRONLY | os.O_CREAT, 0600), 'w')
+ f.write(json.dumps(tokens))
+ f.close()
+
# Set the corosync.conf file on the specified node
def setCorosyncConfig(node,config):
data = urllib.urlencode({'corosync_conf':config})
@@ -30,9 +70,17 @@ def stopCluster(node):
# Send an HTTP request to a node return a tuple with status, data
# If status is 0 then data contains server response
# Otherwise if non-zero then data contains error message
+# Returns a tuple (error, error message)
+# 0 = Success,
+# 1 = HTTP Error
+# 2 = No response,
+# 3 = Auth Error
def sendHTTPRequest(host, request, data = None, printResult = True):
url = 'http://' + host + ':2222/' + request
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor())
+ tokens = readTokens()
+ if host in tokens:
+ opener.addheaders.append(('Cookie', 'token='+tokens[host]))
urllib2.install_opener(opener)
try:
result = opener.open(url,data)
@@ -42,8 +90,14 @@ def sendHTTPRequest(host, request, data = None, printResult = True):
return (0,html)
except urllib2.HTTPError, e:
if printResult:
- print "Error connecting to %s - (HTTP error: %d)" % (host,e.code)
- return (1,"Error connecting to %s - (HTTP error: %d)" % (host,e.code))
+ if e.code == 401:
+ print "Unable to authenticate to %s - (HTTP error: %d)" % (host,e.code)
+ else:
+ print "Error connecting to %s - (HTTP error: %d)" % (host,e.code)
+ if e.code == 401:
+ return (3,"Unable to authenticate to %s - (HTTP error: %d)" % (host,e.code))
+ else:
+ return (1,"Error connecting to %s - (HTTP error: %d)" % (host,e.code))
except urllib2.URLError, e:
if printResult:
print "Unable to connect to %s (%s)" % (host, e.reason)

0 comments on commit 02d848a

Please sign in to comment.