diff --git a/handyrep/daemon/config.py b/handyrep/daemon/config.py index 1ac0afa..303a4f1 100644 --- a/handyrep/daemon/config.py +++ b/handyrep/daemon/config.py @@ -1,3 +1,4 @@ import os -os.environ['HANDYREP_CONFIG'] = '/srv/handyrep//handyrep/handyrep.conf' \ No newline at end of file +if not os.environ.has_key('HANDYREP_CONFIG'): + os.environ['HANDYREP_CONFIG'] = '/srv/handyrep//handyrep/handyrep.conf' diff --git a/handyrep/handyrep.py b/handyrep/handyrep.py index 0beb287..ff764db 100644 --- a/handyrep/handyrep.py +++ b/handyrep/handyrep.py @@ -1929,7 +1929,8 @@ def test_ssh_newhost(self, hostname, ssh_key, ssh_user ): command = self.conf["handyrep"]["test_ssh_command"] testit = run(command, warn_only=True, quiet=True) except Exception as ex: - print exstr(ex) + self.log("SSH","Unable to ssh to host %s" % hostname,True) + #print exstr(ex) return False result = testit.succeeded diff --git a/handyrep/hdaemon.py b/handyrep/hdaemon.py index 98b7b4a..8f7f851 100644 --- a/handyrep/hdaemon.py +++ b/handyrep/hdaemon.py @@ -85,13 +85,13 @@ def run_periodic(func): print func, "exiting with return", result +def start(): + startup() -startup() - -for func_name in PERIODIC.keys(): - t = Thread(target=run_periodic, args=(func_name,) ) - t.daemon = True - t.start() + for func_name in PERIODIC.keys(): + t = Thread(target=run_periodic, args=(func_name,) ) + t.daemon = True + t.start() if __name__ == "__main__": app.run(host="0.0.0.0") diff --git a/handyrep/hdaemon.wsgi b/handyrep/hdaemon.wsgi index 93e1b40..c34ac66 100644 --- a/handyrep/hdaemon.wsgi +++ b/handyrep/hdaemon.wsgi @@ -1,2 +1,41 @@ -from hdaemon import app as application +import hdaemon +import os + +class ReverseProxied(object): + '''Wrap the application in this middleware and configure the + front-end server to add these headers, to let you quietly bind + this to a URL other than / and to an HTTP scheme that is + different than what is used locally. + + In nginx: + location /myprefix { + proxy_pass http://192.168.0.1:5001; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Scheme $scheme; + proxy_set_header X-Script-Name /myprefix; + } + + :param app: the hdaemon module so we can get the app and start the daemon + ''' + def __init__(self, hd): + self.hdaemon = hdaemon + + def __call__(self, environ, start_response): + script_name = environ.get('HTTP_X_SCRIPT_NAME', '') + if script_name: + environ['SCRIPT_NAME'] = script_name + path_info = environ['PATH_INFO'] + if path_info.startswith(script_name): + environ['PATH_INFO'] = path_info[len(script_name):] + + scheme = environ.get('HTTP_X_SCHEME', '') + if scheme: + environ['wsgi.url_scheme'] = scheme + + os.environ['HANDYREP_CONFIG'] = environ['HANDYREP_CONFIG'] + self.hdaemon.start() + return self.hdaemon.app(environ, start_response) + +application = ReverseProxied(hdaemon) diff --git a/handyrep/plugins/handyrepplugin.py b/handyrep/plugins/handyrepplugin.py index 5389506..4e12e88 100644 --- a/handyrep/plugins/handyrepplugin.py +++ b/handyrep/plugins/handyrepplugin.py @@ -15,6 +15,7 @@ from subprocess import call import re import threading +import traceback class HandyRepPlugin(object): @@ -160,6 +161,7 @@ def push_template(self, servername, templatename, destination, template_params, if new_owner: sudo("chown %s %s" % (new_owner, destination,), quiet=True) except: + self.log('PLUGIN','could not push template %s to server %s - %s' % (templatename,servername, traceback.format_exc()),True) retdict = return_dict(False, "could not push template %s to server %s" % (templatename, servername,)) else: retdict = return_dict(True, "pushed template") @@ -371,4 +373,4 @@ def execute_it(self, cur, statement, params=[]): def exstr(self, errorobj): return exstr(errorobj) - \ No newline at end of file + diff --git a/handyrep/plugins/multi_pgbouncer.py b/handyrep/plugins/multi_pgbouncer.py index b9ca456..26e51df 100644 --- a/handyrep/plugins/multi_pgbouncer.py +++ b/handyrep/plugins/multi_pgbouncer.py @@ -108,8 +108,12 @@ def bouncer_list(self): def test(self): #check that we have all config variables required - if self.failed( self.test_plugin_conf("multi_pgbouncer","pgbouncerbin","template","owner","config_location","database_list","readonly_suffix","all_replicas")): + if self.failed( self.test_plugin_conf("multi_pgbouncer","pgbouncerbin","template","owner","config_location","readonly_suffix","all_replicas")): return self.rd(False, "multi-pgbouncer failover is not configured" ) + + if self.failed( self.test_plugin_conf("multi_pgbouncer","database_list") or self.test_plugin_conf("multi_pgbouncer","databases")): + return self.rd(False, "multi-pgbouncer failover has no configured databases" ) + #check that we can connect to the pgbouncer servers blist = self.bouncer_list() if len(blist) == 0: @@ -157,23 +161,32 @@ def dbconnect_list(self, master): # servers for pgbouncer # build master string first myconf = self.conf["plugins"]["multi_pgbouncer"] - dblist = myconf["database_list"] + + dbconfig = {} + if myconf["databases"]: + dbconfig.update(myconf["databases"]) + + if myconf["database_list"]: + for dbname in myconf["database_list"]: + dbconfig[dbname] = myconf["extra_connect_param"] + # add in the handyrep db if the user has forgotten it - if self.conf["handyrep"]["handyrep_db"] not in dblist: - dblist.append(self.conf["handyrep"]["handyrep_db"]) - constr = self.dbconnect_line(dblist, self.servers[master]["hostname"], self.servers[master]["port"], "", myconf["extra_connect_param"]) + if not dbconfig.has_key(self.conf["handyrep"]["handyrep_db"]): + dbconfig[self.conf["handyrep"]["handyrep_db"]] = myconf["extra_connect_param"] + + constr = self.dbconnect_line(dbconfig, self.servers[master]["hostname"], self.servers[master]["port"], "") replicas = self.sorted_replicas() if self.is_true(myconf["all_replicas"]): #if we're doing all replicas, we need to put them in as _ro0, _ro1, etc. # if there's no replicas, set ro1 to go to the master: if len(replicas) == 0 or (len(replicas) == 1 and master in replicas): rsuff = "%s%d" % (myconf["readonly_suffix"],1,) - constr += self.dbconnect_line(myconf["database_list"], self.servers[master]["hostname"], self.servers[master]["port"], rsuff, myconf["extra_connect_param"]) + constr += self.dbconnect_line(dbconfig, self.servers[master]["hostname"], self.servers[master]["port"], rsuff) else: for rep in replicas: if not rep == master: rsuff = "%s%d" % (myconf["readonly_suffix"],repno,) - constr += self.dbconnect_line(myconf["database_list"], self.servers[rep]["hostname"], self.servers[rep]["port"], rsuff, myconf["extra_connect_param"]) + constr += self.dbconnect_line(dbconfig, self.servers[rep]["hostname"], self.servers[rep]["port"], rsuff) repno += 1 else: # only one readonly replica, setting it up with _ro @@ -183,23 +196,17 @@ def dbconnect_list(self, master): replicas.pop(0) if len(replicas) > 0: - constr += self.dbconnect_line(myconf["database_list"], self.servers[replicas[0]]["hostname"], self.servers[replicas[0]]["port"], myconf["readonly_suffix"], myconf["extra_connect_param"]) + constr += self.dbconnect_line(dbconfig, self.servers[replicas[0]]["hostname"], self.servers[replicas[0]]["port"], myconf["readonly_suffix"]) else: # if no replicas, read-only connections should go to the master - constr += self.dbconnect_line(myconf["database_list"], self.servers[master]["hostname"], self.servers[master]["port"], myconf["readonly_suffix"], myconf["extra_connect_param"]) + constr += self.dbconnect_line(dbconfig, self.servers[master]["hostname"], self.servers[master]["port"], myconf["readonly_suffix"]) return constr - def dbconnect_line(self, database_list, hostname, portno, suffix, extra): + def dbconnect_line(self, database_list, hostname, portno, suffix): confout = "" - if extra: - nex = extra - else: - nex = "" - for dbname in database_list: + for dbname,nex in database_list.items(): confout += "%s%s = dbname=%s host=%s port=%s %s \n" % (dbname, suffix, dbname, hostname, portno, nex,) return confout - - \ No newline at end of file diff --git a/handyrepGUI/GUI_app/templates/base.html b/handyrepGUI/GUI_app/templates/base.html index 01c9f99..33bd894 100755 --- a/handyrepGUI/GUI_app/templates/base.html +++ b/handyrepGUI/GUI_app/templates/base.html @@ -2,19 +2,19 @@ handyrepGUI<!--{% block title %}{% endblock %}--> - + -
logout
+
logout
- \ No newline at end of file + diff --git a/handyrepGUI/GUI_app/templates/base2.html b/handyrepGUI/GUI_app/templates/base2.html index cdd8ad9..0882691 100644 --- a/handyrepGUI/GUI_app/templates/base2.html +++ b/handyrepGUI/GUI_app/templates/base2.html @@ -11,7 +11,7 @@ Enabled -

cluster

+

cluster

{{ status.cluster.get("status") }}

{{ status.cluster.get("status_message") }}

{{ status.cluster.get("status_ts") }}

@@ -20,7 +20,7 @@ {% for key, value in status.get("servers")|dictsort %} -

{{key}}

+

{{key}}

{{value.get("status")}}

{{value.get("status_message")}}

{{value.get("status_ts")}}

@@ -31,4 +31,4 @@ {% block eachcontent %}{% endblock %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/handyrepGUI/GUI_app/templates/index.html b/handyrepGUI/GUI_app/templates/index.html index 92a55b9..5e1d971 100644 --- a/handyrepGUI/GUI_app/templates/index.html +++ b/handyrepGUI/GUI_app/templates/index.html @@ -9,7 +9,7 @@

-

Cluster status is {{ status.get(category).get("status") }} because {{ status.get(category).get("status_message") }}. +

Cluster status is {{ status.get(category).get("status") }} because {{ status.get(category).get("status_message") }}. This was reported at {{ status.get(category).get("status_ts") }}

@@ -23,7 +23,7 @@