#!${buildout:executable} equeue_database = '${equeue:database}' equeue_lockfile = '${equeue:lockfile}' takeover_script = '${resiliency-takeover-script:wrapper-takeover}' import cgi import cgitb import datetime import gdbm import os import shutil import subprocess import sys import tempfile if os.path.exists('resilient_software_release_information.py'): from resilient_software_release_information import main as resilient_main else: resilient_main = lambda: {} cgitb.enable() def getLatestBackupDate(): """ Get the date of the latest successful backup. """ # Create a copy of the db (locked by equeue process) temporary_directory = tempfile.mkdtemp() equeue_database_copy = os.path.join(temporary_directory, 'equeue.db') shutil.copyfile(equeue_database, equeue_database_copy) db = gdbm.open(equeue_database_copy) # Usually, there is only one callback (so only one key # in the db), but if there are several: # Take the "oldest" one (oldest value). if not db.keys(): result = False else: last_backup = db[db.keys()[0]] for callback in db.keys(): timestamp = float(db[callback]) if timestamp < last_backup: last_backup = timestamp result = datetime.datetime.fromtimestamp(last_backup) db.close() shutil.rmtree(temporary_directory) return result def isBackupInProgress(): """ Check if backup is in progress (importer script is running) by checking if equeue lockfile exists. """ # XXX: check if file is valid return os.path.exists(equeue_lockfile) def getInformationFromSoftwareRelease(): result = resilient_main() if isinstance(result, dict): return result else: return {'Custom Information': 'Error, received information is malformed'} def getSoftwareReleaseInformationFormatted(): result_string = "" for key, value in getInformationFromSoftwareRelease().items(): result_string += "<p><b>%s:</b> %s</p>" % (key, value) return result_string latest_backup_date = getLatestBackupDate() if latest_backup_date == False: latest_backup_message = "No backup downloaded yet, takeover should not happen now." else: latest_backup_message = latest_backup_date.strftime('%Y-%m-%d %H:%M:%S') print "Content-Type: text/html" print form = cgi.FieldStorage() if "password" not in form: print """<html> <body> <h1>This is takeover web interface.</h1> <p>Calling takeover will stop and freeze the current main instance, and make this clone instance the new main instance, replacing the old one.</p> <p><font size=\"+2\"><b>Warning: submit the form only if you understand what you are doing.</b></font></p> <p>Note: the password asked here can be found within the parameters of your SlapOS instance page.</p> <hr /> <p><b>Last valid backup:</b> %s</p> <p><b>Importer script(s) of backup in progress:</b> %s</p> <p><b>Backup Signature:</b> <a href='${resilient-web-takeover-cgi-script:proof-signature-url}'>${resilient-web-takeover-cgi-script:proof-signature-url}</a></b></p> %s <form action="/"> Password: <input type="text" name="password"> <input type="submit" value="Take over" style="background: red;"> </form> </body> </html>""" % (latest_backup_message, isBackupInProgress(), getSoftwareReleaseInformationFormatted()) sys.exit(0) if form['password'].value != '${:password}': print "<H1>Error</H1>" print "Password is invalid." sys.exit(1) # XXX hardcoded location result = subprocess.check_output([takeover_script], stderr=subprocess.STDOUT) print 'Success.' print '<pre>%s</pre>' % result