resilient-web-takeover-cgi-script.py.in 3.62 KB
Newer Older
1
#!${buildout:executable}
2 3

equeue_database = '${equeue:database}'
4
equeue_lockfile = '${equeue:lockfile}'
5
takeover_script = '${resiliency-takeover-script:wrapper-takeover}'
6

7
import atexit
8 9
import cgi
import cgitb
10 11
import datetime
import gdbm
12
import os
13
import shutil
14 15
import subprocess
import sys
16
import tempfile
17 18 19 20 21 22

if os.path.exists('resilient_software_release_information.py'):
  from resilient_software_release_information import main as resilient_main
else:
  resilient_main = lambda: {}

23 24
cgitb.enable()

25 26 27 28
def deleteTemporaryDirectory(path):
  if os.path.exists(path):
    shutil.rmtree(path)

29 30 31 32 33 34
def getLatestBackupDate():
  """
  Get the date of the latest successful backup.
  """
  # Create a copy of the db (locked by equeue process)
  temporary_directory = tempfile.mkdtemp()
35
  atexit.register(deleteTemporaryDirectory, temporary_directory)
36 37 38 39 40 41
  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).
42 43 44 45 46 47 48 49 50 51 52 53
  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
54

55 56 57 58 59 60 61 62
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)

63 64 65 66 67 68 69 70 71 72 73 74 75
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

76 77 78 79 80 81
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')

82
print "Content-Type: text/html"
83
print
84 85 86 87 88 89 90

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>
91
  <p><font size=\"+2\"><b>Warning: submit the form only if you understand what you are doing.</b></font></p>
92
  <p>Note: the password asked here can be found within the parameters of your SlapOS instance page.</p>
93 94 95
  <hr />
  <p><b>Last valid backup:</b> %s</p>
  <p><b>Importer script(s) of backup in progress:</b> %s</p>
96
  <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>
97
  %s
98 99 100 101 102
  <form action="/">
    Password: <input type="text" name="password">
    <input type="submit" value="Take over" style="background: red;">
  </form>
</body>
103
</html>""" % (latest_backup_message, isBackupInProgress(), getSoftwareReleaseInformationFormatted())
104 105 106 107 108 109 110 111
  sys.exit(0)

if form['password'].value != '${:password}':
  print "<H1>Error</H1>"
  print "Password is invalid."
  sys.exit(1)

# XXX hardcoded location
112
result = subprocess.check_output([takeover_script], stderr=subprocess.STDOUT)
113 114
print 'Success.'
print '<pre>%s</pre>' % result