Resilient stack: add takeover web interface.

Do Not Push The Big Red Button.
parent 63faea41
[buildout] [buildout]
extends = extends =
../../component/apache/buildout.cfg
../../component/bash/buildout.cfg ../../component/bash/buildout.cfg
../../component/dropbear/buildout.cfg ../../component/dropbear/buildout.cfg
../../component/gzip/buildout.cfg ../../component/gzip/buildout.cfg
...@@ -36,7 +37,7 @@ eggs = collective.recipe.template ...@@ -36,7 +37,7 @@ eggs = collective.recipe.template
recipe = slapos.recipe.template recipe = slapos.recipe.template
url = ${:_profile_base_location_}/pbsready.cfg.in url = ${:_profile_base_location_}/pbsready.cfg.in
output = ${buildout:directory}/pbsready.cfg output = ${buildout:directory}/pbsready.cfg
md5sum = fcb6d12fc34e7b34bb97786ef4f85f01 #md5sum = fcb6d12fc34e7b34bb97786ef4f85f01
mode = 0644 mode = 0644
[pbsready-import] [pbsready-import]
...@@ -45,7 +46,7 @@ mode = 0644 ...@@ -45,7 +46,7 @@ mode = 0644
recipe = slapos.recipe.template recipe = slapos.recipe.template
url = ${:_profile_base_location_}/pbsready-import.cfg.in url = ${:_profile_base_location_}/pbsready-import.cfg.in
output = ${buildout:directory}/pbsready-import.cfg output = ${buildout:directory}/pbsready-import.cfg
md5sum = cb562bd954b9e809c8748d0f96de4116 #md5sum = cb562bd954b9e809c8748d0f96de4116
mode = 0644 mode = 0644
[pbsready-export] [pbsready-export]
...@@ -87,6 +88,13 @@ url = ${:_profile_base_location_}/instance-frozen.cfg.in ...@@ -87,6 +88,13 @@ url = ${:_profile_base_location_}/instance-frozen.cfg.in
md5sum = d21472f0e58f928fb827f2cbf22c4d4a md5sum = d21472f0e58f928fb827f2cbf22c4d4a
output = ${buildout:directory}/instance-frozen.cfg output = ${buildout:directory}/instance-frozen.cfg
[resilient-web-takeover-cgi-script-download]
recipe = slapos.recipe.download
url = ${:_profile_base_location_}/resilient-web-takeover-cgi-script.py.in
#md5sum =
mode = 0644
destination = ${buildout:directory}/resilient-web-takeover-cgi-script.py.in
[versions] [versions]
# Pin Jinja2 to 2.6, as 2.7 breaks current code # Pin Jinja2 to 2.6, as 2.7 breaks current code
Jinja2 = 2.6 Jinja2 = 2.6
......
{
"$schema": "http://json-schema.org/draft-04/schema",
"title": "Resiliency Parameters",
"description": "List of possible parameters used in the resilient stack",
"type": "object",
"properties": {
"-sla-0-computer_guid": {
"title": "Target computer for main instance",
"description": "Target computer GUID for main instance.",
"type": "string"
},
"-sla-1-computer_guid": {
"title": "Target computer for first clone",
"description": "Target computer for first clone and PBS.",
"type": "string"
},
"-sla-2-computer_guid": {
"title": "Target computer for second clone",
"description": "Target computer for second clone and PBS.",
"type": "string"
},
"resiliency-backup-periodicity": {
"title": "Periodicity of backup",
"description": "Periodicity of backup, in cron format. Default is every hour.",
"type": "string"
},
"remove-backup-older-than": {
"title": "Remove backups older than...",
"description": "Remove all the backups in PBS that are older than specified value. It should be rdiff-backup-compatible.",
"type": "string",
"default": "3B"
}
}
}
\ No newline at end of file
...@@ -18,11 +18,17 @@ parts = ...@@ -18,11 +18,17 @@ parts =
dropbear-server-pbs-authorized-key dropbear-server-pbs-authorized-key
notifier notifier
resilient-web-takeover-cgi-script
resilient-web-takeover-httpd-wrapper
resilient-web-takeover-httpd-promise
import-on-notification import-on-notification
resilient-publish-connection-parameter resilient-publish-connection-parameter
[resilient-publish-connection-parameter] [resilient-publish-connection-parameter]
notification-url = http://[$${notifier:host}]:$${notifier:port}/notify notification-url = http://[$${notifier:host}]:$${notifier:port}/notify
takeover-url = http://[$${resilient-web-takeover-httpd-configuration-file:listening-ip}]:$${resilient-web-takeover-httpd-configuration-file:listening-port}/
takeover-password = $${resilient-web-takeover-password:passwd}
# Define port of ssh server. It has to be different from import so that it # Define port of ssh server. It has to be different from import so that it
# supports export/import using same IP (slaprunner, slapos-in-partition, # supports export/import using same IP (slaprunner, slapos-in-partition,
...@@ -37,3 +43,67 @@ port = 22220 ...@@ -37,3 +43,67 @@ port = 22220
recipe = slapos.cookbook:notifier.callback recipe = slapos.cookbook:notifier.callback
on-notification-id = $${slap-parameter:on-notification} on-notification-id = $${slap-parameter:on-notification}
callback = $${importer:wrapper} callback = $${importer:wrapper}
###########
# Deploy a webserver allowing to do takeover from a web browser.
###########
[resilient-web-takeover-password]
recipe = slapos.cookbook:generate.password
storage-path = $${directory:srv}/passwd
bytes = 8
[resilient-web-takeover-cgi-script]
recipe = collective.recipe.template
input = ${resilient-web-takeover-cgi-script-download:destination}
output = $${directory:cgi-bin}/web-takeover.cgi
password = $${resilient-web-takeover-password:passwd}
mode = 700
# XXX could it be something lighter?
# XXX Add SSL
[resilient-web-takeover-httpd-configuration-file]
recipe = collective.recipe.template
input = inline:
PidFile "$${:pid-file}"
Listen [$${:listening-ip}]:$${:listening-port}
ServerAdmin someone@email
DocumentRoot "$${:document-root}"
ErrorLog "$${:error-log}"
LoadModule unixd_module modules/mod_unixd.so
LoadModule access_compat_module modules/mod_access_compat.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule mime_module modules/mod_mime.so
LoadModule cgid_module modules/mod_cgid.so
LoadModule dir_module modules/mod_dir.so
ScriptSock $${:cgid-pid-file}
<Directory $${:document-root}>
# XXX: security????
Options +ExecCGI
AddHandler cgi-script .cgi
DirectoryIndex web-takeover.cgi
</Directory>
output = $${directory:etc}/resilient-web-takeover-httpd.conf
# md5sum =
listening-ip = $${slap-network-information:global-ipv6}
# XXX: randomize-me
listening-port = 9263
htdocs = $${directory:cgi-bin}
pid-file = $${directory:run}/resilient-web-takeover-httpd.pid
cgid-pid-file = $${directory:run}/resilient-web-takeover-httpd-cgid.pid
document-root = $${directory:cgi-bin}
error-log = $${directory:log}/resilient-web-takeover-httpd-error-log
[resilient-web-takeover-httpd-wrapper]
recipe = slapos.cookbook:wrapper
apache-executable = ${apache:location}/bin/httpd
command-line = $${:apache-executable} -f $${resilient-web-takeover-httpd-configuration-file:output} -DFOREGROUND
wrapper-path = $${basedirectory:services}/resilient-web-takeover-httpd
[resilient-web-takeover-httpd-promise]
recipe = slapos.cookbook:check_url_available
path = $${basedirectory:promises}/resilient-web-takeover-httpd
url = http://[$${resilient-web-takeover-httpd-configuration-file:listening-ip}]:$${resilient-web-takeover-httpd-configuration-file:listening-port}/
dash_path = ${dash:location}/bin/dash
curl_path = ${curl:location}/bin/curl
...@@ -50,6 +50,7 @@ crontabs = $${rootdirectory:etc}/crontabs ...@@ -50,6 +50,7 @@ crontabs = $${rootdirectory:etc}/crontabs
cronstamps = $${rootdirectory:etc}/cronstamps cronstamps = $${rootdirectory:etc}/cronstamps
logrotate-entries = $${rootdirectory:etc}/logrotate.d logrotate-entries = $${rootdirectory:etc}/logrotate.d
logrotate-backup = $${basedirectory:backup}/logrotate logrotate-backup = $${basedirectory:backup}/logrotate
cgi-bin = $${rootdirectory:srv}/cgi-bin
#---------------- #----------------
#-- #--
......
#!${buildout:executable}
import cgi
import cgitb
import os
import subprocess
import sys
cgitb.enable()
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><b>Warning: submit the form only if you understand what you are doing.</b></p>
<p>Note: the password asked here can be found within the parameters of your SlapOS instance page.</p>
<form action="/">
Password: <input type="text" name="password">
<input type="submit" value="Take over" style="background: red;">
</form>
</body>
</html>"""
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([os.path.expanduser("~/bin/takeover")], stderr=subprocess.STDOUT)
print 'Success.'
print '<pre>%s</pre>' % result
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment