Commit c2913c92 authored by Alain Takoudjou's avatar Alain Takoudjou Committed by Tristan Cavelier

kvm: first deployment of new monitor stack

parent 9312f960
......@@ -90,7 +90,7 @@ command =
[template]
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/instance.cfg.in
md5sum = 41eb12b66bd1af86b1b98b2166e86417
md5sum = 4aa10c9cb6b4c2092e1f9effc981ba09
output = ${buildout:directory}/template.cfg
mode = 0644
......@@ -98,7 +98,7 @@ mode = 0644
recipe = hexagonit.recipe.download
url = ${:_profile_base_location_}/instance-kvm.cfg.jinja2
mode = 644
md5sum = 52e115fe1aaf232994af9037bf7c292c
md5sum = c6d616fc3922c28a502935963a00da2b
download-only = true
on-update = true
......@@ -179,6 +179,14 @@ mode = 0644
download-only = true
filename = ansible-promise.in
[ansible-monitor-script]
recipe = hexagonit.recipe.download
url = ${:_profile_base_location_}/monitor/ansibleReport.py
md5sum = 7a1be56978e043467f4f071cbae34b3c
mode = 0644
download-only = true
filename = ansibleReport.py
[template-apache-conf]
recipe = hexagonit.recipe.download
url = ${:_profile_base_location_}/template/apache.conf.in
......@@ -219,4 +227,3 @@ context =
raw openssl_executable_location ${openssl:location}/bin/openssl
raw template_apache_conf ${template-apache-conf:location}/${template-apache-conf:filename}
......@@ -29,22 +29,28 @@ parts =
frontend-promise
{% if monitor -%}
# monitor parts
cron-entry-monitor
cron-entry-rss
deploy-index
deploy-status-history-cgi
deploy-status-cgi
# cron-entry-monitor
# cron-entry-rss
# deploy-index
# deploy-status-history-cgi
# deploy-status-cgi
# deploy-logfile-cgi
# deploy-resource-consumption-monitoring-cgi
setup-static-files
public-symlink
cgi-httpd-wrapper
cgi-httpd-graceful-wrapper
monitor-promise
monitor-instance-log-access
monitor-access-log
monitor-access-public
# setup-static-files
# public-symlink
# cgi-httpd-wrapper
# cgi-httpd-graceful-wrapper
# monitor-promise
# monitor-instance-log-access
# monitor-access-log
# monitor-access-public
# monitor-frontend-promise
cron-entry-logrotate
monitor
run-ansible-monitor
start-monitor
ca-httpd
monitor-promise
{% endif -%}
{% if slapparameter_dict.get('document-host', '') %}
cluster-url-path
......@@ -327,14 +333,50 @@ port = ${httpd:port}
{% if monitor == 'true' -%}
[monitor-access-log]
< = monitor-directory-access
source = ${directory:log}
#< = monitor-directory-access
#source = ${directory:log}
[monitor-access-public]
< = monitor-directory-access
source = ${directory:public}
#< = monitor-directory-access
#source = ${directory:public}
[monitor-directory]
ansible-public = ${:public}/ansible-report
ansible-private = ${:private}/ansible-report
[monitor-parameters]
[monitor-symlink]
public-path =
${directory:log}
${directory:public}
private-path =
[monitor-kvm-ansible]
recipe = slapos.recipe.template:jinja2
template = {{ monitor_service_template_conf }}
rendered = ${monitor-directory:services-conf}/ansible-report.conf
name = ansible-report
title = kvm Ansible report
executable-file = ${directory:scripts}/ansible-kvm-report
context =
key name :name
key public_path_list monitor-symlink:public-path
key private_path_list monitor-symlink:private-path
key script_path :executable-file
key title :title
raw frequency */5 * * * *
section parameters ansible-parameters-dict
[ansible-parameters-dict]
status_path = ${monitor-directory:ansible-public}/status.json
public_folder = ${monitor-directory:ansible-public}
private_folder = ${monitor-directory:ansible-private}
[run-ansible-monitor]
recipe = slapos.cookbook:wrapper
command-line = python {{ ansible_report_script }} ${ansible-parameters-dict:status_path}
wrapper-path = ${monitor-kvm-ansible:executable-file}
[monitor-httpd-conf]
port = 8026
{% if slapparameter_dict.get('document-host', '') and slapparameter_dict.get('document-port', '') -%}
......@@ -349,7 +391,7 @@ name = Monitor {{ slapparameter_dict.get('name', '') }} Frontend
# XXX We have hardcoded SR URL here.
software-url = http://git.erp5.org/gitweb/slapos.git/blob_plain/HEAD:/software/apache-frontend/software.cfg
slave = true
config-url = ${monitor-parameters:url}
config-url = ${monitor-httpd-conf:url}
software-type = {{ slapparameter_dict.get('monitor-frontend-software-type', frontend_software_type) }}
return = site_url domain
......@@ -398,7 +440,6 @@ tap-ipv4 = ${slap-network-information:tap-ipv4}
{% endif %}
{% if monitor -%}
monitor_url = ${request-monitor-frontend:connection-site_url}
monitor_v6_url = ${monitor-parameters:url}
{% endif -%}
{% if use_tap == 'true' and tap_network_dict.has_key('ipv4') -%}
......
......@@ -84,11 +84,13 @@ context =
key storage_dict slap-configuration:storage-dict
key tap_network_dict slap-configuration:tap-network-information-dict
raw ansible_promise_tpl ${template-ansible-promise:location}/${template-ansible-promise:filename}
raw ansible_report_script ${ansible-monitor-script:location}/${ansible-monitor-script:filename}
raw curl_executable_location ${curl:location}/bin/curl
raw dash_executable_location ${dash:location}/bin/dash
raw dcron_executable_location ${dcron:location}/sbin/crond
raw debian_amd64_netinst_location ${debian-amd64-netinst.iso:location}/${debian-amd64-netinst.iso:filename}
raw logrotate_cfg ${template-logrotate-base:rendered}
raw monitor_service_template_conf ${monitor-service-template-conf:location}/${monitor-service-template-conf:filename}
raw novnc_location ${noVNC:location}
raw netcat_bin ${netcat:location}/bin/netcat
raw openssl_executable_location ${openssl:location}/bin/openssl
......@@ -97,7 +99,7 @@ context =
raw sixtunnel_executable_location ${6tunnel:location}/bin/6tunnel
raw template_httpd_cfg ${template-httpd:rendered}
raw template_content ${template-content:location}/${template-content:filename}
raw template_monitor ${monitor-template:output}
raw template_monitor ${monitor-site-template:rendered}
raw websockify_executable_location ${buildout:directory}/bin/websockify
template-parts-destination = ${template-parts:destination}
template-replicated-destination = ${template-replicated:destination}
......
#!/usr/bin/env python
# Parse Ansible result log file and and generate a report
import os, time
import json
import sqlite3
from datetime import datetime, timedelta
import sys
FIELDS = ['cmd', 'command', 'start', 'end', 'delta', 'msg', 'stdout', 'stderr',
'response', 'status_code', 'url', 'dest']
class ansibleReport(object):
def __init__(self, db_path,
ansible_log_dir,
name):
self.db_path = db_path
self.ansible_log_dir = ansible_log_dir
self.name = name
self.result_OK = '127.0.0.1_OK'
self.result_failed = '127.0.0.1_FAILED'
self.result_failed_ignore = '127.0.0.1_FAILED_INGORED' # tipo in ansible log upload pluging
self.date_format = '%Y-%m-%d %H:%M:%S'
self.day_format = '%Y-%m-%d'
self._init_db()
def _init_db(self):
db = sqlite3.connect(self.db_path)
c = db.cursor()
c.executescript("""
CREATE TABLE IF NOT EXISTS ansible_report (
name VARCHAR(40),
reportdate VARCHAR(15),
createdate VARCHAR(15),
status VARCHAR(20),
success_count INTEGER,
ignored_count INTEGER,
failed_count INTEGER,
ignored TEXT,
failed TEXT,
success TEXT);
""")
db.commit()
db.close()
def connect_db(self):
db = sqlite3.connect(self.db_path)
return db
def insertEntryDb(self, table_name, data_dict):
db = self.connect_db()
columns = data_dict.keys()
entries = ', '.join(columns)
values = '?' + ', ?' * (len(columns)-1)
sql_string = "insert into %s(%s) values (%s)" % (
table_name, entries, values)
tuple_data = ()
for key in columns:
tuple_data += (data_dict[key],)
db.execute(sql_string, tuple_data)
db.commit()
db.close()
def selectEntriesDb(self, fields=[], start_date=None, limit=0, success=None, order='DESC', where=""):
db = self.connect_db()
entries = ', '.join(fields) if fields else '*'
query = "select %s from ansible_report " % entries
where = " and %s" % where if where else ""
if not start_date:
start_date = datetime.utcnow().strftime(self.day_format)
tuple_values = (start_date,)
if success is not None:
status = 'OK' if success else 'FAILLED'
query += "where createdate>=? and status=? %s order by createdate %s" % (where, order)
tuple_values += (status,)
else:
query += "where createdate>=? %s order by createdate %s" % (where, order)
if limit:
query += " limit ?"
tuple_values += (limit,)
rows = db.cursor().execute(query, tuple_values)
#db.close()
if rows:
return [list(row) for row in rows]
return []
def truncateEntriesDb(self, table_name, on_field, to_value, operator='<'):
db = self.connect_db()
query = "delete from %s where %s%s?" % (table_name, on_field,
operator)
db.execute(query, (to_value,))
db.commit()
db.close()
def getLogString(self, res, head=False):
log = ""
if type(res) == type(dict()):
log = '%s, args [%s]\n' % (res['invocation']['module_name'],
res['invocation']['module_args'])
if head:
return log
for field in FIELDS:
if field in res.keys():
# use default encoding, check out sys.setdefaultencoding
log += '\n{0}:\n{1}'.format(field, res[field])
return log
def _read_file(self, filepath):
content = '[]'
with open(filepath, 'r') as f:
content = f.read()
return content
def saveResult(self):
date = datetime.utcnow().strftime(self.date_format)
files_list = os.listdir(self.ansible_log_dir)
if not len(files_list):
return
to_date = (datetime.now() - timedelta(days=2)).strftime(self.date_format)
cmp_file = os.path.join(self.ansible_log_dir, files_list.pop())
modification_date = datetime.fromtimestamp(
os.path.getmtime(cmp_file)
).strftime(self.date_format)
# Get the latest insert date
result = self.selectEntriesDb(['reportdate'], start_date=to_date, limit=1)
if len(result):
latest_date = result[0][0]
if latest_date >= modification_date:
return
file_map = dict(
success_file=os.path.join(self.ansible_log_dir, self.result_OK),
failed_file=os.path.join(self.ansible_log_dir, self.result_failed),
ignored_file=os.path.join(self.ansible_log_dir, self.result_failed_ignore))
data = dict(name=self.name, status='FAILED',
reportdate=modification_date, createdate=date,
success_count=0, ignored_count=0,
failed_count=0, success="",
failed="", ignored="")
for category in ('failed', 'success', 'ignored'):
file_category = file_map['%s_file' % category]
if os.path.exists(file_category):
text_content = self._read_file(file_category)
count = len(json.loads(text_content))
if count > 0:
data['%s_count' % category] = count
data[category] = text_content
if data['failed_count'] == 0:
data['status'] = 'OK'
self.insertEntryDb('ansible_report', data)
def getAnsibleReport(self, start_date=None, limit=0, success=None, order='DESC', category=None, head=False, only_state=True):
"""Get one or many entries from the ansible report table.
"""
where = ""
get_content = category is not None
fields = ['name', 'reportdate', 'createdate', 'status', 'success_count',
'ignored_count', 'failed_count']
if category:
where = " %s_count>0" % category
if not only_state:
fields.append(category)
rows = self.selectEntriesDb(fields=fields, start_date=start_date,
limit=limit, success=success, order=order,
where=where)
result_dict = {}
if category and not only_state:
last_pos = len(fields) -1
for i in range (0, len(rows)):
message = ""
message_list = json.loads(rows[i][last_pos])
for msg in message_list:
message += '%s\n\n' % self.getLogString(msg, head=head)
rows[i][last_pos] = message
else:
return {}
return rows
if __name__ == "__main__":
json = """{
"status": "OK",
"message": "kvm-1: OK(114) FAILED(0) IGNORED(2)",
"description": "Ansible playbook report in kvm-1. Execution date is: 2015-08-28 17:42:01."
}"""
path = sys.argv[1]
with open(path, 'w') as status_file:
status_file.write(json)
\ No newline at end of file
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