Skip to content
Snippets Groups Projects
Commit ba029f8d authored by Nikolay Stanchev's avatar Nikolay Stanchev
Browse files

Refactors alerts API views.py

parent 7b9868db
No related branches found
No related tags found
No related merge requests found
......@@ -59,32 +59,37 @@ class AlertsConfigurationAPI(object):
@view_config(route_name='alerts_configuration', request_method='POST')
def post_alerts_specification(self):
"""
The view for receiving and configuring alerts based on the TOSCA alerts specification document.
The view for receiving and configuring alerts based on the TOSCA alerts specification document. This endpoint must also receive the TOSCA resources specification document for validation.
:raises HTTPBadRequest: if the request doesn't contain a (YAML) file input referenced as alert-spec representing the TOSCA Alerts Specification
"""
kapacitor_host, kapacitor_port = self.request.registry.settings['kapacitor_host'], self.request.registry.settings['kapacitor_port']
if not hasattr(self.request.POST.get('alert-spec'), "file") or not hasattr(self.request.POST.get('alert-spec'), "filename"):
alert_spec_reference = self.request.POST.get('alert-spec')
# check that the specification file was sent
if not hasattr(alert_spec_reference, "file") or not hasattr(alert_spec_reference, "filename"):
raise HTTPBadRequest("Request to this API endpoint must include a (YAML) file input referenced as 'alert-spec' representing the TOSCA Alerts Specification.")
input_filename = self.request.POST['alert-spec'].filename
input_file = self.request.POST['alert-spec'].file
# extract alert specification file and filename
alerts_input_filename = alert_spec_reference.filename
alerts_input_file = alert_spec_reference.file
if not input_filename.lower().endswith('.yaml'):
if not alerts_input_filename.lower().endswith('.yaml'):
raise HTTPBadRequest("Request to this API endpoint must include a (YAML) file input referenced as 'alert-spec' representing the TOSCA Alerts Specification.")
# parse the alerts specification file
try:
yaml_content = load(input_file)
adjust_tosca_definitions_import(yaml_content)
alerts_yaml_content = load(alerts_input_file)
adjust_tosca_definitions_import(alerts_yaml_content)
except YAMLError as err:
log.error("Couldn't parse user request file {0} to yaml format due to error: {1}".format(input_filename, err))
log.error("Invalid content is: {0}".format(input_file.read()))
log.error("Couldn't parse user request file {0} to yaml format due to error: {1}".format(alerts_input_filename, err))
log.error("Invalid content is: {0}".format(alerts_input_file.read()))
raise HTTPBadRequest("Request alert specification file could not be parsed as valid YAML document.")
try:
tosca_tpl = ToscaTemplate(yaml_dict_tpl=yaml_content)
tosca_tpl = ToscaTemplate(yaml_dict_tpl=alerts_yaml_content)
except Exception as e:
log.error(e)
raise HTTPBadRequest("Request alert specification file could not be parsed as a valid TOSCA document.")
......@@ -101,6 +106,33 @@ class AlertsConfigurationAPI(object):
alert_handlers_errors = []
# iterate through every policy and extract all triggers of the given policy
self._config_kapacitor_alerts(tosca_tpl, sfc, sfc_instance, db, kapacitor_host, kapacitor_port, alert_tasks_errors, alert_handlers_errors)
return_msg = {"msg": "Alerts specification has been successfully validated and forwarded to Kapacitor", "service_function_chain_id": sfc,
"service_function_chain_instance_id": sfc_instance}
if len(alert_tasks_errors) > 0:
return_msg["triggers_specification_errors"] = alert_tasks_errors
if len(alert_handlers_errors) > 0:
return_msg["triggers_action_errors"] = alert_handlers_errors
return return_msg
def _config_kapacitor_alerts(self, tosca_tpl, sfc, sfc_instance, db, kapacitor_host, kapacitor_port, alert_tasks_errors, alert_handlers_errors):
"""
Configures the alerts task and alert handlers within Kapacitor.
:param tosca_tpl: the parsed Tosca template object
:param sfc: sfc ID
:param sfc_instance: sfc instance ID
:param db: Influx database ID
:param kapacitor_host: default host is localhost (CLMC service running on the same machine as Kapacitor)
:param kapacitor_port: default value to use is 9092
:param alert_tasks_errors: the list for tracking errors while interacting with Kapacitor tasks
:param alert_handlers_errors: the list for tracking errors while interacting with Kapacitor alert handlers
"""
for policy in tosca_tpl.policies:
for trigger in policy.triggers:
event_id = trigger.name
......@@ -168,30 +200,34 @@ class AlertsConfigurationAPI(object):
http_handlers = trigger.trigger_tpl["action"]["implementation"]
# subscribe all http handlers to the created topic
kapacitor_api_handlers_url = "http://{0}:{1}/kapacitor/v1/alerts/topics/{2}/handlers".format(kapacitor_host, kapacitor_port, topic_id)
for http_handler_url in http_handlers:
http_handler_host = urlparse(http_handler_url).hostname
handler_id = "{0}.{1}.{2}".format(policy.name, event_id, http_handler_host)
kapacitor_http_request_body = fill_http_post_handler_vars(handler_id, http_handler_url)
response = post(kapacitor_api_handlers_url, json=kapacitor_http_request_body)
response_content = response.json()
log.info(response_content, response.status_code)
if response_content.get("error", "") != "":
alert_handlers_errors.append({
"policy": policy.name,
"trigger": event_id,
"handler": http_handler_url,
"error": response_content.get("error")
})
self._config_kapacitor_alert_handlers(kapacitor_host, kapacitor_port, policy.name, topic_id, event_id, http_handlers, alert_handlers_errors)
return_msg = {"msg": "Alerts specification has been successfully validated and forwarded to Kapacitor", "service_function_chain_id": sfc,
"service_function_chain_instance_id": sfc_instance}
if len(alert_tasks_errors) > 0:
return_msg["triggers_specification_errors"] = alert_tasks_errors
if len(alert_handlers_errors) > 0:
return_msg["triggers_action_errors"] = alert_handlers_errors
def _config_kapacitor_alert_handlers(self, kapacitor_host, kapacitor_port, policy_id, topic_id, event_id, http_handlers, alert_handlers_errors):
"""
Handles the configuration of HTTP Post alert handlers.
:param kapacitor_host: default host is localhost (CLMC service running on the same machine as Kapacitor)
:param kapacitor_port: default value to use is 9092
:param policy_id: policy ID those triggers relate to
:param topic_id: topic ID built of sfc, sfc instance and event_id
:param event_id: name of trigger
:param http_handlers: list of handlers to subscribe
:param alert_handlers_errors: the list for tracking errors while interacting with Kapacitor alert handlers
"""
return return_msg
kapacitor_api_handlers_url = "http://{0}:{1}/kapacitor/v1/alerts/topics/{2}/handlers".format(kapacitor_host, kapacitor_port, topic_id)
for http_handler_url in http_handlers:
http_handler_host = urlparse(http_handler_url).hostname
handler_id = "{0}.{1}.{2}".format(policy_id, event_id, http_handler_host)
kapacitor_http_request_body = fill_http_post_handler_vars(handler_id, http_handler_url)
response = post(kapacitor_api_handlers_url, json=kapacitor_http_request_body)
response_content = response.json()
log.info(response_content, response.status_code)
if response_content.get("error", "") != "":
alert_handlers_errors.append({
"policy": policy_id,
"trigger": event_id,
"handler": http_handler_url,
"error": response_content.get("error")
})
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment