Commit 15df3830 authored by Tristan Cavelier's avatar Tristan Cavelier

monitor: update api

parent 5571bb14
...@@ -56,12 +56,12 @@ md5sum = 2db5c08c7e8658981b4b1e3f27fd5967 ...@@ -56,12 +56,12 @@ md5sum = 2db5c08c7e8658981b4b1e3f27fd5967
[monitor-bin] [monitor-bin]
<= monitor-download-base <= monitor-download-base
filename = monitor.py.in filename = monitor.py.in
md5sum = a3c673bbd37a98f160f8a10a8fb1b13a md5sum = 0f9c69954d3b9e952ac6cb63c293f127
[monitor-web-default-promise-interface] [monitor-web-default-promise-interface]
<= monitor-download-base <= monitor-download-base
filename = default-promise-interface.html filename = default-promise-interface.html
md5sum = 1d71746d4afcdc43d663ae8181190254 md5sum = 81fde0e082165ade03c5a9c8abf11136
[monitor-web-index-html] [monitor-web-index-html]
<= monitor-download-base <= monitor-download-base
...@@ -94,7 +94,7 @@ recipe = slapos.recipe.template:jinja2 ...@@ -94,7 +94,7 @@ recipe = slapos.recipe.template:jinja2
filename = template-monitor.cfg filename = template-monitor.cfg
template = ${:_profile_base_location_}/instance-monitor.cfg.jinja2.in template = ${:_profile_base_location_}/instance-monitor.cfg.jinja2.in
rendered = ${buildout:directory}/template-monitor.cfg rendered = ${buildout:directory}/template-monitor.cfg
md5sum = 66d13e6e93369a38ff86b8e65abe1cee md5sum = 008a25e95a87e0e74e8cf4fbefa9ae82
context = context =
key apache_location apache:location key apache_location apache:location
key gzip_location gzip:location key gzip_location gzip:location
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
var service_name = getServiceName(), var service_name = getServiceName(),
monitor_json_url = "/monitor.haljson", monitor_json_url = "/monitor.haljson",
status_json_url = "/public/" + service_name + "/status.json"; // XXX hardcoded status_json_url = "/public/" + service_name + ".status.json";
function newDeferred() { function newDeferred() {
var d = { var d = {
......
...@@ -48,6 +48,7 @@ scripts = ${:etc}/run ...@@ -48,6 +48,7 @@ scripts = ${:etc}/run
services = ${:etc}/service services = ${:etc}/service
promises = ${:etc}/promise promises = ${:etc}/promise
monitor = ${:srv}/monitor monitor = ${:srv}/monitor
monitor-promise = ${:etc}/monitor-promise
[monitor-directory] [monitor-directory]
recipe = slapos.cookbook:mkdirectory recipe = slapos.cookbook:mkdirectory
...@@ -223,9 +224,11 @@ rendered = ${directory:scripts}/bootstrap-monitor ...@@ -223,9 +224,11 @@ rendered = ${directory:scripts}/bootstrap-monitor
context = context =
raw python_executable {{ python_executable }} raw python_executable {{ python_executable }}
key public_folder monitor-directory:public key public_folder monitor-directory:public
key configuration_location monitor-conf:rendered key private_folder monitor-directory:private
key monitor_configuration_path monitor-conf:rendered
key promise_runner_path monitor-run-promise:rendered key promise_runner_path monitor-run-promise:rendered
key promise_folder directory:promises key promise_folder directory:promises
key monitor_promise_folder directory:monitor-promise
[monitor-run-promise] [monitor-run-promise]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
...@@ -246,17 +249,15 @@ curl_path = {{ curl_executable_location }} ...@@ -246,17 +249,15 @@ curl_path = {{ curl_executable_location }}
[monitor-httpd-promise-conf] [monitor-httpd-promise-conf]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
rendered = ${monitor-directory:services-conf}/monitor-httpd-promise.conf rendered = ${directory:monitor-promise}/${monitor-httpd-promise:filename}.cfg
template = {{ monitor_httpd_promise_conf }} template = {{ monitor_httpd_promise_conf }}
mode = 0644
context = section parameter_dict monitor-httpd-promise-conf-parameter context = section parameter_dict monitor-httpd-promise-conf-parameter
[monitor-httpd-promise-conf-parameter] [monitor-httpd-promise-conf-parameter]
title = Monitor httpd listening title = Monitor httpd listening
name = ${monitor-httpd-promise:filename}
# frequency minute hour day mounth weekday # frequency minute hour day mounth weekday
frequency = * * * * * frequency = * * * * *
#promise-path =
#interface-path =
public-path-list = ${monitor-httpd-conf-parameter:access-log} ${monitor-httpd-conf-parameter:error-log} public-path-list = ${monitor-httpd-conf-parameter:access-log} ${monitor-httpd-conf-parameter:error-log}
#private-path-list = #private-path-list =
...@@ -280,5 +281,6 @@ parts = ...@@ -280,5 +281,6 @@ parts =
monitor-conf monitor-conf
start-monitor start-monitor
ca-httpd ca-httpd
monitor-httpd-promise
monitor-httpd-promise-conf monitor-httpd-promise-conf
publish publish
#!{{ python_executable }} #!{{ python_executable }}
configuration_location = "{{ configuration_location }}" # Put this file in the software release
promise_runner_path = "{{ promise_runner_path }}" promise_runner_path = "{{ promise_runner_path }}"
public_folder = "{{ public_folder }}" public_folder = "{{ public_folder }}"
private_folder = "{{ private_folder }}"
monitor_configuration_path = "{{ monitor_configuration_path }}"
promise_folder = "{{ promise_folder }}" promise_folder = "{{ promise_folder }}"
monitor_promise_folder = "{{ monitor_promise_folder }}"
import sys import sys
import os import os
...@@ -10,44 +13,33 @@ import subprocess ...@@ -10,44 +13,33 @@ import subprocess
import threading import threading
import json import json
import ConfigParser import ConfigParser
import traceback
def main(): def main():
# initialisation # initialisation
config = loadConfig([configuration_location]) config = loadConfig([monitor_configuration_path])
# search for configurations in monitor.conf.d # get promises in monitor_promise_folder
configuration_folder_location = configuration_location + ".d" promise_dict = {}
service_config_list = [ fillPromiseDictFromFolder(promise_dict, monitor_promise_folder)
loadConfig(os.path.join(configuration_folder_location, filename)) # get promises in promise_folder
for filename in os.listdir(configuration_folder_location) fillPromiseDictFromFolder(promise_dict, promise_folder)
if os.path.isfile(os.path.join(configuration_folder_location, filename)) # get promises configurations
] for filename in os.listdir(monitor_promise_folder):
# fill dict of service path = os.path.join(monitor_promise_folder, filename)
service_config_dict = {} if os.path.isfile(path) and filename[-4:] == ".cfg":
for service_config in service_config_list: promise_name = filename[:-4]
service_config_dict[service_config.get("service", "name")] = service_config if promise_name in promise_dict:
# search for promises and make relation between service_config_list loadConfig([path], promise_dict[promise_name]["configuration"])
for filename in os.listdir(promise_folder): promise_items = promise_dict.items()
promise_path = os.path.join(promise_folder, filename) # create symlinks from service configurations
if os.path.isfile(promise_path) and os.access(promise_path, os.X_OK): for service_name, promise in promise_items:
service_name = filename service_config = promise["configuration"]
service_config = service_config_dict.get(service_name) createSymlinksFromConfig((config, "monitor", "public-folder"), (service_config, "service", "public-path-list"), service_name)
if service_name not in service_config_dict or softConfigGet(service_config, "service", "promise-path"): createSymlinksFromConfig((config, "monitor", "private-folder"), (service_config, "service", "private-path-list"), service_name)
service_name = newServiceName(service_name, service_config_dict) # create symlinks from monitor.conf
service_config = ConfigParser.ConfigParser() createSymlinksFromConfig((config, "monitor", "public-folder"), (config, "monitor", "public-path-list"))
service_config_list.append(service_config) createSymlinksFromConfig((config, "monitor", "private-folder"), (config, "monitor", "private-path-list"))
service_config_dict[service_name] = service_config
service_config.add_section("service")
service_config.set("service", "name", service_name)
service_config.set("service", "frequency", "* * * * *") # every minutes
service_config.set("service", "promise-path", promise_path)
# filter services without promise-path
service_config_dict = None
service_config_list = [
service_config
for service_config in service_config_list
if softConfigGet(service_config, "service", "promise-path")
]
# generate monitor.json # generate monitor.json
monitor_dict = {} monitor_dict = {}
tmp = softConfigGet(config, "monitor", "title") tmp = softConfigGet(config, "monitor", "title")
...@@ -56,57 +48,58 @@ def main(): ...@@ -56,57 +48,58 @@ def main():
tmp = softConfigGet(config, "monitor", "monitor-url-list") tmp = softConfigGet(config, "monitor", "monitor-url-list")
if tmp: if tmp:
monitor_dict["_links"] = {"related_monitor": [{"href": url} for url in tmp.split()]} monitor_dict["_links"] = {"related_monitor": [{"href": url} for url in tmp.split()]}
if service_config_list: if promise_items:
service_list = [] service_list = []
monitor_dict["_embedded"] = {"service": service_list} monitor_dict["_embedded"] = {"service": service_list}
for service_config in service_config_list: for service_name, promise in promise_items:
service_config = promise["configuration"]
service_dict = {} service_dict = {}
service_list.append(service_dict) service_list.append(service_dict)
service_name = service_dict["id"] = service_config.get("service", "name") service_dict["id"] = service_name
service_dict["_links"] = {"status": {"href": "/public/%s/status.json" % service_name}} service_dict["_links"] = {"status": {"href": "/public/%s.status.json" % service_name}} # hardcoded
tmp = softConfigGet(service_config, "service", "title") tmp = softConfigGet(service_config, "service", "title")
if tmp: if tmp:
service_dict["title"] = tmp service_dict["title"] = tmp
tmp = softConfigGet(service_config, "service", "interface-path") interface_path = os.path.join(private_folder, service_name, "interface/index.html") # hardcoded
if tmp: if os.path.isfile(interface_path):
service_dict["_links"]["interface"] = {"href": "/%s.html" % service_name} # XXX hardcoded service_dict["_links"]["interface"] = {"href": "/private/%s/interface/" % service_name} # hardcoded
else: else:
service_dict["_links"]["interface"] = {"href": "/default-promise-interface.html?service_name=%s" % service_name} # XXX hardcoded service_dict["_links"]["interface"] = {"href": "/default-promise-interface.html?service_name=%s" % service_name} # XXX hardcoded
with open(config.get("monitor", "monitor-hal-json"), "w") as fp: with open(config.get("monitor", "monitor-hal-json"), "w") as fp:
json.dump(monitor_dict, fp) json.dump(monitor_dict, fp)
# create symlinks from service configurations
for service_config in service_config_list:
service_name = service_config.get("service", "name")
createSymlinksFromConfig((config, "monitor", "public-folder"), (service_config, "service", "public-path-list"), service_name)
createSymlinksFromConfig((config, "monitor", "private-folder"), (service_config, "service", "private-path-list"), service_name)
# put promises to a cron file # put promises to a cron file
# XXX if manifest is modified then: # add manifest to avoid to write every minutes on cron.d... # XXX only if at least one configuration file is modified, then write in the cron
service_pid_folder = config.get("monitor", "service-pid-folder") service_pid_folder = config.get("monitor", "service-pid-folder")
crond_folder = config.get("monitor", "crond-folder") crond_folder = config.get("monitor", "crond-folder")
cron_line_list = [] cron_line_list = []
for service_config in service_config_list: for service_name, promise in promise_items:
service_name = service_config.get("service", "name") service_status_path = "%s/%s.status.json" % (public_folder, service_name) # hardcoded
service_status_path = "%s/%s/status.json" % (public_folder, service_name)
mkdirAll(os.path.dirname(service_status_path)) mkdirAll(os.path.dirname(service_status_path))
service_cron_path = os.path.join(crond_folder, service_name)
cron_line_list.append("%s %s %s %s " % ( cron_line_list.append("%s %s %s %s " % (
service_config.get("service", "frequency"), softConfigGet(service_config, "service", "frequency") or "* * * * *",
promise_runner_path, promise_runner_path,
os.path.join(service_pid_folder, "%s.pid" % service_name), os.path.join(service_pid_folder, "%s.pid" % service_name),
service_status_path, service_status_path,
) + service_config.get("service", "promise-path").replace("%", "\\%")) ) + promise["path"].replace("%", "\\%"))
with open(crond_folder + "/monitor-promises", "w") as fp: with open(crond_folder + "/monitor-promises", "w") as fp:
fp.write("\n".join(cron_line_list)) fp.write("\n".join(cron_line_list))
# create symlinks from monitor.conf
createSymlinksFromConfig((config, "monitor", "public-folder"), (config, "monitor", "public-path-list"))
createSymlinksFromConfig((config, "monitor", "private-folder"), (config, "monitor", "private-path-list"))
return 0 return 0
def loadConfig(pathes): def loadConfig(pathes, config=None):
if config is None:
config = ConfigParser.ConfigParser() config = ConfigParser.ConfigParser()
try:
config.read(pathes) config.read(pathes)
except ConfigParser.MissingSectionHeaderError:
traceback.print_exc()
return config return config
def fillPromiseDictFromFolder(promise_dict, folder):
for filename in os.listdir(folder):
path = os.path.join(folder, filename)
if os.path.isfile(path) and os.access(path, os.X_OK):
promise_dict[filename] = {"path": path, "configuration": ConfigParser.ConfigParser()}
def softConfigGet(config, *args, **kwargs): def softConfigGet(config, *args, **kwargs):
try: try:
return config.get(*args, **kwargs) return config.get(*args, **kwargs)
...@@ -127,14 +120,6 @@ def createSymlinksFromConfig(destination_folder_config_tuple, source_list_config ...@@ -127,14 +120,6 @@ def createSymlinksFromConfig(destination_folder_config_tuple, source_list_config
if e.errno != os.errno.EEXIST: if e.errno != os.errno.EEXIST:
raise raise
def newServiceName(name, name_dict):
part = name
count = 1
while name in name_dict:
name = part + "_" + str(count)
count += 1
return name
def mkdirAll(path): def mkdirAll(path):
try: try:
os.makedirs(path) os.makedirs(path)
......
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