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 +=
cron-entry-monitor
cron-entry-rss
deploy-index
deploy-index-template
deploy-monitor-script
deploy-rss-script
deploy-settings-cgi
deploy-status-cgi
make-rss
setup-static-files
certificate-authority
public
zero-parameters
cgi-httpd-wrapper
[exporter]
recipe = slapos.cookbook:slaprunner.export
wrapper = $${directory:bin}/$${slap-parameter:namebase}-exporter
......
......@@ -31,11 +31,13 @@ parts =
cron-entry-monitor
cron-entry-rss
deploy-index
deploy-index-template
deploy-monitor-script
deploy-rss-script
deploy-settings-cgi
deploy-status-cgi
make-rss
setup-static-files
certificate-authority
public
zero-parameters
......@@ -421,7 +423,6 @@ mode = 700
context =
key software_root runnerdirectory:software-root
key instance_root runnerdirectory:instance-root
key cloud9_url slaprunner:cloud9-url
key console slaprunner:console
key debug slaprunner:debug
key etc_dir slaprunner:etc_dir
......
......@@ -212,7 +212,7 @@ slapos.recipe.build = 0.11.5
slapos.recipe.cmmi = 0.2
slapos.recipe.download = 1.0.dev-r4053
slapos.recipe.template = 2.4.2
slapos.toolbox = 0.38.1
#slapos.toolbox = 0.38.1
smmap = 0.8.2
xml-marshaller = 0.9.7
z3c.recipe.scripts = 1.0.1
......
* 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
* 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 :
----------------
......@@ -42,10 +42,21 @@ dash_path = ${dash:location}/bin/dash
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 :
--------
* /!\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".
* 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)
......@@ -10,6 +10,7 @@ parts +=
backup-script-template
collective.recipe.template-egg
dcron
download-static-files
eggs
extra-eggs
make-rss
......@@ -18,6 +19,7 @@ parts +=
nginx
rss-bin
slapos-cookbook
static-folder
template-nginx-conf
[collective.recipe.template-egg]
......@@ -27,9 +29,10 @@ eggs = collective.recipe.template
[extra-eggs]
recipe = zc.recipe.egg
interpreter = pythonforrssgen
interpreter = pythonwitheggs
eggs =
PyRSS2Gen
Jinja2
[make-rss-script]
recipe = slapos.recipe.template
......@@ -42,6 +45,7 @@ mode = 0644
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/monitor.cfg.in
output = ${buildout:directory}/monitor.cfg
filename = monitor.cfg
#md5sum = 6564a2e7c7d9e631b997ff2960ad3299
mode = 0644
......@@ -55,7 +59,15 @@ mode = 0644
[index]
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
#md5sum =
filename = index.html.jinja2
......@@ -63,7 +75,7 @@ mode = 0644
[status-cgi]
recipe = hexagonit.recipe.download
url = ${:_profile_base_location_}/${:filename}
url = ${:_profile_base_location_}/webfiles/${:filename}
download-only = true
#md5sum =
filename = status.cgi.in
......@@ -71,7 +83,7 @@ mode = 0644
[settings-cgi]
recipe = hexagonit.recipe.download
url = ${:_profile_base_location_}/${:filename}
url = ${:_profile_base_location_}/webfiles/${:filename}
download-only = true
#md5sum =
filename = settings.cgi.in
......@@ -92,6 +104,14 @@ output = $${directory:services}/crond
mode = 0700
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]
recipe = z3c.recipe.scripts
eggs =
......@@ -100,3 +120,4 @@ eggs =
[versions]
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
result-dir = $${:monitor-dir}/bool
json-filename = monitor.json
json-path = $${:monitor-dir}/$${:json-filename}
rss-path = $${directory:www}/$${:rss-filename}
rss-path = $${:monitoring-cgi}/$${:rss-filename}
rss-filename = rssfeed.html
executable = $${directory:bin}/monitor.py
cgi-bin = $${directory:cgi-bin}
monitoring-cgi = $${directory:monitoring-cgi}
knowledge0-cgi = $${directory:knowledge0-cgi}
[directory]
home = $${buildout:directory}
etc = $${:home}/etc
bin = $${:home}/bin
srv = $${:home}/srv
var = $${:home}/var
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
crontabs = $${:etc}/crontabs
cronstamps = $${:etc}/cronstamps
......@@ -65,40 +71,57 @@ name = build-rss
frequency = * * * * *
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]
recipe = slapos.recipe.template:jinja2
template = ${index:location}/${index:filename}
rendered = $${directory:www}/$${:filename}
filename = index.html
filename = index.cgi
mode = 0744
context =
key rss_filename monitor-parameters:rss-filename
key settings_filename deploy-settings-cgi:filename
key status_filename deploy-status-cgi:filename
key cgi_directory monitor-parameters:cgi-bin
raw index_template $${deploy-index-template:location}/$${deploy-index-template: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]
recipe = slapos.recipe.template:jinja2
template = ${status-cgi:location}/${status-cgi:filename}
rendered = $${directory:www}/$${:filename}
rendered = $${monitor-parameters:monitoring-cgi}/$${:filename}
filename = status.cgi
mode = 0744
context =
key json_file monitor-parameters:json-path
key password zero-parameters:monitor-password
raw python_executable ${buildout:executable}
key this_filename :filename
[deploy-settings-cgi]
recipe = slapos.recipe.template:jinja2
template = ${settings-cgi:location}/${settings-cgi:filename}
rendered = $${directory:www}/$${:filename}
rendered = $${monitor-parameters:knowledge0-cgi}/$${:filename}
filename = settings.cgi
mode = 0744
context =
raw config_cfg $${buildout:directory}/knowledge0.cfg
key password zero-parameters:monitor-password
raw python_executable ${buildout:executable}
key this_filename :filename
raw pwd monitoring
key this_file :filename
[deploy-monitor-script]
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