Commit 16b33bfe authored by Alain Takoudjou's avatar Alain Takoudjou

monitor: add support for report script folder

parent 0f3ae9fb
...@@ -99,7 +99,7 @@ recipe = slapos.recipe.template:jinja2 ...@@ -99,7 +99,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 = cd7f386fe1b5066d8508758249b408d3 md5sum = b6da7709da533c5c8280e5e103809c58
context = context =
key apache_location apache:location key apache_location apache:location
key gzip_location gzip:location key gzip_location gzip:location
...@@ -130,13 +130,13 @@ depends = ...@@ -130,13 +130,13 @@ depends =
[monitor2-bin] [monitor2-bin]
<= monitor-template-script <= monitor-template-script
filename = monitor.py filename = monitor.py
md5sum = 31beec15d3c3cd7979d04ecb834c439a md5sum = 6db3d9fcfff32c556f2bedee804ffb47
[run-promise-py] [run-promise-py]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
template = ${:_profile_base_location_}/scripts/run-promise.py template = ${:_profile_base_location_}/scripts/run-promise.py
rendered = ${buildout:parts-directory}/monitor-scripts/run-promise.py rendered = ${buildout:parts-directory}/monitor-scripts/run-promise.py
md5sum = 8ba8b661c55f2c5a379e9e42573be486 md5sum = 5694920c5789f4d953cb5d41adfa7f8b
mode = 0755 mode = 0755
context = context =
raw python ${buildout:directory}/bin/${extra-eggs:interpreter} raw python ${buildout:directory}/bin/${extra-eggs:interpreter}
......
...@@ -70,7 +70,7 @@ etc = ${directory:etc} ...@@ -70,7 +70,7 @@ etc = ${directory:etc}
run = ${directory:monitor}/run run = ${directory:monitor}/run
#run = ${directory:scripts} #run = ${directory:scripts}
promises = ${directory:monitor-promise} promises = ${directory:monitor-promise}
report = ${directory:monitor-report} reports = ${directory:monitor-report}
pids = ${directory:run}/monitor pids = ${directory:run}/monitor
cgi-bin = ${directory:monitor}/cgi-bin cgi-bin = ${directory:monitor}/cgi-bin
webdav = ${directory:monitor}/webdav webdav = ${directory:monitor}/webdav
...@@ -134,6 +134,7 @@ root-title = ${monitor-instance-parameter:root-instance-title} ...@@ -134,6 +134,7 @@ root-title = ${monitor-instance-parameter:root-instance-title}
public-folder = ${monitor-directory:public} public-folder = ${monitor-directory:public}
private-folder = ${monitor-directory:private} private-folder = ${monitor-directory:private}
webdav-folder = ${monitor-directory:webdav} webdav-folder = ${monitor-directory:webdav}
report-folder = ${monitor-directory:reports}
web-folder = ${monitor-directory:web-dir} web-folder = ${monitor-directory:web-dir}
base-url = ${monitor-instance-parameter:monitor-base-url} base-url = ${monitor-instance-parameter:monitor-base-url}
monitor-hal-json = ${monitor-directory:public}/monitor.hal.json monitor-hal-json = ${monitor-directory:public}/monitor.hal.json
......
...@@ -94,6 +94,7 @@ class Monitoring(object): ...@@ -94,6 +94,7 @@ class Monitoring(object):
self.collector_db = config.get("monitor", "collector-db") self.collector_db = config.get("monitor", "collector-db")
self.collect_script = config.get("monitor", "collect-script") self.collect_script = config.get("monitor", "collect-script")
self.webdav_folder = config.get("monitor", "webdav-folder") self.webdav_folder = config.get("monitor", "webdav-folder")
self.report_script_folder = config.get("monitor", "report-folder")
self.webdav_url = '%s/share' % config.get("monitor", "base-url") self.webdav_url = '%s/share' % config.get("monitor", "base-url")
self.public_url = '%s/public' % config.get("monitor", "base-url") self.public_url = '%s/public' % config.get("monitor", "base-url")
self.status_history_folder = os.path.join(self.public_folder, 'history') self.status_history_folder = os.path.join(self.public_folder, 'history')
...@@ -106,6 +107,7 @@ class Monitoring(object): ...@@ -106,6 +107,7 @@ class Monitoring(object):
self.parameter_cfg_file = config.get("monitor", "parameter-file-path").strip() self.parameter_cfg_file = config.get("monitor", "parameter-file-path").strip()
self.config_folder = os.path.join(self.private_folder, 'config') self.config_folder = os.path.join(self.private_folder, 'config')
self.report_folder = os.path.join(self.private_folder, 'report')
self.promise_dict = {} self.promise_dict = {}
for promise_folder in self.promise_folder_list: for promise_folder in self.promise_folder_list:
...@@ -267,9 +269,11 @@ class Monitoring(object): ...@@ -267,9 +269,11 @@ class Monitoring(object):
raise raise
self.data_folder = os.path.join(self.private_folder, 'data', '.jio_documents') self.data_folder = os.path.join(self.private_folder, 'data', '.jio_documents')
self.report_folder = os.path.join(self.report_folder, '.jio_documents')
config_folder = os.path.join(self.config_folder, '.jio_documents') config_folder = os.path.join(self.config_folder, '.jio_documents')
mkdirAll(self.data_folder) mkdirAll(self.data_folder)
mkdirAll(config_folder) mkdirAll(config_folder)
mkdirAll(self.report_folder)
try: try:
os.symlink(os.path.join(self.private_folder, 'data'), os.symlink(os.path.join(self.private_folder, 'data'),
os.path.join(jio_private, 'data')) os.path.join(jio_private, 'data'))
...@@ -281,6 +285,11 @@ class Monitoring(object): ...@@ -281,6 +285,11 @@ class Monitoring(object):
except OSError, e: except OSError, e:
if e.errno != os.errno.EEXIST: if e.errno != os.errno.EEXIST:
raise raise
try:
os.symlink(self.report_folder, os.path.join(jio_private, 'report'))
except OSError, e:
if e.errno != os.errno.EEXIST:
raise
def makeConfigurationFiles(self): def makeConfigurationFiles(self):
config_folder = os.path.join(self.config_folder, '.jio_documents') config_folder = os.path.join(self.config_folder, '.jio_documents')
...@@ -385,6 +394,53 @@ class Monitoring(object): ...@@ -385,6 +394,53 @@ class Monitoring(object):
with open(self.monitor_hal_json, "w") as fp: with open(self.monitor_hal_json, "w") as fp:
json.dump(self.monitor_dict, fp) json.dump(self.monitor_dict, fp)
def generateReportCronEntries(self):
cron_line_list = []
# We should add the possibility to modify this parameter later from monitor interface
report_frequency = "*/30 * * * *"
report_name_list = [name.replace('.report.json', '')
for name in os.listdir(self.report_folder) if name.endswith('.report.json')]
for filename in os.listdir(self.report_script_folder):
report_script = os.path.join(self.report_script_folder, filename)
if os.path.isfile(report_script) and os.access(report_script, os.X_OK):
report_name = os.path.splitext(filename)[0]
report_json_path = "%s.report.json" % report_name
report_cmd_line = [
report_frequency,
self.promise_runner,
'--pid_path "%s"' % os.path.join(self.service_pid_folder,
"%s.pid" % filename),
'--output "%s"' % os.path.join(self.report_folder,report_json_path),
'--promise_script "%s"' % report_script,
'--promise_name "%s"' % report_name,
'--monitor_url "%s/jio_private/"' % self.webdav_url, # XXX hardcoded,
'--history_folder "%s"' % self.report_folder,
'--instance_name "%s"' % self.title,
'--hosting_name "%s"' % self.root_title,
'--promise_type "report"']
cron_line_list.append(' '.join(report_cmd_line))
if report_name in report_name_list:
report_name_list.pop(report_name_list.index(report_name))
# cleanup removed report json result
if report_name_list != []:
for report_name in report_name_list:
result_path = os.path.join(self.public_folder, '%s.report.json' % report_name)
if os.path.exists(result_path):
try:
os.unlink(result_path)
except OSError, e:
print "Error: Failed to delete %s" % result_path, str(e)
pass
with open(self.crond_folder + "/monitor-reports", "w") as freport:
freport.write("\n".join(cron_line_list))
def generateServiceCronEntries(self): def generateServiceCronEntries(self):
# XXX only if at least one configuration file is modified, then write in the cron # XXX only if at least one configuration file is modified, then write in the cron
#cron_line_list = ['PATH=%s\n' % os.environ['PATH']] #cron_line_list = ['PATH=%s\n' % os.environ['PATH']]
...@@ -401,13 +457,13 @@ class Monitoring(object): ...@@ -401,13 +457,13 @@ class Monitoring(object):
promise_cmd_line = [ promise_cmd_line = [
softConfigGet(service_config, "service", "frequency") or "* * * * *", softConfigGet(service_config, "service", "frequency") or "* * * * *",
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" % service_name), "%s.pid" % service_name),
'--output %s' % service_status_path, '--output "%s"' % service_status_path,
'--promise_script %s' % promise["path"], '--promise_script "%s"' % promise["path"],
'--promise_name "%s"' % service_name, '--promise_name "%s"' % service_name,
'--monitor_url "%s/jio_private/"' % self.webdav_url, # XXX hardcoded, '--monitor_url "%s/jio_private/"' % self.webdav_url, # XXX hardcoded,
'--history_folder %s' % self.status_history_folder, '--history_folder "%s"' % self.status_history_folder,
'--instance_name "%s"' % self.title, '--instance_name "%s"' % self.title,
'--hosting_name "%s"' % self.root_title] '--hosting_name "%s"' % self.root_title]
...@@ -442,6 +498,13 @@ class Monitoring(object): ...@@ -442,6 +498,13 @@ class Monitoring(object):
cronf.write(entry_line) cronf.write(entry_line)
def bootstrapMonitor(self): def bootstrapMonitor(self):
# 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()
# create symlinks from service configurations # create symlinks from service configurations
self.promise_items = self.promise_dict.items() self.promise_items = self.promise_dict.items()
for service_name, promise in self.promise_items: for service_name, promise in self.promise_items:
...@@ -457,12 +520,6 @@ class Monitoring(object): ...@@ -457,12 +520,6 @@ class Monitoring(object):
private_path_list.split(), private_path_list.split(),
service_name) service_name)
# 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()
# generate monitor.json # generate monitor.json
self.monitor_dict = {} self.monitor_dict = {}
self.generateMonitorHalJson() self.generateMonitorHalJson()
...@@ -474,6 +531,9 @@ class Monitoring(object): ...@@ -474,6 +531,9 @@ class Monitoring(object):
# put promises to a cron file # put promises to a cron file
self.generateServiceCronEntries() self.generateServiceCronEntries()
# put report script to cron
self.generateReportCronEntries()
# Generate parameters files and scripts # Generate parameters files and scripts
self.makeConfigurationFiles() self.makeConfigurationFiles()
......
...@@ -24,15 +24,18 @@ def parseArguments(): ...@@ -24,15 +24,18 @@ def parseArguments():
help='Promise script to execute.') help='Promise script to execute.')
parser.add_argument('--promise_name', parser.add_argument('--promise_name',
help='Title to give to this promise.') help='Title to give to this promise.')
parser.add_argument('--promise_type',
default='status',
help='Type of promise to execute. [status, report].')
parser.add_argument('--monitor_url', parser.add_argument('--monitor_url',
help='Monitor Instance website URL.') help='Monitor Instance website URL.')
parser.add_argument('--history_folder', parser.add_argument('--history_folder',
help='Path where old result file will be placed before generate a new json result file.') help='Path where old result file will be placed before generate a new json result file.')
parser.add_argument('--instance_name', parser.add_argument('--instance_name',
default='UNKNOW Software Instance', default='UNKNOWN Software Instance',
help='Software Instance name.') help='Software Instance name.')
parser.add_argument('--hosting_name', parser.add_argument('--hosting_name',
default='UNKNOW Hosting Subscription', default='UNKNOWN Hosting Subscription',
help='Hosting Subscription name.') help='Hosting Subscription name.')
return parser.parse_args() return parser.parse_args()
...@@ -74,14 +77,16 @@ def main(): ...@@ -74,14 +77,16 @@ def main():
updateStatusHistoryFolder( updateStatusHistoryFolder(
parser.promise_name, parser.promise_name,
parser.output, parser.output,
parser.history_folder parser.history_folder,
parser.promise_type
) )
with open(parser.output, "w") as outputfile: with open(parser.output, "w") as outputfile:
json.dump(status_json, outputfile) json.dump(status_json, outputfile)
os.remove(parser.pid_path) os.remove(parser.pid_path)
def updateStatusHistoryFolder(name, status_file, history_folder): def updateStatusHistoryFolder(name, status_file, history_folder, promise_type):
old_history_list = [] old_history_list = []
keep_item_amount = 25
history_path = os.path.join(history_folder, name, '.jio_documents') history_path = os.path.join(history_folder, name, '.jio_documents')
if not os.path.exists(status_file): if not os.path.exists(status_file):
return return
...@@ -96,18 +101,19 @@ def updateStatusHistoryFolder(name, status_file, history_folder): ...@@ -96,18 +101,19 @@ def updateStatusHistoryFolder(name, status_file, history_folder):
else: raise else: raise
with open(status_file, 'r') as sf: with open(status_file, 'r') as sf:
status_dict = json.loads(sf.read()) status_dict = json.loads(sf.read())
filename = '%s.status.json' % ( filename = '%s.%s.json' % (
status_dict['start-date'].replace(' ', '_').replace(':', '')) status_dict['start-date'].replace(' ', '_').replace(':', ''),
promise_type)
copyfile(status_file, os.path.join(history_path, filename)) copyfile(status_file, os.path.join(history_path, filename))
# Don't let history foler grow too much, keep 40 files # Don't let history foler grow too much, keep xx files
file_list = filter(os.path.isfile, file_list = filter(os.path.isfile,
glob.glob("%s/*.status.json" % history_path) glob.glob("%s/*.%s.json" % (history_path, promise_type))
) )
file_count = len(file_list) file_count = len(file_list)
if file_count > 40: if file_count > keep_item_amount:
file_list.sort(key=lambda x: os.path.getmtime(x)) file_list.sort(key=lambda x: os.path.getmtime(x))
while file_count > 40: while file_count > keep_item_amount:
to_delete = file_list.pop(0) to_delete = file_list.pop(0)
try: try:
os.unlink(to_delete) os.unlink(to_delete)
......
...@@ -63,7 +63,7 @@ mode = 0644 ...@@ -63,7 +63,7 @@ mode = 0644
recipe = slapos.recipe.template recipe = slapos.recipe.template
url = ${:_profile_base_location_}/instance-pull-backup.cfg.in url = ${:_profile_base_location_}/instance-pull-backup.cfg.in
output = ${buildout:directory}/instance-pull-backup.cfg output = ${buildout:directory}/instance-pull-backup.cfg
md5sum = 028dfc01dfb0d738e1b4793f67b24e8c md5sum = cb7acac7ab41bf44c20d6d03bfad8217
mode = 0644 mode = 0644
[template-replicated] [template-replicated]
......
...@@ -11,6 +11,7 @@ parts = ...@@ -11,6 +11,7 @@ parts =
## Monitor for pbs ## Monitor for pbs
monitor-base
monitor-check-resilient-feed-file monitor-check-resilient-feed-file
extends = ${monitor2-template:rendered} extends = ${monitor2-template:rendered}
...@@ -266,7 +267,7 @@ private-path-list += ...@@ -266,7 +267,7 @@ private-path-list +=
[monitor-check-resilient-feed-file] [monitor-check-resilient-feed-file]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
template = ${template-monitor-check-resilient-feed:location}/${template-monitor-check-resilient-feed:filename} template = ${template-monitor-check-resilient-feed:location}/${template-monitor-check-resilient-feed:filename}
rendered = $${monitor-directory:promises}/check-create-resilient-feed-files rendered = $${monitor-directory:reports}/check-create-resilient-feed-files
mode = 700 mode = 700
context = context =
key input_feed_directory directory:notifier-feeds key input_feed_directory directory:notifier-feeds
......
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