Commit 8b1572ea authored by Alain Takoudjou's avatar Alain Takoudjou

monitor: remove useless folders and information, always set date with utc timezone

some jio folders are not needed anymore, webdav is only needed for config folder.
Report results are placed in documents folder so they will not be synced automatically (we can get then when needed)
Use UTC timezone in json result instead of local time.
parent f3f875fd
...@@ -12,7 +12,7 @@ import hashlib ...@@ -12,7 +12,7 @@ import hashlib
import PyRSS2Gen import PyRSS2Gen
def getKey(item): def getKey(item):
return item.pubDate return item.source.name
class monitorFeed(object): class monitorFeed(object):
...@@ -27,23 +27,24 @@ class monitorFeed(object): ...@@ -27,23 +27,24 @@ class monitorFeed(object):
self.feed_url = feed_url self.feed_url = feed_url
def appendItem(self, item_dict): def appendItem(self, item_dict):
event_time = datetime.fromtimestamp(item_dict['change-time']) event_time = datetime.utcfromtimestamp(item_dict['change-time'])
description = item_dict.get('message', '') description = item_dict.get('message', '')
rss_item = PyRSS2Gen.RSSItem( rss_item = PyRSS2Gen.RSSItem(
categories = [item_dict['status']], categories = [item_dict['status']],
source = PyRSS2Gen.Source(item_dict['title'], self.public_url), source = PyRSS2Gen.Source(item_dict['title'], self.public_url),
title = '[%s] %s' % (item_dict['status'], item_dict['title']), title = '[%s] %s' % (item_dict['status'], item_dict['title']),
comments = description, description = "%s: %s\n\n%s" % (event_time, item_dict['status'], description),
description = "%s: %s\n%s" % (event_time, item_dict['status'], description),
link = self.private_url, link = self.private_url,
pubDate = event_time, pubDate = event_time,
guid = PyRSS2Gen.Guid(base64.b64encode("%s, %s" % (self.hosting_name, guid = PyRSS2Gen.Guid(base64.b64encode("%s, %s, %s" % (self.hosting_name,
item_dict['title']))) item_dict['title'], event_time)),
isPermaLink=False)
) )
self.rss_item_list.append(rss_item) self.rss_item_list.append(rss_item)
def genrss(self, output_file): def genrss(self, output_file):
### Build the rss feed ### Build the rss feed
# try to keep the list in the same order
sorted(self.rss_item_list, key=getKey) sorted(self.rss_item_list, key=getKey)
rss_feed = PyRSS2Gen.RSS2 ( rss_feed = PyRSS2Gen.RSS2 (
title = self.instance_name, title = self.instance_name,
...@@ -52,7 +53,7 @@ class monitorFeed(object): ...@@ -52,7 +53,7 @@ class monitorFeed(object):
lastBuildDate = self.report_date, lastBuildDate = self.report_date,
items = self.rss_item_list items = self.rss_item_list
) )
with open(output_file, 'w') as frss: with open(output_file, 'w') as frss:
frss.write(rss_feed.to_xml()) frss.write(rss_feed.to_xml())
...@@ -78,7 +79,7 @@ def generateStatisticsData(stat_file_path, content): ...@@ -78,7 +79,7 @@ def generateStatisticsData(stat_file_path, content):
content['date'], content['date'],
content['state']['success'], content['state']['success'],
content['state']['error'], content['state']['error'],
content['state']['warning']) '')
# append to file # append to file
if current_state: if current_state:
...@@ -98,27 +99,19 @@ def run(args_list): ...@@ -98,27 +99,19 @@ def run(args_list):
status_folder = monitor_config.get('monitor', 'public-folder') status_folder = monitor_config.get('monitor', 'public-folder')
base_url = monitor_config.get('monitor', 'base-url') base_url = monitor_config.get('monitor', 'base-url')
related_monitor_list = monitor_config.get("monitor", "monitor-url-list").split() related_monitor_list = monitor_config.get("monitor", "monitor-url-list").split()
statistic_folder = os.path.join(base_folder, 'data', '.jio_documents') statistic_folder = os.path.join(base_folder, 'documents')
# need webdav to update parameters
parameter_file = os.path.join(base_folder, 'config', '.jio_documents', 'config.json') parameter_file = os.path.join(base_folder, 'config', '.jio_documents', 'config.json')
feed_output = os.path.join(status_folder, 'feed') feed_output = os.path.join(status_folder, 'feed')
public_url = "%s/share/jio_public/" % base_url public_url = "%s/share/public/" % base_url
private_url = "%s/share/jio_private/" % base_url private_url = "%s/share/private/" % base_url
feed_url = "%s/public/feed" % base_url feed_url = "%s/public/feed" % base_url
error = warning = success = 0 error = success = 0
status = 'OK' status = 'OK'
promise_list = []
global_state_file = os.path.join(base_folder, 'monitor.global.json') global_state_file = os.path.join(base_folder, 'monitor.global.json')
public_state_file = os.path.join(status_folder, 'monitor.global.json') public_state_file = os.path.join(status_folder, 'monitor.global.json')
if not os.path.exists(statistic_folder):
try:
os.makedirs(statistic_folder)
except OSError, e:
if e.errno == os.errno.EEXIST and os.path.isdir(statistic_folder):
pass
else: raise
# search for all status files # search for all status files
file_list = filter(os.path.isfile, file_list = filter(os.path.isfile,
glob.glob("%s/*.status.json" % status_folder) glob.glob("%s/*.status.json" % status_folder)
...@@ -129,7 +122,7 @@ def run(args_list): ...@@ -129,7 +122,7 @@ def run(args_list):
else: else:
raise Exception("Cannot read instance configuration at %s" % instance_file) raise Exception("Cannot read instance configuration at %s" % instance_file)
report_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') report_date = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S')
monitor_feed = monitorFeed( monitor_feed = monitorFeed(
config.get('instance', 'name'), config.get('instance', 'name'),
config.get('instance', 'root-name'), config.get('instance', 'root-name'),
...@@ -147,29 +140,22 @@ def run(args_list): ...@@ -147,29 +140,22 @@ def run(args_list):
error += 1 error += 1
elif tmp_json['status'] == 'OK': elif tmp_json['status'] == 'OK':
success += 1 success += 1
elif tmp_json['status'] == 'WARNING':
warning += 1
tmp_json['time'] = tmp_json['start-date'].split(' ')[1]
promise_list.append(tmp_json)
monitor_feed.appendItem(tmp_json) monitor_feed.appendItem(tmp_json)
if error: if error:
status = 'ERROR' status = 'ERROR'
elif warning:
status = 'WARNING'
monitor_feed.genrss(feed_output) monitor_feed.genrss(feed_output)
global_state_dict = dict( global_state_dict = dict(
status=status, status=status,
state={ state={
'error': error, 'error': error,
'success': success, 'success': success
'warning': warning,
}, },
type='global', type='global', # bwd compatibility
portal_type='Software Instance',
date=report_date, date=report_date,
_links={"rss_url": {"href": "%s/public/feed" % base_url}, _links={"rss_url": {"href": feed_url},
"public_url": {"href": public_url}, "public_url": {"href": public_url},
"private_url": {"href": private_url} "private_url": {"href": private_url}
}, },
...@@ -179,13 +165,15 @@ def run(args_list): ...@@ -179,13 +165,15 @@ def run(args_list):
'memory_resource': 'monitor_resource_memory.data', 'memory_resource': 'monitor_resource_memory.data',
'io_resource': 'monitor_resource_io.data', 'io_resource': 'monitor_resource_io.data',
'monitor_process_state': 'monitor_resource.status'}, 'monitor_process_state': 'monitor_resource.status'},
_embedded={'promises': promise_list}, _embedded={},
) )
instance_dict = {} instance_dict = {}
global_state_dict['title'] = config.get('instance', 'name') global_state_dict['title'] = config.get('instance', 'name')
# XXX - hosting-title should be removed at some point in favour of specialise_title
global_state_dict['hosting-title'] = config.get('instance', 'root-name') global_state_dict['hosting-title'] = config.get('instance', 'root-name')
global_state_dict['specialise_title'] = config.get('instance', 'root-name')
global_state_dict['aggregate_reference'] = config.get('instance', 'computer')
if not global_state_dict['title']: if not global_state_dict['title']:
global_state_dict['title'] = 'Instance Monitoring' global_state_dict['title'] = 'Instance Monitoring'
...@@ -199,7 +187,7 @@ def run(args_list): ...@@ -199,7 +187,7 @@ def run(args_list):
global_state_dict['_embedded'].update({'instance' : instance_dict}) global_state_dict['_embedded'].update({'instance' : instance_dict})
if related_monitor_list: if related_monitor_list:
global_state_dict['_links']['related_monitor'] = [{'href': "%s/share/jio_public" % url} global_state_dict['_links']['related_monitor'] = [{'href': "%s/share/public" % url}
for url in related_monitor_list] for url in related_monitor_list]
if os.path.exists(parameter_file): if os.path.exists(parameter_file):
...@@ -210,10 +198,10 @@ def run(args_list): ...@@ -210,10 +198,10 @@ def run(args_list):
public_state_dict = dict( public_state_dict = dict(
status=status, status=status,
date=report_date, date=report_date,
_links={'monitor': {'href': '%s/share/jio_private/' % base_url}}, _links={'monitor': {'href': '%s/share/private/' % base_url}},
title=global_state_dict.get('title', '') title=global_state_dict.get('title', '')
) )
public_state_dict['hosting-title'] = global_state_dict.get('hosting-title', '') public_state_dict['specialise_title'] = global_state_dict.get('specialise_title', '')
public_state_dict['_links']['related_monitor'] = global_state_dict['_links'].get('related_monitor', []) public_state_dict['_links']['related_monitor'] = global_state_dict['_links'].get('related_monitor', [])
with open(global_state_file, 'w') as fglobal: with open(global_state_file, 'w') as fglobal:
......
...@@ -103,6 +103,7 @@ class Monitoring(object): ...@@ -103,6 +103,7 @@ class Monitoring(object):
self.config_folder = os.path.join(self.private_folder, 'config') self.config_folder = os.path.join(self.private_folder, 'config')
self.report_folder = self.private_folder self.report_folder = self.private_folder
self.data_folder = os.path.join(self.private_folder, 'documents')
self.promise_output_file = config.get("monitor", "promise-output-file") self.promise_output_file = config.get("monitor", "promise-output-file")
self.bootstrap_is_ok = True self.bootstrap_is_ok = True
...@@ -267,35 +268,22 @@ class Monitoring(object): ...@@ -267,35 +268,22 @@ class Monitoring(object):
return (report_name, "*/%s * * * *" % value) return (report_name, "*/%s * * * *" % value)
def configureFolders(self): def configureFolders(self):
# create symlinks from monitor.conf
self.createSymlinksFromConfig(self.public_folder, self.public_path_list)
self.createSymlinksFromConfig(self.private_folder, self.private_path_list)
# configure public and private folder # configure public and private folder
self.createSymlinksFromConfig(self.webdav_folder, [self.public_folder]) self.createSymlinksFromConfig(self.webdav_folder, [self.public_folder])
self.createSymlinksFromConfig(self.webdav_folder, [self.private_folder]) self.createSymlinksFromConfig(self.webdav_folder, [self.private_folder])
#configure jio_documents folder config_jio_folder = os.path.join(self.config_folder, '.jio_documents')
jio_public = os.path.join(self.webdav_folder, 'jio_public')
jio_private = os.path.join(self.webdav_folder, 'jio_private')
mkdirAll(jio_public)
mkdirAll(jio_private)
createSymlink(self.public_folder,
os.path.join(jio_public, '.jio_documents'))
createSymlink(self.private_folder,
os.path.join(jio_private, '.jio_documents'))
self.data_folder = os.path.join(self.private_folder, 'data', '.jio_documents')
self.document_folder = os.path.join(self.private_folder, 'documents')
config_folder = os.path.join(self.config_folder, '.jio_documents')
mkdirAll(self.data_folder) mkdirAll(self.data_folder)
mkdirAll(config_folder) mkdirAll(config_jio_folder)
createSymlink(os.path.join(self.private_folder, 'data'), # Cleanup private folder, remove files that should not be synced from private root dir
os.path.join(jio_private, 'data')) cleanup_file_list = glob.glob("%s/*.history.json" % self.private_folder)
createSymlink(self.config_folder, os.path.join(jio_private, 'config')) cleanup_file_list.extend(glob.glob("%s/*.report.json" % self.private_folder))
createSymlink(self.data_folder, self.document_folder) for file in cleanup_file_list:
# Cleanup private folder
for file in glob.glob("%s/*.history.json" % self.private_folder):
try: try:
os.unlink(file) os.unlink(file)
except OSError: except OSError:
...@@ -305,7 +293,6 @@ class Monitoring(object): ...@@ -305,7 +293,6 @@ class Monitoring(object):
config_folder = os.path.join(self.config_folder, '.jio_documents') config_folder = os.path.join(self.config_folder, '.jio_documents')
parameter_config_file = os.path.join(config_folder, 'config.parameters.json') parameter_config_file = os.path.join(config_folder, 'config.parameters.json')
parameter_file = os.path.join(config_folder, 'config.json') parameter_file = os.path.join(config_folder, 'config.json')
#mkdirAll(config_folder)
parameter_list = self.readInstanceConfiguration() parameter_list = self.readInstanceConfiguration()
description_dict = {} description_dict = {}
...@@ -336,10 +323,12 @@ class Monitoring(object): ...@@ -336,10 +323,12 @@ class Monitoring(object):
def generateOpmlFile(self, feed_url_list, output_file): def generateOpmlFile(self, feed_url_list, output_file):
if os.path.exists(output_file): if os.path.exists(output_file):
creation_date = datetime.fromtimestamp(os.path.getctime(output_file)).utcnow().strftime("%a, %d %b %Y %H:%M:%S +0000") creation_date = datetime.utcfromtimestamp(os.path.getctime(output_file))\
.strftime("%a, %d %b %Y %H:%M:%S +0000")
modification_date = datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S +0000") modification_date = datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S +0000")
else: else:
creation_date = modification_date = datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S +0000") creation_date = modification_date = datetime.utcnow()\
.strftime("%a, %d %b %Y %H:%M:%S +0000")
opml_content = OPML_START % {'creation_date': creation_date, opml_content = OPML_START % {'creation_date': creation_date,
'modification_date': modification_date, 'modification_date': modification_date,
...@@ -349,13 +338,13 @@ class Monitoring(object): ...@@ -349,13 +338,13 @@ class Monitoring(object):
opml_content += OPML_OUTLINE_FEED % {'title': self.title, opml_content += OPML_OUTLINE_FEED % {'title': self.title,
'html_url': self.public_url + '/feed', 'html_url': self.public_url + '/feed',
'xml_url': self.public_url + '/feed', 'xml_url': self.public_url + '/feed',
'global_url': "%s/jio_private/" % self.webdav_url} 'global_url': "%s/private/" % self.webdav_url}
for feed_url in feed_url_list: for feed_url in feed_url_list:
opml_content += OPML_OUTLINE_FEED % { opml_content += OPML_OUTLINE_FEED % {
'title': self.getMonitorTitleFromUrl(feed_url + "/share/public/"), 'title': self.getMonitorTitleFromUrl(feed_url + "/share/public/"),
'html_url': feed_url + '/public/feed', 'html_url': feed_url + '/public/feed',
'xml_url': feed_url + '/public/feed', 'xml_url': feed_url + '/public/feed',
'global_url': "%s/share/jio_private/" % feed_url} 'global_url': "%s/share/private/" % feed_url}
opml_content += OPML_END opml_content += OPML_END
...@@ -384,18 +373,17 @@ class Monitoring(object): ...@@ -384,18 +373,17 @@ class Monitoring(object):
report_script = os.path.join(self.report_script_folder, filename) report_script = os.path.join(self.report_script_folder, filename)
if os.path.isfile(report_script) and os.access(report_script, os.X_OK): if os.path.isfile(report_script) and os.access(report_script, os.X_OK):
report_name, frequency = self.getReportInfoFromFilename(filename) report_name, frequency = self.getReportInfoFromFilename(filename)
# report_name = os.path.splitext(filename)[0] report_json_name = "%s.report.json" % report_name
report_json_path = "%s.report.json" % report_name
report_cmd_line = [ report_cmd_line = [
frequency, frequency,
self.promise_runner, self.promise_runner,
'--pid_path "%s"' % os.path.join(self.service_pid_folder, '--pid_path "%s"' % os.path.join(self.service_pid_folder,
"%s.pid" % filename), "%s.pid" % filename),
'--output "%s"' % os.path.join(self.report_folder,report_json_path), '--output "%s"' % os.path.join(self.data_folder, report_json_name),
'--promise_script "%s"' % report_script, '--promise_script "%s"' % report_script,
'--promise_name "%s"' % report_name, '--promise_name "%s"' % report_name,
'--monitor_url "%s/jio_private/"' % self.webdav_url, # XXX hardcoded, '--monitor_url "%s/private/"' % self.webdav_url, # XXX hardcoded,
'--history_folder "%s"' % self.data_folder, '--history_folder "%s"' % self.data_folder,
'--instance_name "%s"' % self.title, '--instance_name "%s"' % self.title,
'--hosting_name "%s"' % self.root_title, '--hosting_name "%s"' % self.root_title,
...@@ -436,7 +424,7 @@ class Monitoring(object): ...@@ -436,7 +424,7 @@ class Monitoring(object):
'--promise_folder "%s"' % self.promise_folder, '--promise_folder "%s"' % self.promise_folder,
'--timeout_file "%s"' % self.promise_timeout_file, '--timeout_file "%s"' % self.promise_timeout_file,
'--monitor_promise_folder "%s"' % self.monitor_promise_folder, '--monitor_promise_folder "%s"' % self.monitor_promise_folder,
'--monitor_url "%s/jio_private/"' % self.webdav_url, # XXX hardcoded, '--monitor_url "%s/private/"' % self.webdav_url, # XXX hardcoded,
'--history_folder "%s"' % self.public_folder, '--history_folder "%s"' % self.public_folder,
'--instance_name "%s"' % self.title, '--instance_name "%s"' % self.title,
'--hosting_name "%s"' % self.root_title] '--hosting_name "%s"' % self.root_title]
...@@ -477,10 +465,6 @@ class Monitoring(object): ...@@ -477,10 +465,6 @@ class Monitoring(object):
with open(self.pid_file, 'w') as pid_file: with open(self.pid_file, 'w') as pid_file:
pid_file.write(str(os.getpid())) pid_file.write(str(os.getpid()))
# create symlinks from monitor.conf
self.createSymlinksFromConfig(self.public_folder, self.public_path_list)
self.createSymlinksFromConfig(self.private_folder, self.private_path_list)
self.configureFolders() self.configureFolders()
# Generate OPML file # Generate OPML file
......
...@@ -7,6 +7,7 @@ import subprocess ...@@ -7,6 +7,7 @@ import subprocess
import json import json
import psutil import psutil
import time import time
from datetime import datetime
from shutil import copyfile from shutil import copyfile
import glob import glob
import argparse import argparse
...@@ -68,9 +69,10 @@ class RunPromise(object): ...@@ -68,9 +69,10 @@ class RunPromise(object):
def runpromise(self): def runpromise(self):
if self.config.promise_folder: if self.config.promise_folder:
# run all promises from the given folder # run all promises from the given folder in a synchronous way
return self.runpromise_synchronous() return self.runpromise_synchronous()
# run the promises in a new process
if os.path.exists(self.config.pid_path): if os.path.exists(self.config.pid_path):
with open(self.config.pid_path, "r") as pidfile: with open(self.config.pid_path, "r") as pidfile:
try: try:
...@@ -84,7 +86,7 @@ class RunPromise(object): ...@@ -84,7 +86,7 @@ class RunPromise(object):
with open(self.config.pid_path, "w") as pidfile: with open(self.config.pid_path, "w") as pidfile:
process = self.executeCommand(self.config.promise_script) process = self.executeCommand(self.config.promise_script)
ps_process = psutil.Process(process.pid) ps_process = psutil.Process(process.pid)
start_date = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(ps_process.create_time())) start_date = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S')
pidfile.write(str(process.pid)) pidfile.write(str(process.pid))
status_json = self.generateStatusJsonFromProcess(process, start_date=start_date) status_json = self.generateStatusJsonFromProcess(process, start_date=start_date)
...@@ -94,6 +96,8 @@ class RunPromise(object): ...@@ -94,6 +96,8 @@ class RunPromise(object):
status_json['instance'] = self.config.instance_name status_json['instance'] = self.config.instance_name
status_json['hosting_subscription'] = self.config.hosting_name status_json['hosting_subscription'] = self.config.hosting_name
status_json['type'] = self.config.promise_type status_json['type'] = self.config.promise_type
status_json['portal_type'] = "promise" if \
self.config.promise_type == "status" else self.config.promise_type
# Save the lastest status change date (needed for rss) # Save the lastest status change date (needed for rss)
status_json['change-time'] = ps_process.create_time() status_json['change-time'] = ps_process.create_time()
...@@ -112,12 +116,19 @@ class RunPromise(object): ...@@ -112,12 +116,19 @@ class RunPromise(object):
self.config.history_folder, self.config.history_folder,
self.config.promise_type self.config.promise_type
) )
with open(self.config.output, "w") as outputfile: # write the promise in a tmp file the move to promise output file
# this reduce conflict error on read/write at sametime
output_tmp = '%s.tmp' % self.config.output
with open(output_tmp, "w") as outputfile:
json.dump(status_json, outputfile) json.dump(status_json, outputfile)
os.rename(output_tmp, self.config.output)
os.remove(self.config.pid_path) os.remove(self.config.pid_path)
def runpromise_synchronous(self):
def runpromise_synchronous(self):
"""
run all promises in sequential ways
"""
if os.path.exists(self.config.pid_path): if os.path.exists(self.config.pid_path):
# Check if another run promise is running # Check if another run promise is running
with open(self.config.pid_path) as fpid: with open(self.config.pid_path) as fpid:
...@@ -155,14 +166,19 @@ class RunPromise(object): ...@@ -155,14 +166,19 @@ class RunPromise(object):
for status_dict in status_list: for status_dict in status_list:
status_dict.update(base_dict) status_dict.update(base_dict)
if previous_state_dict.has_key(status_dict['title']): if previous_state_dict.has_key(status_dict['title']):
status, time = previous_state_dict[status_dict['title']].split('#') status, change_time = previous_state_dict[status_dict['title']].split('#')
if status_dict['status'] == status: if status_dict['status'] == status:
status_dict['change-time'] = float(time) status_dict['change-time'] = float(change_time)
promise_result_file = os.path.join(self.config.output, promise_result_file = os.path.join(self.config.output,
"%s.status.json" % status_dict['title']) "%s.status.json" % status_dict['title'])
with open(promise_result_file, "w") as outputfile: # write the promise in a tmp file the move to promise output file
# this reduce conflict error on read/write at sametime
promise_tmp_file = '%s.tmp' % promise_result_file
with open(promise_tmp_file, "w") as outputfile:
json.dump(status_dict, outputfile) json.dump(status_dict, outputfile)
os.rename(promise_tmp_file, promise_result_file)
new_state_dict[status_dict['title']] = '%s#%s' % (status_dict['status'], new_state_dict[status_dict['title']] = '%s#%s' % (status_dict['status'],
status_dict['change-time']) status_dict['change-time'])
self.updateStatusHistoryFolder( self.updateStatusHistoryFolder(
...@@ -216,6 +232,7 @@ class RunPromise(object): ...@@ -216,6 +232,7 @@ class RunPromise(object):
status_dict.pop('title', '') status_dict.pop('title', '')
status_dict.pop('instance', '') status_dict.pop('instance', '')
status_dict.pop('type', '') status_dict.pop('type', '')
status_dict.pop('portal_type', '')
with open (history_file, mode="r+") as f_history: with open (history_file, mode="r+") as f_history:
f_history.seek(0,2) f_history.seek(0,2)
...@@ -298,9 +315,10 @@ class RunPromise(object): ...@@ -298,9 +315,10 @@ class RunPromise(object):
promise_name = os.path.basename(command[0]) promise_name = os.path.basename(command[0])
result_dict = { result_dict = {
"status": "ERROR", "status": "ERROR",
"type": "status", "type": "status", # keep compatibility
"portal_type": "promise",
"title": promise_name, "title": promise_name,
"start-date" : time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())), "start-date" : datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S'),
"change-time": time.time() "change-time": time.time()
} }
...@@ -333,7 +351,7 @@ class RunPromise(object): ...@@ -333,7 +351,7 @@ class RunPromise(object):
message = process_handler.stderr.read() message = process_handler.stderr.read()
if message is None: if message is None:
message = process_handler.stdout.read() or "" message = process_handler.stdout.read() or ""
message += '\nPROMISE TIME OUT AFTER %s SECONDS' % self.promise_timeout message += '\nPROMISE TIMED OUT AFTER %s SECONDS' % self.promise_timeout
result_dict["message"] = message result_dict["message"] = message
promise_result_list.append(result_dict) promise_result_list.append(result_dict)
......
...@@ -76,7 +76,7 @@ promise-output-file = %(base_dir)s/monitor-bootstrap-status ...@@ -76,7 +76,7 @@ promise-output-file = %(base_dir)s/monitor-bootstrap-status
promise-runner = %(promise_run_script)s promise-runner = %(promise_run_script)s
""" """
self.opml_outline = """<outline text="Monitoring RSS Feed list"><outline text="%(title)s" title="%(title)s" type="rss" version="RSS" htmlUrl="%(base_url)s/public/feed" xmlUrl="%(base_url)s/public/feed" url="%(base_url)s/share/jio_private/" />""" self.opml_outline = """<outline text="%(title)s" title="%(title)s" type="rss" version="RSS" htmlUrl="%(base_url)s/public/feed" xmlUrl="%(base_url)s/public/feed" url="%(base_url)s/share/private/" />"""
def tearDown(self): def tearDown(self):
if os.path.exists(self.base_dir): if os.path.exists(self.base_dir):
...@@ -122,12 +122,12 @@ promise-runner = %(promise_run_script)s ...@@ -122,12 +122,12 @@ promise-runner = %(promise_run_script)s
promise_command_list = cronf.read() promise_command_list = cronf.read()
if not sequential: if not sequential:
promise_entry = '* * * * * sleep $((1 + RANDOM %% 20)) && %(promise_run_script)s --pid_path "%(promise_runner_pid)s" --output "%(public_folder)s" --promise_folder "%(promise_folder)s" --timeout_file "None" --monitor_promise_folder "%(monitor_promise_folder)s" --monitor_url "%(base_url)s/share/jio_private/" --history_folder "%(base_dir)s/public" --instance_name "%(title)s" --hosting_name "%(root_title)s"' promise_entry = '* * * * * sleep $((1 + RANDOM %% 20)) && %(promise_run_script)s --pid_path "%(promise_runner_pid)s" --output "%(public_folder)s" --promise_folder "%(promise_folder)s" --timeout_file "None" --monitor_promise_folder "%(monitor_promise_folder)s" --monitor_url "%(base_url)s/share/private/" --history_folder "%(base_dir)s/public" --instance_name "%(title)s" --hosting_name "%(root_title)s"'
entry_line = promise_entry % self.monitor_config_dict entry_line = promise_entry % self.monitor_config_dict
self.assertTrue(entry_line in promise_command_list, self.assertTrue(entry_line in promise_command_list,
"%s not in %s" %(entry_line, promise_command_list)) "%s not in %s" %(entry_line, promise_command_list))
else: else:
promise_entry = '* * * * * sleep $((1 + RANDOM %% 30)) &&%(promise_run_script)s --pid_path "%(promise_pid)s" --output "%(promise_output)s" --promise_script "%(promise_executable)s" --promise_name "%(promise_name)s" --monitor_url "%(base_url)s/share/jio_private/" --history_folder "%(base_dir)s/public" --instance_name "%(title)s" --hosting_name "%(root_title)s"' promise_entry = '* * * * * sleep $((1 + RANDOM %% 30)) &&%(promise_run_script)s --pid_path "%(promise_pid)s" --output "%(promise_output)s" --promise_script "%(promise_executable)s" --promise_name "%(promise_name)s" --monitor_url "%(base_url)s/share/private/" --history_folder "%(base_dir)s/public" --instance_name "%(title)s" --hosting_name "%(root_title)s"'
promise_dir = os.path.join(self.base_dir, 'promise') promise_dir = os.path.join(self.base_dir, 'promise')
for filename in os.listdir(promise_dir): for filename in os.listdir(promise_dir):
...@@ -142,9 +142,9 @@ promise-runner = %(promise_run_script)s ...@@ -142,9 +142,9 @@ promise-runner = %(promise_run_script)s
self.assertTrue(entry_line in promise_command_list) self.assertTrue(entry_line in promise_command_list)
def check_report(self): def check_report(self):
promise_entry = '* * * * * %(promise_run_script)s --pid_path "%(promise_pid)s" --output "%(promise_output)s" --promise_script "%(promise_executable)s" --promise_name "%(promise_name)s" --monitor_url "%(base_url)s/share/jio_private/" --history_folder "%(data_dir)s" --instance_name "%(title)s" --hosting_name "%(root_title)s" --promise_type "report"' promise_entry = '* * * * * %(promise_run_script)s --pid_path "%(promise_pid)s" --output "%(promise_output)s" --promise_script "%(promise_executable)s" --promise_name "%(promise_name)s" --monitor_url "%(base_url)s/share/private/" --history_folder "%(data_dir)s" --instance_name "%(title)s" --hosting_name "%(root_title)s" --promise_type "report"'
promise_dir = os.path.join(self.base_dir, 'monitor-report') promise_dir = os.path.join(self.base_dir, 'monitor-report')
data_dir = os.path.join(self.base_dir, 'private', 'data', '.jio_documents') data_dir = os.path.join(self.base_dir, 'private', 'documents')
promise_cron = os.path.join(self.base_dir, 'cron.d', 'monitor-reports') promise_cron = os.path.join(self.base_dir, 'cron.d', 'monitor-reports')
self.assertTrue(os.path.exists(promise_cron)) self.assertTrue(os.path.exists(promise_cron))
...@@ -154,7 +154,7 @@ promise-runner = %(promise_run_script)s ...@@ -154,7 +154,7 @@ promise-runner = %(promise_run_script)s
for filename in os.listdir(promise_dir): for filename in os.listdir(promise_dir):
promise_dict = dict( promise_dict = dict(
promise_pid=os.path.join(self.base_dir, 'run', '%s.pid' % filename), promise_pid=os.path.join(self.base_dir, 'run', '%s.pid' % filename),
promise_output=os.path.join(self.base_dir, 'private', '%s.report.json' % filename), promise_output=os.path.join(data_dir, '%s.report.json' % filename),
promise_executable=os.path.join(promise_dir, filename), promise_executable=os.path.join(promise_dir, filename),
promise_name=filename, promise_name=filename,
data_dir=data_dir data_dir=data_dir
...@@ -239,9 +239,6 @@ promise-runner = %(promise_run_script)s ...@@ -239,9 +239,6 @@ promise-runner = %(promise_run_script)s
self.checkOPML([self.monitor_config_dict['base_url']]) self.checkOPML([self.monitor_config_dict['base_url']])
# Check jio webdav folder
self.assertTrue(os.path.exists(os.path.join(self.base_dir, 'webdav/jio_public')))
self.assertTrue(os.path.exists(os.path.join(self.base_dir, 'webdav/jio_private')))
# check symlink configured # check symlink configured
self.check_symlink(folder_one, os.path.join(self.base_dir, 'public', 'folderOne')) self.check_symlink(folder_one, os.path.join(self.base_dir, 'public', 'folderOne'))
self.check_symlink(folder_two, os.path.join(self.base_dir, 'public', 'folderTwo')) self.check_symlink(folder_two, os.path.join(self.base_dir, 'public', 'folderTwo'))
...@@ -258,7 +255,8 @@ promise-runner = %(promise_run_script)s ...@@ -258,7 +255,8 @@ promise-runner = %(promise_run_script)s
# check that configuration folder exist # check that configuration folder exist
self.assertTrue(os.path.exists(os.path.join(self.base_dir, 'private/config'))) self.assertTrue(os.path.exists(os.path.join(self.base_dir, 'private/config')))
self.assertTrue(os.path.exists(os.path.join(self.base_dir, 'private/data'))) # Check jio webdav folder
self.assertTrue(os.path.exists(os.path.join(self.base_dir, 'private/config/.jio_documents')))
self.assertTrue(os.path.exists(os.path.join(self.base_dir, 'private/documents'))) self.assertTrue(os.path.exists(os.path.join(self.base_dir, 'private/documents')))
def test_monitor_bootstrap_promises(self): def test_monitor_bootstrap_promises(self):
......
# -*- coding: utf-8 -*-
import os, time
import sys
import shutil
import tempfile
import unittest
import json
from slapos.monitor import globalstate
from slapos.monitor.runpromise import RunPromise, parseArguments
from slapos.monitor.monitor import Monitoring
class MonitorGlobalTest(unittest.TestCase):
def setUp(self):
self.base_dir = tempfile.mkdtemp()
os.mkdir(os.path.join(self.base_dir, 'promise'))
os.mkdir(os.path.join(self.base_dir, 'monitor-promise'))
os.mkdir(os.path.join(self.base_dir, 'public'))
os.mkdir(os.path.join(self.base_dir, 'private'))
os.mkdir(os.path.join(self.base_dir, 'cron.d'))
os.mkdir(os.path.join(self.base_dir, 'logrotate.d'))
os.mkdir(os.path.join(self.base_dir, 'monitor-report'))
os.mkdir(os.path.join(self.base_dir, 'webdav'))
os.mkdir(os.path.join(self.base_dir, 'run'))
self.writeContent(os.path.join(self.base_dir, 'param'), '12345')
self.writeContent(os.path.join(self.base_dir, '.monitor_pwd'), 'bcuandjy')
self.writeContent(os.path.join(self.base_dir, 'test-httpd-cors.cfg'), '')
self.writeContent(os.path.join(self.base_dir, 'monitor-htpasswd'), '12345')
self.writeContent(os.path.join(self.base_dir, 'instance.cfg'), """[instance]
name = Monitor
root-name = Monitor ROOT
computer = COMP-1234
ipv4 = 10.0.151.118
ipv6 = 2001:34c:1254:df3:89::5df3
software-release = http://some.url.com/software.cfg
software-type = default
partition = slappart10""")
self.monitor_config_file = os.path.join(self.base_dir, 'monitor.conf')
self.public_dir = os.path.join(self.base_dir, 'public')
self.private_dir = os.path.join(self.base_dir, 'private')
self.monitor_config_dict = dict(
base_dir=self.base_dir,
root_title="Monitor ROOT",
title="Monitor",
url_list="",
base_url="https://monitor.test.com",
monitor_promise_folder=os.path.join(self.base_dir, 'monitor-promise'),
promise_folder=os.path.join(self.base_dir, 'promise'),
promise_runner_pid=os.path.join(self.base_dir, 'run', 'monitor-promises.pid'),
public_folder=os.path.join(self.base_dir, 'public'),
public_path_list="",
private_path_list="",
promise_run_script="/bin/echo",
collect_run_script="/bin/echo",
statistic_script="/bin/echo"
)
self.monitor_conf = """[monitor]
parameter-file-path = %(base_dir)s/knowledge0.cfg
promise-folder = %(base_dir)s/promise
service-pid-folder = %(base_dir)s/run
monitor-promise-folder = %(base_dir)s/monitor-promise
private-folder = %(base_dir)s/private
public-folder = %(base_dir)s/public
public-path-list = %(public_path_list)s
private-path-list = %(private_path_list)s
crond-folder = %(base_dir)s/cron.d
logrotate-folder = %(base_dir)s/logrotate.d
report-folder = %(base_dir)s/monitor-report
root-title = %(root_title)s
pid-file = %(base_dir)s/monitor.pid
parameter-list =
raw monitor-user admin
file sample %(base_dir)s/param
htpasswd monitor-password %(base_dir)s/.monitor_pwd admin %(base_dir)s/monitor-htpasswd
httpdcors cors-domain %(base_dir)s/test-httpd-cors.cfg /bin/echo
webdav-folder = %(base_dir)s/webdav
collect-script = %(collect_run_script)s
statistic-script = %(statistic_script)s
python = python
monitor-url-list = %(url_list)s
collector-db =
base-url = %(base_url)s
title = %(title)s
service-pid-folder = %(base_dir)s/run
promise-output-file = %(base_dir)s/monitor-bootstrap-status
promise-runner = %(promise_run_script)s
"""
def tearDown(self):
if os.path.exists(self.base_dir):
shutil.rmtree(self.base_dir)
def writeContent(self, file_path, config):
with open(file_path, 'w') as cfg:
cfg.write(config)
def writePromise(self, name, success=True):
if success:
result_dict = {'output': 'success', 'code': 0}
else:
result_dict = {'output': 'error', 'code': 1}
content = """#!/bin/sh
echo "%(output)s"
exit %(code)s
""" % result_dict
promise_path = os.path.join(self.base_dir, 'promise', name)
self.writeContent(promise_path, content)
os.chmod(promise_path, 0755)
return promise_path
def getPromiseParser(self):
pid_path = os.path.join(self.base_dir, 'run', 'monitor-promise.pid')
promise_cmd = [
'--pid_path',
'%s' % pid_path, '--output', os.path.join(self.base_dir, 'public'),
'--promise_folder', os.path.join(self.base_dir, 'promise'),
'--monitor_promise_folder', os.path.join(self.base_dir, 'monitor-promise'),
'--promise_type', 'status',
'--monitor_url', 'https://monitor.test.com/share/private/',
'--history_folder', os.path.join(self.base_dir, 'public'),
'--instance_name', 'Monitor', '--hosting_name', 'Monitor ROOT']
arg_parser = parseArguments()
return arg_parser.parse_args(promise_cmd)
def test_monitor_instance_state(self):
config_content = self.monitor_conf % self.monitor_config_dict
self.writeContent(self.monitor_config_file, config_content)
instance = Monitoring(self.monitor_config_file)
instance.bootstrapMonitor()
self.writePromise('promise_1')
self.writePromise('promise_2', success=False)
self.writePromise('promise_3', success=False)
self.writePromise('promise_4')
parser = self.getPromiseParser()
promise_runner = RunPromise(parser)
promise_runner.runpromise()
self.assertTrue(os.path.exists(os.path.join(self.public_dir, 'promise_1.status.json')))
self.assertTrue(os.path.exists(os.path.join(self.public_dir, 'promise_2.status.json')))
self.assertTrue(os.path.exists(os.path.join(self.public_dir, 'promise_3.status.json')))
self.assertTrue(os.path.exists(os.path.join(self.public_dir, 'promise_4.status.json')))
# generate instance state files
globalstate.run([self.monitor_config_file, os.path.join(self.base_dir, 'instance.cfg')])
self.assertTrue(os.path.exists(os.path.join(self.public_dir, 'feed')))
self.assertTrue(os.path.exists(os.path.join(self.public_dir, 'monitor.global.json')))
self.assertTrue(os.path.exists(os.path.join(self.private_dir, 'monitor.global.json')))
expected_result = """{
"status": "ERROR",
"_embedded": {
"instance": {
"partition": "slappart10",
"ipv6": "2001:34c:1254:df3:89::5df3",
"computer": "COMP-1234",
"ipv4": "10.0.151.118",
"software-release": "http://some.url.com/software.cfg",
"software-type": "default"
}
},
"parameters": [{
"key": "",
"value": "admin",
"title": "monitor-user"
}, {
"key": "sample",
"value": "12345",
"title": "sample"
}, {
"key": "monitor-password",
"value": "bcuandjy",
"title": "monitor-password"
}, {
"key": "cors-domain",
"value": "",
"title": "cors-domain"
}],
"title": "Monitor",
"data": {
"process_state": "monitor_process_resource.status",
"io_resource": "monitor_resource_io.data",
"state": "monitor_state.data",
"memory_resource": "monitor_resource_memory.data",
"process_resource": "monitor_resource_process.data",
"monitor_process_state": "monitor_resource.status"
},
"portal_type": "instance_state",
"state": {
"success": 2,
"error": 2
},
"_links": {
"rss_url": {
"href": "https://monitor.test.com/public/feed"
},
"public_url": {
"href": "https://monitor.test.com/share/public/"
},
"private_url": {
"href": "https://monitor.test.com/share/private/"
}
},
"computer_reference": "COMP-1234",
"type": "global",
"hosting-title": "Monitor ROOT"
}"""
with open(os.path.join(self.private_dir, 'monitor.global.json')) as r:
result = json.loads(r.read().decode("utf-8"))
result.pop("date")
self.assertEquals(result,
json.loads(expected_result))
# all promises are OK now
self.writePromise('promise_2', success=True)
self.writePromise('promise_3', success=True)
promise_runner.runpromise()
globalstate.run([self.monitor_config_file, os.path.join(self.base_dir, 'instance.cfg')])
expected_result_dict = json.loads(expected_result)
expected_result_dict["status"] = "OK"
expected_result_dict["state"] = {'error': 0, 'success': 4}
with open(os.path.join(self.private_dir, 'monitor.global.json')) as r:
result = json.loads(r.read().decode("utf-8"))
result.pop("date")
self.assertEquals(result,
expected_result_dict)
This diff is collapsed.
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