Commit a4e67e7e authored by Nicolas Wavrant's avatar Nicolas Wavrant

stack-monitor: index.cgi serves all other monitor files

parent 64c41cca
...@@ -33,17 +33,18 @@ parts += ...@@ -33,17 +33,18 @@ parts +=
cron-entry-monitor cron-entry-monitor
cron-entry-rss cron-entry-rss
deploy-index deploy-index
deploy-index-template
deploy-monitor-script deploy-monitor-script
deploy-rss-script deploy-rss-script
deploy-settings-cgi deploy-settings-cgi
deploy-status-cgi deploy-status-cgi
make-rss make-rss
setup-static-files
certificate-authority certificate-authority
public public
zero-parameters zero-parameters
cgi-httpd-wrapper cgi-httpd-wrapper
[exporter] [exporter]
recipe = slapos.cookbook:slaprunner.export recipe = slapos.cookbook:slaprunner.export
wrapper = $${directory:bin}/$${slap-parameter:namebase}-exporter wrapper = $${directory:bin}/$${slap-parameter:namebase}-exporter
......
...@@ -31,11 +31,13 @@ parts = ...@@ -31,11 +31,13 @@ parts =
cron-entry-monitor cron-entry-monitor
cron-entry-rss cron-entry-rss
deploy-index deploy-index
deploy-index-template
deploy-monitor-script deploy-monitor-script
deploy-rss-script deploy-rss-script
deploy-settings-cgi deploy-settings-cgi
deploy-status-cgi deploy-status-cgi
make-rss make-rss
setup-static-files
certificate-authority certificate-authority
public public
zero-parameters zero-parameters
...@@ -421,7 +423,6 @@ mode = 700 ...@@ -421,7 +423,6 @@ mode = 700
context = context =
key software_root runnerdirectory:software-root key software_root runnerdirectory:software-root
key instance_root runnerdirectory:instance-root key instance_root runnerdirectory:instance-root
key cloud9_url slaprunner:cloud9-url
key console slaprunner:console key console slaprunner:console
key debug slaprunner:debug key debug slaprunner:debug
key etc_dir slaprunner:etc_dir key etc_dir slaprunner:etc_dir
......
...@@ -212,7 +212,7 @@ slapos.recipe.build = 0.11.5 ...@@ -212,7 +212,7 @@ slapos.recipe.build = 0.11.5
slapos.recipe.cmmi = 0.2 slapos.recipe.cmmi = 0.2
slapos.recipe.download = 1.0.dev-r4053 slapos.recipe.download = 1.0.dev-r4053
slapos.recipe.template = 2.4.2 slapos.recipe.template = 2.4.2
slapos.toolbox = 0.38.1 #slapos.toolbox = 0.38.1
smmap = 0.8.2 smmap = 0.8.2
xml-marshaller = 0.9.7 xml-marshaller = 0.9.7
z3c.recipe.scripts = 1.0.1 z3c.recipe.scripts = 1.0.1
......
* This stack has for purpose to know if all promises, services, custom monitoring scripts went/are ok. * This stack has for purpose to know if all promises, services, custom monitoring scripts went/are ok.
* The second purpose of this stack is to implement a zero-knowledge feature : it means you can use its control interface to provide the user with sensible data. It can also let the user change some parameters * The second purpose of this stack is to implement a zero-knowledge feature : it means you can use its control interface to provide the user with sensible data. It can also let the user change some parameters
* It also provides a web interface, to see which promises, services and custom scripts failed. It also provide a rss feed to easily know the actual state of your instance, and to know when it started to went bad. * It also provides a web interface, to see which promises, services and custom scripts failed. It also provide a rss feed to easily know the actual state of your instance, and to know when it started to went bad. You can also add your own monitoring scripts, or cgi files (or just files) that you would want to check easily using a web interface.
Implementation : Implementation :
---------------- ----------------
...@@ -42,10 +42,21 @@ dash_path = ${dash:location}/bin/dash ...@@ -42,10 +42,21 @@ dash_path = ${dash:location}/bin/dash
curl_path = ${curl:location}/bin/curl curl_path = ${curl:location}/bin/curl
CGI SCripts:
------------
This stack also provides a web interface, in wich you can execute custom cgi scripts, or just print files. The web link is provided in the published parameters, as for the password that you have to change as soon as possible
In that interface you will have access to the previous scripts and the RSS feed. You can also add your files/scripts.
For that, there exists a folder /var/cgi-bin. You should see that directory as a tree having of deep 2. In /var/cgi-bin, you must create only folders, which are called categories. In each category, you can then add your own files.
The backend system will automatically render the webpage according to the inside structure of the cgi-bin directory. Moreover, it will also let you access to your scripts only if you are logged in : you do not need do do your own authentication system !
Notice : Notice :
-------- --------
* /!\A default password is set up at the installation : "passwordtochange". It has to be rewritten in the control interface by the user itself * /!\A default password is set up at the installation : "passwordtochange". It has to be rewritten in the control interface by the user itself
* /!\ If you use the recipe zeroknown, never name a parameter "recipe" or "password". * /!\ If you use the recipe zeroknown, never name a parameter "recipe" or "password".
* The control interface will let you change the values of the options declared in the [public] section of the config file (see zeroknown recipe). Other section's values will just be printed. These values won't be overwritten by buildout. * The control interface will let you change the values of the options declared in the [public] section of the config file (see zeroknown recipe). Other section's values will just be printed. These values won't be overwritten by buildout.
* If you want to allow a user to change, use the recipe zeroknown, with the buildout section name : "[public]" * If you want to allow a user to change a parameter, use the recipe zeroknown, with the buildout section name : "[public]"
* If you manually change a parameter, it could take some time for the modifications to be applied (at least 1 or 2 slapgrid-cp) * If you manually change a parameter, it could take some time for the modifications to be applied (at least 1 or 2 slapgrid-cp)
...@@ -10,6 +10,7 @@ parts += ...@@ -10,6 +10,7 @@ parts +=
backup-script-template backup-script-template
collective.recipe.template-egg collective.recipe.template-egg
dcron dcron
download-static-files
eggs eggs
extra-eggs extra-eggs
make-rss make-rss
...@@ -18,6 +19,7 @@ parts += ...@@ -18,6 +19,7 @@ parts +=
nginx nginx
rss-bin rss-bin
slapos-cookbook slapos-cookbook
static-folder
template-nginx-conf template-nginx-conf
[collective.recipe.template-egg] [collective.recipe.template-egg]
...@@ -27,9 +29,10 @@ eggs = collective.recipe.template ...@@ -27,9 +29,10 @@ eggs = collective.recipe.template
[extra-eggs] [extra-eggs]
recipe = zc.recipe.egg recipe = zc.recipe.egg
interpreter = pythonforrssgen interpreter = pythonwitheggs
eggs = eggs =
PyRSS2Gen PyRSS2Gen
Jinja2
[make-rss-script] [make-rss-script]
recipe = slapos.recipe.template recipe = slapos.recipe.template
...@@ -42,6 +45,7 @@ mode = 0644 ...@@ -42,6 +45,7 @@ mode = 0644
recipe = slapos.recipe.template recipe = slapos.recipe.template
url = ${:_profile_base_location_}/monitor.cfg.in url = ${:_profile_base_location_}/monitor.cfg.in
output = ${buildout:directory}/monitor.cfg output = ${buildout:directory}/monitor.cfg
filename = monitor.cfg
#md5sum = 6564a2e7c7d9e631b997ff2960ad3299 #md5sum = 6564a2e7c7d9e631b997ff2960ad3299
mode = 0644 mode = 0644
...@@ -55,7 +59,15 @@ mode = 0644 ...@@ -55,7 +59,15 @@ mode = 0644
[index] [index]
recipe = hexagonit.recipe.download recipe = hexagonit.recipe.download
url = ${:_profile_base_location_}/${:filename} url = ${:_profile_base_location_}/webfiles/${:filename}
download-only = true
#md5sum =
filename = index.cgi.in
mode = 0644
[index-template]
recipe = hexagonit.recipe.download
url = ${:_profile_base_location_}/webfiles/${:filename}
download-only = true download-only = true
#md5sum = #md5sum =
filename = index.html.jinja2 filename = index.html.jinja2
...@@ -63,7 +75,7 @@ mode = 0644 ...@@ -63,7 +75,7 @@ mode = 0644
[status-cgi] [status-cgi]
recipe = hexagonit.recipe.download recipe = hexagonit.recipe.download
url = ${:_profile_base_location_}/${:filename} url = ${:_profile_base_location_}/webfiles/${:filename}
download-only = true download-only = true
#md5sum = #md5sum =
filename = status.cgi.in filename = status.cgi.in
...@@ -71,7 +83,7 @@ mode = 0644 ...@@ -71,7 +83,7 @@ mode = 0644
[settings-cgi] [settings-cgi]
recipe = hexagonit.recipe.download recipe = hexagonit.recipe.download
url = ${:_profile_base_location_}/${:filename} url = ${:_profile_base_location_}/webfiles/${:filename}
download-only = true download-only = true
#md5sum = #md5sum =
filename = settings.cgi.in filename = settings.cgi.in
...@@ -92,6 +104,14 @@ output = $${directory:services}/crond ...@@ -92,6 +104,14 @@ output = $${directory:services}/crond
mode = 0700 mode = 0700
logfile = $${directory:log}/crond.log logfile = $${directory:log}/crond.log
[download-static-files]
recipe = hexagonit.recipe.download
url = https://github.com/Sebatyne/staticForMonitoring/blob/master/static-files.tar.gz?raw=true
download-only = true
#md5sum =
filename = static-files.tar.gz
mode = 0644
[eggs] [eggs]
recipe = z3c.recipe.scripts recipe = z3c.recipe.scripts
eggs = eggs =
...@@ -100,3 +120,4 @@ eggs = ...@@ -100,3 +120,4 @@ eggs =
[versions] [versions]
PyRSS2Gen = 1.1 PyRSS2Gen = 1.1
Jinja2 = 2.6
<html>
<head>
<title>Monitoring Interface</title>
</head>
<body style="padding:15px">
<ul>
<li><a href="/{{ rss_filename }}" target="cgi-frame">RSS feed</a></li>
<li><a href="/{{ status_filename }}" target="cgi-frame">status</a></li>
<li><a href="/{{ settings_filename }}" target="cgi-frame">settings</a></li>
</ul>
<iframe name="cgi-frame" style="width:80%;height:70%;margin-left:15%;position:absolute;top:10px;border-style:none;border-left-style:solid"></iframe>
<body>
...@@ -11,18 +11,24 @@ monitor-dir = $${directory:var}/monitor ...@@ -11,18 +11,24 @@ monitor-dir = $${directory:var}/monitor
result-dir = $${:monitor-dir}/bool result-dir = $${:monitor-dir}/bool
json-filename = monitor.json json-filename = monitor.json
json-path = $${:monitor-dir}/$${:json-filename} json-path = $${:monitor-dir}/$${:json-filename}
rss-path = $${directory:www}/$${:rss-filename} rss-path = $${:monitoring-cgi}/$${:rss-filename}
rss-filename = rssfeed.html rss-filename = rssfeed.html
executable = $${directory:bin}/monitor.py executable = $${directory:bin}/monitor.py
cgi-bin = $${directory:cgi-bin}
monitoring-cgi = $${directory:monitoring-cgi}
knowledge0-cgi = $${directory:knowledge0-cgi}
[directory] [directory]
home = $${buildout:directory} home = $${buildout:directory}
etc = $${:home}/etc etc = $${:home}/etc
bin = $${:home}/bin bin = $${:home}/bin
srv = $${:home}/srv srv = $${:home}/srv
var = $${:home}/var var = $${:home}/var
ca-dir = $${:srv}/ssl ca-dir = $${:srv}/ssl
cgi-bin = $${:var}/cgi-bin
monitoring-cgi = $${:cgi-bin}/monitoring
knowledge0-cgi = $${:cgi-bin}/zero-knowledge
cron-entries = $${:etc}/cron.d cron-entries = $${:etc}/cron.d
crontabs = $${:etc}/crontabs crontabs = $${:etc}/crontabs
cronstamps = $${:etc}/cronstamps cronstamps = $${:etc}/cronstamps
...@@ -65,40 +71,57 @@ name = build-rss ...@@ -65,40 +71,57 @@ name = build-rss
frequency = * * * * * frequency = * * * * *
command = $${make-rss:output} command = $${make-rss:output}
[setup-static-files]
recipe = hexagonit.recipe.download
url = ${download-static-files:destination}/${download-static-files:filename}
#md5sum = 628072e7212db1e8cdacb22b21752cda
filename = static
destination = $${directory:www}
ignore-existing = true
mode = 0644
[deploy-index] [deploy-index]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
template = ${index:location}/${index:filename} template = ${index:location}/${index:filename}
rendered = $${directory:www}/$${:filename} rendered = $${directory:www}/$${:filename}
filename = index.html filename = index.cgi
mode = 0744 mode = 0744
context = context =
key rss_filename monitor-parameters:rss-filename key cgi_directory monitor-parameters:cgi-bin
key settings_filename deploy-settings-cgi:filename raw index_template $${deploy-index-template:location}/$${deploy-index-template:filename}
key status_filename deploy-status-cgi:filename key password zero-parameters:monitor-password
raw extra_eggs_interpreter ${buildout:directory}/bin/${extra-eggs:interpreter}
[deploy-index-template]
recipe = hexagonit.recipe.download
url = ${index-template:location}/$${:filename}
destination = $${directory:www}
filename = ${index-template:filename}
download-only = true
#md5sum =
mode = 0644
[deploy-status-cgi] [deploy-status-cgi]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
template = ${status-cgi:location}/${status-cgi:filename} template = ${status-cgi:location}/${status-cgi:filename}
rendered = $${directory:www}/$${:filename} rendered = $${monitor-parameters:monitoring-cgi}/$${:filename}
filename = status.cgi filename = status.cgi
mode = 0744 mode = 0744
context = context =
key json_file monitor-parameters:json-path key json_file monitor-parameters:json-path
key password zero-parameters:monitor-password
raw python_executable ${buildout:executable} raw python_executable ${buildout:executable}
key this_filename :filename
[deploy-settings-cgi] [deploy-settings-cgi]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
template = ${settings-cgi:location}/${settings-cgi:filename} template = ${settings-cgi:location}/${settings-cgi:filename}
rendered = $${directory:www}/$${:filename} rendered = $${monitor-parameters:knowledge0-cgi}/$${:filename}
filename = settings.cgi filename = settings.cgi
mode = 0744 mode = 0744
context = context =
raw config_cfg $${buildout:directory}/knowledge0.cfg raw config_cfg $${buildout:directory}/knowledge0.cfg
key password zero-parameters:monitor-password
raw python_executable ${buildout:executable} raw python_executable ${buildout:executable}
key this_filename :filename raw pwd monitoring
key this_file :filename
[deploy-monitor-script] [deploy-monitor-script]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
......
#!{{ extra_eggs_interpreter }}
import cgi
import cgitb
import Cookie
import jinja2
import json
import os
import subprocess
import sys
import urllib
cgitb.enable(display=0, logdir="/tmp/cgi.log")
form = cgi.FieldStorage()
cookie = Cookie.SimpleCookie()
cgi_path = "{{ cgi_directory }}"
def forward_form():
command = os.path.join(cgi_path, form['posting-script'].value)
params_dict = {}
for f in form:
params_dict[f] = form[f].value
del params_dict['posting-script']
os.environ['QUERY_STRING'] = urllib.urlencode(params_dict)
try:
if os.access(command, os.X_OK):
print '\n', subprocess.check_output([command])
except subprocess.CalledProcessError:
print "There is a problem with sub-process"
pass
def return_document():
command = os.path.join(cgi_path, form['script'].value)
#XXX this functions should be called only for display,
#so a priori it doesn't need form data
os.environ['QUERY_STRING'] = ''
try:
if os.access(command, os.X_OK):
print '\n', subprocess.check_output([command])
elif os.access(command, os.R_OK):
print open(command).read()
else:
raise OSError
except (subprocess.CalledProcessError, OSError):
print "<p>File cannot be found</p>"
def make_menu():
# Transform deep-2 tree in json
folder_list = {}
for folder in os.listdir(cgi_path):
if os.path.isdir(os.path.join(cgi_path, folder)):
folder_list[folder] = []
for folder in folder_list:
for file in os.listdir(os.path.join(cgi_path, folder)):
if os.path.isfile(os.path.join(cgi_path, folder, file)):
folder_list[folder].append(file)
return folder_list
# Beginning of response
print "Content-Type: text/html"
print
# Check if user is logged
if "password" in form:
password = form['password'].value
if password == '{{ password }}' :
cookie['password'] = password
print cookie
else:
cookie_string = os.environ.get('HTTP_COOKIE')
if cookie_string:
cookie.load(cookie_string)
try:
password = cookie['password'].value
except KeyError:
password = None
else:
password = None
if not password or password != '{{ password }}':
print "<html><body>"
if password is None:
print "<h1>This is the monitoring interface</h1>"
else:
print "<h1>Error</h1><p>Wrong password</p>"
print """
<p>Please enter the monitor_password in the next field to access the data</p>
<form action="/index.cgi" method="post">
Password : <input type="password" name="password">
<input type="submit" value="Access">
</form>
</body></html>"""
# redirection to the required script/page
else:
print
if "posting-script" in form:
forward_form()
elif "script" in form:
return_document()
else:
html_base = jinja2.Template(open('{{ index_template }}').read())
print
print html_base.render(tree=make_menu())
<html>
<head>
<title>Monitoring Interface</title>
<link rel="stylesheet" href="pure-min.css">
<link rel="stylesheet" href="/style.css">
<script src="jquery-1.10.2.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<div id="div-menu">
<h1>Monitoring</h1>
<div id="script-categories" class="pure-menu pure-menu-open">
<ul>
{% for category in tree %}
<li class="pure-menu-heading category">{{ category }}</li>
{% for script in tree[category] %}
<li><a href="{{ category }}/{{ script }}" class="script">{{ script }}</a></li>
{% endfor %}
{% endfor %}
</ul>
</div>
</div>
<div id="content">
<iframe src="/index.cgi">
</iframe>
</div>
</body>
</html>
#!{{ python_executable }}
import cgi
import cgitb
import ConfigParser
import os
cgitb.enable()
form = cgi.FieldStorage()
print "<html><body>"
config_file = "{{ config_cfg }}"
if not os.path.exists(config_file):
print "Your software does <b>not</b> embed 0-knowledge. \
This interface is useless in this case"
exit(0)
parser = ConfigParser.ConfigParser()
parser.read(config_file)
for name in form:
parser.set('public', name, form[name].value)
with open(config_file, 'w') as file:
parser.write(file)
print "<h1>Values that can be defined by the user :</h1>"
print "<form action=\"/index.cgi\" method=\"post\">"
print "<input type=\"hidden\" name=\"posting-script\" value=\"{{ pwd }}/{{ this_file }}\">"
for option in parser.options("public"):
print "%s : <input type=\"text\" name=\"%s\" \
value=\"%s\"><br>"% (option, option, parser.get('public', option))
print "<input type=\"submit\" value=\"Save\"></form>"
print "<h1>Other values :</h1>"
for section in parser.sections():
if section != 'public':
for option in parser.options(section):
print "<b>%s</b> : value=\"%s\"<br>" % (option,
parser.get(section, option))
print "</body></html>"
#!{{ python_executable }}
import cgitb
import json
cgitb.enable(display=0, logdir="/tmp/cgi.log")
json_file = "{{ json_file }}"
result = json.load(open(json_file))
print "<html><body>"
print "<h1>Monitoring :</h1>"
print "<p><em>Last time of monitoring process : %s</em></p>" % (result['datetime'])
del result['datetime']
print "<br/>"
print "<h2>These scripts and promises have failed :</h2>"
for r in result:
if result[r] != '':
print "<h3>%s</h3><p style=\"padding-left:30px;\">%s</p>" % (r, result[r])
print "<br/>"
print "<h2>These scripts and promises were successful :</h2>"
for r in result:
if result[r] == '':
print "<h3>%s</h3><p>%s</p>" % (r, result[r])
print "</body></html>"
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