Skip to content
Snippets Groups Projects
Commit c5df5a95 authored by Michael Boniface's avatar Michael Boniface
Browse files

Merge branch 'clmc-service' into 'integration'

Merge latest version of clmc-service into integration branch

See merge request FLAME/flame-clmc!44
parents 78aa394a 17ba3cb4
No related branches found
No related tags found
No related merge requests found
Showing
with 407 additions and 91 deletions
...@@ -43,8 +43,7 @@ https://github.com/openstack/tosca-parser/blob/master/toscaparser/tests/data/pol ...@@ -43,8 +43,7 @@ https://github.com/openstack/tosca-parser/blob/master/toscaparser/tests/data/pol
The TOSCA Alerts Specification Document consists of two main sections - **metadata** and **policies**. Each **policy** contains a number The TOSCA Alerts Specification Document consists of two main sections - **metadata** and **policies**. Each **policy** contains a number
of triggers. A **trigger** is a fully qualified specification for an alert. Full definitions and clarification of the structure of the document of triggers. A **trigger** is a fully qualified specification for an alert. Full definitions and clarification of the structure of the document
is given in the following sections. An example of a valid alert specification is given in the following sections. An example of a valid alert specification document will look like:
document will look like:
```yaml ```yaml
tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0 tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0
...@@ -62,7 +61,7 @@ topology_template: ...@@ -62,7 +61,7 @@ topology_template:
policies: policies:
- high_latency_policy: - high_latency_policy:
type: eu.ict-flame.policies.StateChange type: eu.ict-flame.policies.Alert
triggers: triggers:
high_latency: high_latency:
description: This event triggers when the mean network latency in a given location exceeds a given threshold (in ms). description: This event triggers when the mean network latency in a given location exceeds a given threshold (in ms).
...@@ -77,11 +76,11 @@ topology_template: ...@@ -77,11 +76,11 @@ topology_template:
comparison_operator: gt comparison_operator: gt
action: action:
implementation: implementation:
- http://sfemc.flame.eu/notify - flame_sfemc
- http://companyA.alert-handler.flame.eu/high-latency - http://companyA.alert-handler.flame.eu/high-latency
- low_requests_policy: - low_requests_policy:
type: eu.ict-flame.policies.StateChange type: eu.ict-flame.policies.Alert
triggers: triggers:
low_requests: low_requests:
description: | description: |
...@@ -100,11 +99,11 @@ topology_template: ...@@ -100,11 +99,11 @@ topology_template:
comparison_operator: lt comparison_operator: lt
action: action:
implementation: implementation:
- http://sfemc.flame.eu/notify - flame_sfemc
- http://companyA.alert-handler.flame.eu/low-requests - http://companyA.alert-handler.flame.eu/low-requests
- requests_diff_policy: - requests_diff_policy:
type: eu.ict-flame.policies.StateChange type: eu.ict-flame.policies.Alert
triggers: triggers:
increase_in_requests: increase_in_requests:
description: | description: |
...@@ -116,8 +115,6 @@ topology_template: ...@@ -116,8 +115,6 @@ topology_template:
threshold: 100 # requests have increased by at least 100 threshold: 100 # requests have increased by at least 100
granularity: 120 granularity: 120
resource_type: resource_type:
flame_sfc: companyA-VR
flame_sfci: companyA-VR-premium
flame_sfp: storage flame_sfp: storage
flame_sf: storage-users flame_sf: storage-users
flame_server: watershed flame_server: watershed
...@@ -125,7 +122,7 @@ topology_template: ...@@ -125,7 +122,7 @@ topology_template:
comparison_operator: gte comparison_operator: gte
action: action:
implementation: implementation:
- http://sfemc.flame.eu/notify - flame_sfemc
decrease_in_requests: decrease_in_requests:
description: | description: |
This event triggers when the number of requests has decreased relative to the number of requests received This event triggers when the number of requests has decreased relative to the number of requests received
...@@ -142,10 +139,10 @@ topology_template: ...@@ -142,10 +139,10 @@ topology_template:
comparison_operator: lte comparison_operator: lte
action: action:
implementation: implementation:
- http://sfemc.flame.eu/notify - flame_sfemc
- missing_measurement_policy: - missing_measurement_policy:
type: eu.ict-flame.policies.StateChange type: eu.ict-flame.policies.Alert
triggers: triggers:
missing_storage_measurements: missing_storage_measurements:
description: This event triggers when the number of storage measurements reported falls below the threshold value. description: This event triggers when the number of storage measurements reported falls below the threshold value.
...@@ -160,7 +157,7 @@ topology_template: ...@@ -160,7 +157,7 @@ topology_template:
flame_sfp: storage flame_sfp: storage
action: action:
implementation: implementation:
- http://sfemc.flame.eu/notify - http://companyA.alert-handler.flame.eu/missing-measurements
``` ```
...@@ -178,14 +175,14 @@ metadata: ...@@ -178,14 +175,14 @@ metadata:
##### Policies ##### Policies
The ***policies*** section defines a list of policy nodes, each representing a fully qualified configuration for an The ***policies*** section defines a list of policy nodes, each representing a fully qualified configuration for an
alert within CLMC. The format is the following: alert within CLMC. Each policy must be of type eu.ict-flame.policies.Alert. The format is the following:
```yaml ```yaml
topology_template: topology_template:
policies: policies:
- <policy_identifier>: - <policy_identifier>:
type: eu.ict-flame.policies.StateChange type: eu.ict-flame.policies.Alert
triggers: triggers:
<event identifier>: <event identifier>:
description: <optional description for the given event trigger> description: <optional description for the given event trigger>
...@@ -202,8 +199,8 @@ topology_template: ...@@ -202,8 +199,8 @@ topology_template:
comparison_operator: <logical operator to use for comparison, e.g. 'gt', 'lt', 'gte', etc. comparison_operator: <logical operator to use for comparison, e.g. 'gt', 'lt', 'gte', etc.
action: action:
implementation: implementation:
- <HTTP Alert Handler URL - receives POST messages from Kapacitor when alerts trigger> - <flame_sfemc or HTTP Alert Handler URL - receives POST messages from Kapacitor when alerts trigger>
- <HTTP Alert Handler URL - receives POST messages from Kapacitor when alerts trigger> - <flame_sfemc or HTTP Alert Handler URL - receives POST messages from Kapacitor when alerts trigger>
... ...
... ...
``` ```
...@@ -239,19 +236,24 @@ the format is still the same for consistency. Therefore, using `<measurement>.*` ...@@ -239,19 +236,24 @@ the format is still the same for consistency. Therefore, using `<measurement>.*`
the event_type is set to **threshold**. the event_type is set to **threshold**.
* **resource_type** - provides context for the given event - key-value pairs for the global tags of the CLMC Information Model. * **resource_type** - provides context for the given event - key-value pairs for the global tags of the CLMC Information Model.
This includes any of the following: `"flame_sfc", "flame_sfci", "flame_sfp", "flame_sf", "flame_sfe", "flame_server", "flame_location"`. This includes any of the following: `"flame_sfp", "flame_sf", "flame_sfe", "flame_server", "flame_location"`.
Keep in mind that filtering for **sfc** and **sfci** is automatically generated by extracting the metadata values from the alerts specification. Keep in mind that **flame_sfc** and **flame_sfci** are also part of the CLMC Information Model. However, filtering on
these tags is automatically generated and added to all InfluxDB queries by using the metadata values from the
alerts specification. Therefore, including **flame_sfc** and **flame_sfci** in the **resource_type** is considered INVALID.
For more information on the global tags, please check the [documentation](monitoring.md). For more information on the global tags, please check the [documentation](monitoring.md).
* **comparison_operator** - the logical operator to use for comparison - lt (less than), gt (greater than), lte (less than or equal to), etc. * **comparison_operator** - the logical operator to use for comparison - lt (less than), gt (greater than), lte (less than or equal to), etc.
* **implementation** - a list of the URLs of alert handlers to which alert data is sent when the event condition is true. * **implementation** - a list of the URL entries for alert handlers to which alert data is sent when the event condition is true.
If the alert is supposed to be sent to SFEMC, then instead of typing a URL, use **flame_sfemc** - the configurator will generate the correct
SFEMC URL.
##### Event types ##### Event types
* **threshold** - A threshold event type is an alert in which Kapacitor queries InfluxDB on specific metric in a given period of time * **threshold** - A threshold event type is an alert in which Kapacitor queries InfluxDB on specific metric in a given period of time
by using a query function such as *mean*, *median*, *mode*, etc. This value is then compared against a given threshold. If the by using a query function such as *mean*, *median*, *mode*, etc. If the granularity is less than or equal to 60 seconds, then every measurement
point is monitored (improving performance), thus, ignoring the aggregation function. This value is then compared against a given threshold. If the
result of the comparison operation is true, an alert is triggered. For example: result of the comparison operation is true, an alert is triggered. For example:
```yaml ```yaml
...@@ -268,7 +270,7 @@ result of the comparison operation is true, an alert is triggered. For example: ...@@ -268,7 +270,7 @@ result of the comparison operation is true, an alert is triggered. For example:
comparison_operator: gt comparison_operator: gt
action: action:
implementation: implementation:
- http://sfemc.flame.eu/notify - flame_sfemc
- http://companyA.alert-handler.flame.eu/high-latency - http://companyA.alert-handler.flame.eu/high-latency
``` ```
...@@ -313,7 +315,7 @@ threshold. If the result of the comparison operation is true, an alert is trigge ...@@ -313,7 +315,7 @@ threshold. If the result of the comparison operation is true, an alert is trigge
comparison_operator: lte comparison_operator: lte
action: action:
implementation: implementation:
- http://sfemc.flame.eu/notify - flame_sfemc
``` ```
This trigger specification will create an alert task in Kapacitor, which compares every **requests** value reported in This trigger specification will create an alert task in Kapacitor, which compares every **requests** value reported in
...@@ -345,7 +347,7 @@ For example: ...@@ -345,7 +347,7 @@ For example:
flame_sfp: storage flame_sfp: storage
action: action:
implementation: implementation:
- http://sfemc.flame.eu/notify - flame_sfemc
``` ```
This trigger specification will create an alert task in Kapacitor, which monitors the number of points reported in This trigger specification will create an alert task in Kapacitor, which monitors the number of points reported in
...@@ -361,3 +363,53 @@ For example: ...@@ -361,3 +363,53 @@ For example:
* even if you put something else for field value, it will be ignored - only the **measurement** name is used * even if you put something else for field value, it will be ignored - only the **measurement** name is used
* **aggregation_method** is not required in this event type, any values provided will be ignored * **aggregation_method** is not required in this event type, any values provided will be ignored
* **comparison operator** is not required in this event type, any values provided will be ignored * **comparison operator** is not required in this event type, any values provided will be ignored
##### Alert messages
Every alert handler registered in a trigger *action --> implementation* section receives an alert message when the trigger
event condition is true. This alert message is sent using an *HTTP POST* request to the URL of the alert handler. The alert
message is generated by Kapacitor and, currently, clmc-service has limited control over it. An alert message follows this format:
```json
{
"message": "TRUE",
"id": "<trigger_id>",
"level": "CRITICAL",
"duration": "<integer for the duration of alert - nanoseconds>",
"previousLevel": "<the previous level of the alert>",
"details": "<a context string with info on what triggered the alert>",
"time": "<timestamp of the alert occurrence>",
"data": {
"series": [
{
"name": "<measurement name of the alert metric>",
"tags": {
"<tag name>": "<tag value>"
},
"columns": [
"<column name>"
],
"values": [
[
"<values of each column name>"
]
]
}
]
}
}
```
* message - currently, this is always set to "TRUE"
* id - trigger ID as defined in the alert specification document
* level - the level of the alert; currently all alerts that trigger have their level set as CRITICAL
* previousLevel - the previous level of the alert
* details - a string in the format "db=<db_name>,sfc=<sfc_id>,sfci=<sfc_instance_id>,policy=<policy_id>" providing context of the alert
* duration - integer, duration of the alert in nanoseconds
* time - timestamp of the point that triggered the alert
* data - describes the point(s) that triggered the alert
* data.series.name - the name of the measurement
* data.series.tags - (OPTIONAL) key-value pairs for all measurement tags
* data.series.columns - list of column names
* data.series.values - list of list of values, each nested list represents a measurement point and the values for each column
...@@ -102,6 +102,7 @@ mkdir -p /opt/flame/clmc ...@@ -102,6 +102,7 @@ mkdir -p /opt/flame/clmc
start_script_file="/opt/flame/clmc/start.sh" start_script_file="/opt/flame/clmc/start.sh"
echo "#!/bin/bash" > $start_script_file echo "#!/bin/bash" > $start_script_file
echo "export WORKON_HOME=${HOME}/.virtualenvs" >> $start_script_file echo "export WORKON_HOME=${HOME}/.virtualenvs" >> $start_script_file
echo "export SFEMC_FQDN=${SFEMC_FQDN}" >> $start_script_file
echo "source /usr/local/bin/virtualenvwrapper.sh" >> $start_script_file echo "source /usr/local/bin/virtualenvwrapper.sh" >> $start_script_file
echo "workon CLMC" >> $start_script_file echo "workon CLMC" >> $start_script_file
echo "pserve ${REPO_ROOT}/src/service/production.ini &" >> $start_script_file echo "pserve ${REPO_ROOT}/src/service/production.ini &" >> $start_script_file
......
...@@ -27,6 +27,11 @@ ...@@ -27,6 +27,11 @@
# Force fail on command fail (off for now as virtualenvwrapper install fails) # Force fail on command fail (off for now as virtualenvwrapper install fails)
set -euo pipefail set -euo pipefail
if [[ -z "${SFEMC_FQDN}" ]]; then
echo "Failed: cannot find SFEMC_FQDN environment variable."
exit 1
fi
# Ensure everything runs in directory of the parent script # Ensure everything runs in directory of the parent script
cd `dirname $0` cd `dirname $0`
......
...@@ -52,7 +52,7 @@ create() { ...@@ -52,7 +52,7 @@ create() {
if [ ${service_name} == "clmc-service" ]; then if [ ${service_name} == "clmc-service" ]; then
cmd="/vagrant/scripts/clmc-service/install.sh" cmd="/vagrant/scripts/clmc-service/install.sh"
echo "Provisioning command ${cmd}" echo "Provisioning command ${cmd}"
lxc exec ${service_name} --env REPO_ROOT="/vagrant" -- ${cmd} lxc exec ${service_name} --env REPO_ROOT="/vagrant" --env SFEMC_FQDN="sfemc.localhost" -- ${cmd}
exit_code=$? exit_code=$?
if [ $exit_code != 0 ]; then if [ $exit_code != 0 ]; then
echo "clmc-service installation failed with exit code ${exit_code}" echo "clmc-service installation failed with exit code ${exit_code}"
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
# Python standard libs # Python standard libs
from json import load from json import load
from os.path import dirname, abspath from os.path import dirname, abspath
import os
# PIP installed libs # PIP installed libs
from pyramid.config import Configurator from pyramid.config import Configurator
...@@ -47,6 +48,8 @@ def main(global_config, **settings): ...@@ -47,6 +48,8 @@ def main(global_config, **settings):
DBSession.configure(bind=engine) # bind the engine to a DB session DBSession.configure(bind=engine) # bind the engine to a DB session
Base.metadata.bind = engine # bind the engine to the Base class metadata Base.metadata.bind = engine # bind the engine to the Base class metadata
settings['sfemc_fqdn'] = os.environ['SFEMC_FQDN'] # read the SFEMC FQDN from the OS environment
settings['influx_port'] = int(settings['influx_port']) # the influx port setting must be converted to integer instead of a string settings['influx_port'] = int(settings['influx_port']) # the influx port setting must be converted to integer instead of a string
settings['kapacitor_port'] = int(settings['kapacitor_port']) # the kapacitor port setting must be converted to integer instead of a string settings['kapacitor_port'] = int(settings['kapacitor_port']) # the kapacitor port setting must be converted to integer instead of a string
......
...@@ -35,11 +35,14 @@ from schema import Schema, And, Or, Optional, SchemaError ...@@ -35,11 +35,14 @@ from schema import Schema, And, Or, Optional, SchemaError
# * metadata section must be present (with key-value pairs for sfc and sfci) # * metadata section must be present (with key-value pairs for sfc and sfci)
# * policies section must be present (under the topology_template node) # * policies section must be present (under the topology_template node)
# * each policy must be associated with a triggers node (containing at least 1 trigger) # * each policy must be associated with a triggers node (containing at least 1 trigger)
# * each policy is of type eu.ict-flame.policies.StateChange or eu.ict-flame.policies.Alert # * each policy is of type eu.ict-flame.policies.Alert
# * each trigger must specify event_type, metric, condition, and at least one handler in action/implementation # * each trigger must specify event_type, metric, condition, and at least one handler in action/implementation
# * the condition section must specify threshold, granularity, aggregation_method, comparison_operator # * the condition section must specify threshold, granularity, aggregation_method, comparison_operator
SFEMC = "flame_sfemc" # describes the keyword used for the SFEMC alert handler
# Influx QL functions defined in the documentation https://docs.influxdata.com/influxdb/v1.6/query_language/functions/ # Influx QL functions defined in the documentation https://docs.influxdata.com/influxdb/v1.6/query_language/functions/
INFLUX_QL_FUNCTIONS = ( INFLUX_QL_FUNCTIONS = (
"count", "mean", "median", "mode", "sum", "first", "last", "max", "min" "count", "mean", "median", "mode", "sum", "first", "last", "max", "min"
...@@ -62,7 +65,9 @@ URL_REGEX = re.compile( ...@@ -62,7 +65,9 @@ URL_REGEX = re.compile(
re.IGNORECASE) re.IGNORECASE)
# Global tags allowed to be used for filtering in the trigger condition # Global tags allowed to be used for filtering in the trigger condition
CLMC_INFORMATION_MODEL_GLOBAL_TAGS = {"flame_sfc", "flame_sfci", "flame_sfp", "flame_sf", "flame_sfe", "flame_server", "flame_location"} CLMC_INFORMATION_MODEL_GLOBAL_TAGS = {"flame_sfp", "flame_sf", "flame_sfe", "flame_server", "flame_location"}
# NOTICE that "flame_sfc", "flame_sfci" are not allowed, eventhough they are part of the CLMC Information Model
# This is because those two tags are automatically added to the InfluxDB queries - the required values are retrieved from the alert spec. metadata
ALERTS_SPECIFICATION_SCHEMA = Schema({ ALERTS_SPECIFICATION_SCHEMA = Schema({
"tosca_definitions_version": And(str, lambda v: v == "tosca_simple_profile_for_nfv_1_0_0"), "tosca_definitions_version": And(str, lambda v: v == "tosca_simple_profile_for_nfv_1_0_0"),
...@@ -76,7 +81,7 @@ ALERTS_SPECIFICATION_SCHEMA = Schema({ ...@@ -76,7 +81,7 @@ ALERTS_SPECIFICATION_SCHEMA = Schema({
"policies": [ "policies": [
{ {
str: { str: {
"type": Or("eu.ict-flame.policies.StateChange", "eu.ict-flame.policies.Alert"), "type": "eu.ict-flame.policies.Alert",
"triggers": And({ "triggers": And({
str: { str: {
Optional("description"): str, Optional("description"): str,
...@@ -94,7 +99,7 @@ ALERTS_SPECIFICATION_SCHEMA = Schema({ ...@@ -94,7 +99,7 @@ ALERTS_SPECIFICATION_SCHEMA = Schema({
"action": { "action": {
"implementation": "implementation":
[ [
And(str, lambda s: URL_REGEX.match(s) is not None) Or(SFEMC, And(str, lambda s: URL_REGEX.match(s) is not None))
] ]
} }
} }
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
# Python standard libs # Python standard libs
from os import listdir from os import listdir
from os.path import isfile, join, dirname from os.path import isfile, join, dirname, splitext
# PIP installed libs # PIP installed libs
import pytest import pytest
...@@ -62,7 +62,7 @@ class TestAlertsConfigurationAPI(object): ...@@ -62,7 +62,7 @@ class TestAlertsConfigurationAPI(object):
""" """
self.registry = testing.setUp() self.registry = testing.setUp()
self.registry.add_settings({"kapacitor_host": "localhost", "kapacitor_port": 9092}) self.registry.add_settings({"kapacitor_host": "localhost", "kapacitor_port": 9092, "sfemc_fqdn": "sfemc.localhost"})
yield yield
...@@ -272,6 +272,7 @@ def extract_alert_spec_data(alert_spec): ...@@ -272,6 +272,7 @@ def extract_alert_spec_data(alert_spec):
:return: a tuple containing sfc_id and sfc_instance_id along with a list and a dictionary of generated IDs (alert IDs (list), topic IDs linked to handler IDs (dict)) :return: a tuple containing sfc_id and sfc_instance_id along with a list and a dictionary of generated IDs (alert IDs (list), topic IDs linked to handler IDs (dict))
""" """
version = splitext(alert_spec.name)[0].split("-")[-1] # take the ending number of the alert spec file
yaml_alert_spec = load(alert_spec) yaml_alert_spec = load(alert_spec)
adjust_tosca_definitions_import(yaml_alert_spec) adjust_tosca_definitions_import(yaml_alert_spec)
tosca_tpl = ToscaTemplate(yaml_dict_tpl=yaml_alert_spec) tosca_tpl = ToscaTemplate(yaml_dict_tpl=yaml_alert_spec)
...@@ -296,6 +297,10 @@ def extract_alert_spec_data(alert_spec): ...@@ -296,6 +297,10 @@ def extract_alert_spec_data(alert_spec):
alert_ids.append((alert_id, alert_type)) alert_ids.append((alert_id, alert_type))
for handler_url in trigger.trigger_tpl["action"]["implementation"]: for handler_url in trigger.trigger_tpl["action"]["implementation"]:
if handler_url == "flame_sfemc":
handler_url = "http://sfemc.localhost/{0}/{1}/{2}/{3}".format(sfc, sfc_instance, policy_id, "trigger_id_{0}".format(version))
handler_id = "{0}\n{1}\n{2}\n{3}\n{4}".format(sfc, sfc_instance, policy_id, trigger_id, handler_url) handler_id = "{0}\n{1}\n{2}\n{3}\n{4}".format(sfc, sfc_instance, policy_id, trigger_id, handler_url)
handler_id = AlertsConfigurationAPI.get_hash(handler_id) handler_id = AlertsConfigurationAPI.get_hash(handler_id)
topic_handlers[topic_id].append((handler_id, handler_url)) topic_handlers[topic_id].append((handler_id, handler_url))
......
...@@ -31,6 +31,7 @@ from yaml import load ...@@ -31,6 +31,7 @@ from yaml import load
# CLMC-service imports # CLMC-service imports
from clmcservice import ROOT_DIR from clmcservice import ROOT_DIR
from clmcservice.alertsapi.alerts_specification_schema import SFEMC
CLMC_ALERTS_TOSCA_DEFINITIONS_REL_PATH = ["static", "flame_clmc_alerts_definitions.yaml"] CLMC_ALERTS_TOSCA_DEFINITIONS_REL_PATH = ["static", "flame_clmc_alerts_definitions.yaml"]
...@@ -57,18 +58,18 @@ def adjust_tosca_definitions_import(alert_spec): ...@@ -57,18 +58,18 @@ def adjust_tosca_definitions_import(alert_spec):
pass # nothing to replace if the import is not specified (either imports are missed, or no reference to the clmc tosca definitions file) pass # nothing to replace if the import is not specified (either imports are missed, or no reference to the clmc tosca definitions file)
def get_resource_spec_topic_ids(resource_spec_reference): def get_resource_spec_policy_triggers(resource_spec_reference):
""" """
Tries to extract all event identifiers from a TOSCA resource specification Tries to extract all event identifiers from a TOSCA resource specification
:param resource_spec_reference: the resource specification file reference from the POST HTTP request :param resource_spec_reference: the resource specification file reference from the POST HTTP request
:return: sfc ID, sfc instance ID and the list of topic IDs :return: sfc ID, sfc instance ID and the map of policy trigger IDs linked to the resource spec trigger id
""" """
resource_spec = load(resource_spec_reference.file) resource_spec = load(resource_spec_reference.file)
topic_ids = [] policy_trigger_ids = {}
sfc, sfc_i = resource_spec["metadata"]["sfc"], resource_spec["metadata"]["sfci"] sfc, sfc_i = resource_spec["metadata"]["sfc"], resource_spec["metadata"]["sfci"]
policies = resource_spec["topology_template"]["policies"] policies = resource_spec["topology_template"]["policies"]
...@@ -79,25 +80,26 @@ def get_resource_spec_topic_ids(resource_spec_reference): ...@@ -79,25 +80,26 @@ def get_resource_spec_topic_ids(resource_spec_reference):
if policy_object["type"] == "eu.ict-flame.policies.StateChange": if policy_object["type"] == "eu.ict-flame.policies.StateChange":
triggers = policy_object["triggers"] triggers = policy_object["triggers"]
for trigger in triggers.values(): for trigger_id in triggers:
trigger = triggers[trigger_id]
event = trigger["condition"]["constraint"] event = trigger["condition"]["constraint"]
source, event_id = event.split("::") source, event_id = event.split("::")
if source.lower() == "clmc": # only take those event IDs that have clmc set as their source if source.lower() == "clmc": # only take those event IDs that have clmc set as their source
topic_ids.append("{0}\n{1}".format(policy_id, event_id)) policy_trigger_ids["{0}\n{1}".format(policy_id, event_id)] = trigger_id
return sfc, sfc_i, topic_ids return sfc, sfc_i, policy_trigger_ids
def get_alert_spec_topic_ids(alerts_spec_tpl): def get_alert_spec_policy_triggers(alerts_spec_tpl):
""" """
Tries to extract all event identifiers from a TOSCA alerts specification Tries to extract all event identifiers from a TOSCA alerts specification
:param alerts_spec_tpl: the alerts specification TOSCA template object :param alerts_spec_tpl: the alerts specification TOSCA template object
:return: the list of topic IDs :return: the list of policy triggers
""" """
topic_ids = [] policy_trigger_ids = []
for policy in alerts_spec_tpl.policies: for policy in alerts_spec_tpl.policies:
policy_id = policy.name policy_id = policy.name
...@@ -105,10 +107,12 @@ def get_alert_spec_topic_ids(alerts_spec_tpl): ...@@ -105,10 +107,12 @@ def get_alert_spec_topic_ids(alerts_spec_tpl):
for trigger in policy.triggers: for trigger in policy.triggers:
trigger_id = trigger.name trigger_id = trigger.name
topic_id = "{0}\n{1}".format(policy_id, trigger_id) # only include those triggers that actually POST to SFEMC
topic_ids.append(topic_id) if SFEMC in trigger.trigger_tpl["action"]["implementation"]:
policy_trigger_string = "{0}\n{1}".format(policy_id, trigger_id)
policy_trigger_ids.append(policy_trigger_string)
return topic_ids return policy_trigger_ids
def fill_http_post_handler_vars(handler_id, handler_url): def fill_http_post_handler_vars(handler_id, handler_url):
...@@ -152,7 +156,7 @@ class TICKScriptTemplateFiller: ...@@ -152,7 +156,7 @@ class TICKScriptTemplateFiller:
return fill_function(**kwargs) return fill_function(**kwargs)
@staticmethod @staticmethod
def _fill_threshold_batch_template_vars(db=None, measurement=None, field=None, influx_function=None, critical_value=None, def _fill_threshold_batch_template_vars(sfc=None, sfci=None, policy=None, db=None, measurement=None, field=None, influx_function=None, critical_value=None,
comparison_operator=None, alert_period=None, topic_id=None, event_id=None, where_clause=None, **kwargs): comparison_operator=None, alert_period=None, topic_id=None, event_id=None, where_clause=None, **kwargs):
""" """
Creates a dictionary object ready to be posted to kapacitor to create a "threshold" task from template. Creates a dictionary object ready to be posted to kapacitor to create a "threshold" task from template.
...@@ -174,6 +178,18 @@ class TICKScriptTemplateFiller: ...@@ -174,6 +178,18 @@ class TICKScriptTemplateFiller:
comparison_lambda = '"real_value" {0} {1}'.format(comparison_operator, critical_value) # build up lambda string, e.g. "real_value" >= 10 comparison_lambda = '"real_value" {0} {1}'.format(comparison_operator, critical_value) # build up lambda string, e.g. "real_value" >= 10
template_vars = { template_vars = {
"sfc": {
"type": "string",
"value": sfc
},
"sfci": {
"type": "string",
"value": sfci
},
"policy": {
"type": "string",
"value": policy
},
"db": { "db": {
"type": "string", "type": "string",
"value": db "value": db
...@@ -217,7 +233,7 @@ class TICKScriptTemplateFiller: ...@@ -217,7 +233,7 @@ class TICKScriptTemplateFiller:
return template_vars return template_vars
@staticmethod @staticmethod
def _fill_threshold_stream_template_vars(db=None, measurement=None, field=None, critical_value=None, def _fill_threshold_stream_template_vars(sfc=None, sfci=None, policy=None, db=None, measurement=None, field=None, critical_value=None,
comparison_operator=None, topic_id=None, event_id=None, where_clause=None, **kwargs): comparison_operator=None, topic_id=None, event_id=None, where_clause=None, **kwargs):
""" """
Creates a dictionary object ready to be posted to kapacitor to create a "threshold" task from template. Creates a dictionary object ready to be posted to kapacitor to create a "threshold" task from template.
...@@ -239,6 +255,18 @@ class TICKScriptTemplateFiller: ...@@ -239,6 +255,18 @@ class TICKScriptTemplateFiller:
comparison_lambda = '"{0}" {1} {2}'.format(field, comparison_operator, critical_value) # build up lambda string, e.g. "real_value" >= 10 comparison_lambda = '"{0}" {1} {2}'.format(field, comparison_operator, critical_value) # build up lambda string, e.g. "real_value" >= 10
template_vars = { template_vars = {
"sfc": {
"type": "string",
"value": sfc
},
"sfci": {
"type": "string",
"value": sfci
},
"policy": {
"type": "string",
"value": policy
},
"db": { "db": {
"type": "string", "type": "string",
"value": db "value": db
...@@ -271,7 +299,7 @@ class TICKScriptTemplateFiller: ...@@ -271,7 +299,7 @@ class TICKScriptTemplateFiller:
return template_vars return template_vars
@staticmethod @staticmethod
def _fill_relative_template_vars(db=None, measurement=None, field=None, influx_function=None, critical_value=None, comparison_operator=None, def _fill_relative_template_vars(sfc=None, sfci=None, policy=None, db=None, measurement=None, field=None, influx_function=None, critical_value=None, comparison_operator=None,
alert_period=None, topic_id=None, event_id=None, where_clause=None, **kwargs): alert_period=None, topic_id=None, event_id=None, where_clause=None, **kwargs):
""" """
Creates a dictionary object ready to be posted to kapacitor to create a "relative" task from template. Creates a dictionary object ready to be posted to kapacitor to create a "relative" task from template.
...@@ -293,6 +321,18 @@ class TICKScriptTemplateFiller: ...@@ -293,6 +321,18 @@ class TICKScriptTemplateFiller:
comparison_lambda = '"diff" {0} {1}'.format(comparison_operator, critical_value) comparison_lambda = '"diff" {0} {1}'.format(comparison_operator, critical_value)
template_vars = { template_vars = {
"sfc": {
"type": "string",
"value": sfc
},
"sfci": {
"type": "string",
"value": sfci
},
"policy": {
"type": "string",
"value": policy
},
"db": { "db": {
"type": "string", "type": "string",
"value": db "value": db
...@@ -336,7 +376,7 @@ class TICKScriptTemplateFiller: ...@@ -336,7 +376,7 @@ class TICKScriptTemplateFiller:
return template_vars return template_vars
@staticmethod @staticmethod
def _fill_deadman_template_vars(db=None, measurement=None, critical_value=None, alert_period=None, topic_id=None, event_id=None, where_clause=None, **kwargs): def _fill_deadman_template_vars(sfc=None, sfci=None, policy=None, db=None, measurement=None, critical_value=None, alert_period=None, topic_id=None, event_id=None, where_clause=None, **kwargs):
""" """
Creates a dictionary object ready to be posted to kapacitor to create a "deadman" task from template. Creates a dictionary object ready to be posted to kapacitor to create a "deadman" task from template.
...@@ -352,6 +392,18 @@ class TICKScriptTemplateFiller: ...@@ -352,6 +392,18 @@ class TICKScriptTemplateFiller:
""" """
template_vars = { template_vars = {
"sfc": {
"type": "string",
"value": sfc
},
"sfci": {
"type": "string",
"value": sfci
},
"policy": {
"type": "string",
"value": policy
},
"db": { "db": {
"type": "string", "type": "string",
"value": db "value": db
......
...@@ -34,8 +34,8 @@ from toscaparser.tosca_template import ToscaTemplate ...@@ -34,8 +34,8 @@ from toscaparser.tosca_template import ToscaTemplate
from requests import post from requests import post
# CLMC-service imports # CLMC-service imports
from clmcservice.alertsapi.utilities import adjust_tosca_definitions_import, TICKScriptTemplateFiller, fill_http_post_handler_vars, get_resource_spec_topic_ids, get_alert_spec_topic_ids from clmcservice.alertsapi.utilities import adjust_tosca_definitions_import, TICKScriptTemplateFiller, fill_http_post_handler_vars, get_resource_spec_policy_triggers, get_alert_spec_policy_triggers
from clmcservice.alertsapi.alerts_specification_schema import COMPARISON_OPERATORS, validate_clmc_alerts_specification from clmcservice.alertsapi.alerts_specification_schema import COMPARISON_OPERATORS, SFEMC, validate_clmc_alerts_specification
# initialise logger # initialise logger
log = logging.getLogger('service_logger') log = logging.getLogger('service_logger')
...@@ -100,15 +100,20 @@ class AlertsConfigurationAPI(object): ...@@ -100,15 +100,20 @@ class AlertsConfigurationAPI(object):
alert_spec_reference = self.request.POST.get('alert-spec') alert_spec_reference = self.request.POST.get('alert-spec')
resource_spec_reference = self.request.POST.get('resource-spec') resource_spec_reference = self.request.POST.get('resource-spec')
# check that the resource specification file was sent
if not hasattr(resource_spec_reference, "file") or not hasattr(resource_spec_reference, "filename"):
raise HTTPBadRequest("Request to this API endpoint must include a (YAML) file input referenced as 'resource-spec' representing the TOSCA Resource Specification.")
try: try:
resource_spec_sfc, resource_spec_sfc_i, resource_spec_topic_ids = get_resource_spec_topic_ids(resource_spec_reference) resource_spec_sfc, resource_spec_sfc_i, resource_spec_policy_triggers = get_resource_spec_policy_triggers(resource_spec_reference)
except Exception as e: except Exception as e:
log.error("Couldn't extract resource specification event IDs due to error: {0}".format(e)) log.error("Couldn't extract resource specification event IDs due to error: {0}".format(e))
raise HTTPBadRequest("Couldn't extract resource specification event IDs - invalid TOSCA resource specification.") raise HTTPBadRequest("Couldn't extract resource specification event IDs - invalid TOSCA resource specification.")
# check that the specification file was sent # check that the alerts specification file was sent
if not hasattr(alert_spec_reference, "file") or not hasattr(alert_spec_reference, "filename"): 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.") raise HTTPBadRequest("Request to this API endpoint must include a (YAML) file input referenced as 'alert-spec' representing the TOSCA Alert Specification.")
# extract alert specification file and filename # extract alert specification file and filename
alerts_input_filename = alert_spec_reference.filename alerts_input_filename = alert_spec_reference.filename
...@@ -136,19 +141,20 @@ class AlertsConfigurationAPI(object): ...@@ -136,19 +141,20 @@ class AlertsConfigurationAPI(object):
if not valid_alert_spec: if not valid_alert_spec:
raise HTTPBadRequest("Request alert specification file could not be validated as a CLMC TOSCA alerts specification document.") raise HTTPBadRequest("Request alert specification file could not be validated as a CLMC TOSCA alerts specification document.")
alert_spec_topic_ids = get_alert_spec_topic_ids(tosca_tpl) alert_spec_policy_triggers = get_alert_spec_policy_triggers(tosca_tpl)
sfc, sfc_instance = tosca_tpl.tpl["metadata"]["sfc"], tosca_tpl.tpl["metadata"]["sfci"] sfc, sfc_instance = tosca_tpl.tpl["metadata"]["sfc"], tosca_tpl.tpl["metadata"]["sfci"]
# do validation between the two TOSCA documents # do validation between the two TOSCA documents
self._compare_alert_and_resource_spec(sfc, sfc_instance, alert_spec_topic_ids, resource_spec_sfc, resource_spec_sfc_i, resource_spec_topic_ids) self._compare_alert_and_resource_spec(sfc, sfc_instance, alert_spec_policy_triggers, resource_spec_sfc, resource_spec_sfc_i, resource_spec_policy_triggers)
db = sfc # database per service function chain, named after the service function chain ID
db = sfc # ASSUMPTION: database per service function chain, named after the service function chain ID
# two lists to keep track of any errors while interacting with the Kapacitor HTTP API # two lists to keep track of any errors while interacting with the Kapacitor HTTP API
alert_tasks_errors = [] alert_tasks_errors = []
alert_handlers_errors = [] alert_handlers_errors = []
# iterate through every policy and extract all triggers of the given policy # 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) self._config_kapacitor_alerts(tosca_tpl, sfc, sfc_instance, db, kapacitor_host, kapacitor_port, resource_spec_policy_triggers, alert_tasks_errors, alert_handlers_errors)
return_msg = {"msg": "Alerts specification has been successfully validated and forwarded to Kapacitor", "service_function_chain_id": sfc, 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} "service_function_chain_instance_id": sfc_instance}
...@@ -163,16 +169,16 @@ class AlertsConfigurationAPI(object): ...@@ -163,16 +169,16 @@ class AlertsConfigurationAPI(object):
return return_msg return return_msg
def _compare_alert_and_resource_spec(self, alert_spec_sfc, alert_spec_sfc_instance, alert_spec_topics, resource_spec_sfc, resource_spec_sfc_instance, resource_spec_topics): def _compare_alert_and_resource_spec(self, alert_spec_sfc, alert_spec_sfc_instance, alert_spec_policy_triggers, resource_spec_sfc, resource_spec_sfc_instance, resource_spec_policy_triggers):
""" """
Compares the extracted values from the resource spec against the values from the alerts spec - validation that they refer to the same things, Compares the extracted values from the resource spec against the values from the alerts spec - validation that they refer to the same things,
:param alert_spec_sfc: sfc from alert spec :param alert_spec_sfc: sfc from alert spec
:param alert_spec_sfc_instance: sfc instance from alert spec :param alert_spec_sfc_instance: sfc instance from alert spec
:param alert_spec_topics: policy/trigger IDs from alert spec :param alert_spec_policy_triggers: policy/trigger IDs from alert spec
:param resource_spec_sfc: sfc from resource spec :param resource_spec_sfc: sfc from resource spec
:param resource_spec_sfc_instance: sfc instance from resource spec :param resource_spec_sfc_instance: sfc instance from resource spec
:param resource_spec_topics: policy/trigger IDs from resource spec :param resource_spec_policy_triggers: policy/trigger IDs from resource spec
:raises: HTTP Bad Request if the two specifications are inconsistent :raises: HTTP Bad Request if the two specifications are inconsistent
""" """
...@@ -183,14 +189,20 @@ class AlertsConfigurationAPI(object): ...@@ -183,14 +189,20 @@ class AlertsConfigurationAPI(object):
if alert_spec_sfc_instance != resource_spec_sfc_instance: if alert_spec_sfc_instance != resource_spec_sfc_instance:
raise HTTPBadRequest("Different service function chain instance ID used in the alert and resource specification documents: {0} != {1}".format(alert_spec_sfc_instance, resource_spec_sfc_instance)) raise HTTPBadRequest("Different service function chain instance ID used in the alert and resource specification documents: {0} != {1}".format(alert_spec_sfc_instance, resource_spec_sfc_instance))
alert_spec_topics_set = set(alert_spec_topics) alert_spec_triggers_set = set(alert_spec_policy_triggers)
missing_topic_ids = [topic_id for topic_id in resource_spec_topics if topic_id not in alert_spec_topics_set] resource_spec_triggers_set = set(resource_spec_policy_triggers)
if len(missing_topic_ids) > 0: # check for triggers defined in the resource specification but missing in the alerts specification
missing_topic_ids = [topic_id.replace("\n", " : ") for topic_id in missing_topic_ids] missing_policy_triggers = [policy_trigger_id.replace("\n", " : ") for policy_trigger_id in resource_spec_policy_triggers if policy_trigger_id not in alert_spec_triggers_set]
raise HTTPBadRequest("Couldn't match the following policy triggers from the resource specification with triggers defined in the alerts specification: {0}".format(missing_topic_ids)) if len(missing_policy_triggers) > 0:
raise HTTPBadRequest("Couldn't match the following policy triggers from the resource specification with triggers defined in the alerts specification: {0}".format(missing_policy_triggers))
def _config_kapacitor_alerts(self, tosca_tpl, sfc, sfc_instance, db, kapacitor_host, kapacitor_port, alert_tasks_errors, alert_handlers_errors): # check for triggers defined in the alerts specification and posting to flame_sfemc, but missing in the resource specification
missing_policy_triggers = [policy_trigger_id.replace("\n", " : ") for policy_trigger_id in alert_spec_policy_triggers if policy_trigger_id not in resource_spec_triggers_set]
if len(missing_policy_triggers) > 0:
raise HTTPBadRequest("Couldn't match the following policy triggers from the alerts specification with triggers defined in the resource specification: {0}".format(missing_policy_triggers))
def _config_kapacitor_alerts(self, tosca_tpl, sfc, sfc_instance, db, kapacitor_host, kapacitor_port, resource_spec_policy_triggers, alert_tasks_errors, alert_handlers_errors):
""" """
Configures the alerts task and alert handlers within Kapacitor. Configures the alerts task and alert handlers within Kapacitor.
...@@ -200,6 +212,7 @@ class AlertsConfigurationAPI(object): ...@@ -200,6 +212,7 @@ class AlertsConfigurationAPI(object):
:param db: Influx database ID :param db: Influx database ID
:param kapacitor_host: default host is localhost (CLMC service running on the same machine as Kapacitor) :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 kapacitor_port: default value to use is 9092
:param resource_spec_policy_triggers: the extracted policy-trigger strings from the resource specification
:param alert_tasks_errors: the list for tracking errors while interacting with Kapacitor tasks :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 :param alert_handlers_errors: the list for tracking errors while interacting with Kapacitor alert handlers
...@@ -210,6 +223,7 @@ class AlertsConfigurationAPI(object): ...@@ -210,6 +223,7 @@ class AlertsConfigurationAPI(object):
for trigger in policy.triggers: for trigger in policy.triggers:
event_id = trigger.name event_id = trigger.name
policy_id = policy.name policy_id = policy.name
resource_spec_trigger_id = resource_spec_policy_triggers.get("{0}\n{1}".format(policy_id, event_id))
event_type = trigger.trigger_tpl["event_type"] event_type = trigger.trigger_tpl["event_type"]
template_id = "{0}-template".format(event_type) template_id = "{0}-template".format(event_type)
...@@ -225,7 +239,7 @@ class AlertsConfigurationAPI(object): ...@@ -225,7 +239,7 @@ class AlertsConfigurationAPI(object):
where_clause = None where_clause = None
if "resource_type" in trigger.trigger_tpl["condition"]: if "resource_type" in trigger.trigger_tpl["condition"]:
tags = condition["resource_type"] tags = condition["resource_type"]
# make sure alert tasks are executing with queries for the given sfc and sfc instance # make sure alert tasks are executing with queries for the given sfc and sfc instance - automatically add those tags using the metadata values
tags["flame_sfc"] = sfc tags["flame_sfc"] = sfc
tags["flame_sfci"] = sfc_instance tags["flame_sfci"] = sfc_instance
...@@ -251,9 +265,9 @@ class AlertsConfigurationAPI(object): ...@@ -251,9 +265,9 @@ class AlertsConfigurationAPI(object):
# built up the template vars dictionary depending on the event type (threshold, relative, etc.) # built up the template vars dictionary depending on the event type (threshold, relative, etc.)
# all extracted properties from the trigger are passed, the TICKScriptTemplateFiller entry point then forwards those to the appropriate function for template filling # all extracted properties from the trigger are passed, the TICKScriptTemplateFiller entry point then forwards those to the appropriate function for template filling
template_vars = TICKScriptTemplateFiller.fill_template_vars(event_type, db=db, measurement=measurement, field=field, influx_function=influx_function, template_vars = TICKScriptTemplateFiller.fill_template_vars(event_type, sfc=sfc, sfci=sfc_instance, policy=policy_id, db=db, measurement=measurement,
critical_value=critical_value, comparison_operator=comparison_operator, alert_period=alert_period, field=field, influx_function=influx_function, critical_value=critical_value, comparison_operator=comparison_operator,
topic_id=topic_id, event_id=event_id, where_clause=where_clause) alert_period=alert_period, topic_id=topic_id, event_id=event_id, where_clause=where_clause)
# create and activate alert task through the kapacitor HTTP API # create and activate alert task through the kapacitor HTTP API
kapacitor_api_tasks_url = "http://{0}:{1}/kapacitor/v1/tasks".format(kapacitor_host, kapacitor_port) kapacitor_api_tasks_url = "http://{0}:{1}/kapacitor/v1/tasks".format(kapacitor_host, kapacitor_port)
...@@ -283,9 +297,11 @@ class AlertsConfigurationAPI(object): ...@@ -283,9 +297,11 @@ class AlertsConfigurationAPI(object):
http_handlers = trigger.trigger_tpl["action"]["implementation"] http_handlers = trigger.trigger_tpl["action"]["implementation"]
# subscribe all http handlers to the created topic # subscribe all http handlers to the created topic
self._config_kapacitor_alert_handlers(kapacitor_host, kapacitor_port, sfc, sfc_instance, policy_id, topic_id, event_id, http_handlers, alert_handlers_errors) self._config_kapacitor_alert_handlers(kapacitor_host, kapacitor_port, sfc, sfc_instance, policy_id, resource_spec_trigger_id, topic_id, event_id,
http_handlers, alert_handlers_errors)
def _config_kapacitor_alert_handlers(self, kapacitor_host, kapacitor_port, sfc, sfc_i, policy_id, topic_id, event_id, http_handlers, alert_handlers_errors): def _config_kapacitor_alert_handlers(self, kapacitor_host, kapacitor_port, sfc, sfc_i, policy_id, trigger_id,
topic_id, event_id, http_handlers, alert_handlers_errors):
""" """
Handles the configuration of HTTP Post alert handlers. Handles the configuration of HTTP Post alert handlers.
...@@ -294,6 +310,7 @@ class AlertsConfigurationAPI(object): ...@@ -294,6 +310,7 @@ class AlertsConfigurationAPI(object):
:param sfc: service function chain identifier :param sfc: service function chain identifier
:param sfc_i: service function chain instance identifier :param sfc_i: service function chain instance identifier
:param policy_id: policy ID those triggers relate to :param policy_id: policy ID those triggers relate to
:param trigger_id: the resource specification trigger ID
:param topic_id: topic ID built of sfc, sfc instance and event_id :param topic_id: topic ID built of sfc, sfc instance and event_id
:param event_id: name of trigger :param event_id: name of trigger
:param http_handlers: list of handlers to subscribe :param http_handlers: list of handlers to subscribe
...@@ -302,6 +319,12 @@ class AlertsConfigurationAPI(object): ...@@ -302,6 +319,12 @@ class AlertsConfigurationAPI(object):
kapacitor_api_handlers_url = "http://{0}:{1}/kapacitor/v1/alerts/topics/{2}/handlers".format(kapacitor_host, kapacitor_port, topic_id) 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: for http_handler_url in http_handlers:
# check for flame_sfemc entry, if found replace with sfemc FQDN
if http_handler_url == SFEMC:
sfemc_fqdn = self.request.registry.settings['sfemc_fqdn']
http_handler_url = "http://{0}/{1}/{2}/{3}/{4}".format(sfemc_fqdn, sfc, sfc_i, policy_id, trigger_id)
handler_id = "{0}\n{1}\n{2}\n{3}\n{4}".format(sfc, sfc_i, policy_id, event_id, http_handler_url) handler_id = "{0}\n{1}\n{2}\n{3}\n{4}".format(sfc, sfc_i, policy_id, event_id, http_handler_url)
handler_id = self.get_hash(handler_id) handler_id = self.get_hash(handler_id)
kapacitor_http_request_body = fill_http_post_handler_vars(handler_id, http_handler_url) kapacitor_http_request_body = fill_http_post_handler_vars(handler_id, http_handler_url)
......
...@@ -2,6 +2,6 @@ tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0 ...@@ -2,6 +2,6 @@ tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0
policy_types: policy_types:
eu.ict-flame.policies.StateChange: eu.ict-flame.policies.Alert:
derived_from: tosca.policies.Update derived_from: tosca.policies.Root
\ No newline at end of file \ No newline at end of file
...@@ -14,8 +14,6 @@ pyramid.default_locale_name = en ...@@ -14,8 +14,6 @@ pyramid.default_locale_name = en
pyramid.includes = pyramid_debugtoolbar pyramid_exclog pyramid.includes = pyramid_debugtoolbar pyramid_exclog
exclog.ignore = exclog.ignore =
# Configuration file path
configuration_file_path = /etc/flame/clmc/service.conf
network_configuration_path = /vagrant/src/service/resources/GraphAPI/network_config.json network_configuration_path = /vagrant/src/service/resources/GraphAPI/network_config.json
......
...@@ -14,8 +14,6 @@ pyramid.default_locale_name = en ...@@ -14,8 +14,6 @@ pyramid.default_locale_name = en
pyramid.includes = pyramid_exclog pyramid.includes = pyramid_exclog
exclog.ignore = exclog.ignore =
# Configuration file path
configuration_file_path = /etc/flame/clmc/service.conf
network_configuration_path = /vagrant/src/service/resources/GraphAPI/network_config.json network_configuration_path = /vagrant/src/service/resources/GraphAPI/network_config.json
......
var sfc string
var sfci string
var policy string
var db string // database per service function chain, so db is named after sfc var db string // database per service function chain, so db is named after sfc
var rp = 'autogen' // default value for the retention policy var rp = 'autogen' // default value for the retention policy
...@@ -25,7 +31,7 @@ stream ...@@ -25,7 +31,7 @@ stream
.where(whereClause) .where(whereClause)
| deadman(throughputThreshold, alertPeriod) | deadman(throughputThreshold, alertPeriod)
.id(eventID) .id(eventID)
.details('db=' + db + ',measurement=' + measurement) .details('db=' + db + ',sfc=' + sfc + ',sfci=' + sfci + ',policy=' + policy)
.message(messageValue) .message(messageValue)
.topic(topicID) .topic(topicID)
.noRecoveries() .noRecoveries()
\ No newline at end of file
var sfc string
var sfci string
var policy string
var db string // database per service function chain, so db is named after sfc var db string // database per service function chain, so db is named after sfc
var rp = 'autogen' // default value for the retention policy var rp = 'autogen' // default value for the retention policy
...@@ -42,7 +48,7 @@ past ...@@ -42,7 +48,7 @@ past
.as('diff') .as('diff')
| alert() | alert()
.id(eventID) .id(eventID)
.details('db=' + db + ',measurement=' + measurement) .details('db=' + db + ',sfc=' + sfc + ',sfci=' + sfci + ',policy=' + policy)
.crit(comparisonLambda) .crit(comparisonLambda)
.message(messageValue) .message(messageValue)
.topic(topicID) .topic(topicID)
......
var sfc string
var sfci string
var policy string
var db string // database per service function chain, so db is named after sfc var db string // database per service function chain, so db is named after sfc
var rp = 'autogen' // default value for the retention policy var rp = 'autogen' // default value for the retention policy
...@@ -26,7 +32,7 @@ batch ...@@ -26,7 +32,7 @@ batch
.every(alertPeriod) .every(alertPeriod)
|alert() |alert()
.id(eventID) .id(eventID)
.details('db=' + db + ',measurement=' + measurement) .details('db=' + db + ',sfc=' + sfc + ',sfci=' + sfci + ',policy=' + policy)
.crit(comparisonLambda) .crit(comparisonLambda)
.message(messageValue) .message(messageValue)
.topic(topicID) .topic(topicID)
......
var sfc string
var sfci string
var policy string
var db string // database per service function chain, so db is named after sfc var db string // database per service function chain, so db is named after sfc
var rp = 'autogen' // default value for the retention policy var rp = 'autogen' // default value for the retention policy
...@@ -23,7 +29,7 @@ stream ...@@ -23,7 +29,7 @@ stream
.where(whereClause) .where(whereClause)
| alert() | alert()
.id(eventID) .id(eventID)
.details('db=' + db + ',measurement=' + measurement) .details('db=' + db + ',sfc=' + sfc + ',sfci=' + sfci + ',policy=' + policy)
.crit(comparisonLambda) .crit(comparisonLambda)
.message(messageValue) .message(messageValue)
.topic(topicID) .topic(topicID)
......
...@@ -13,7 +13,7 @@ topology_template: ...@@ -13,7 +13,7 @@ topology_template:
policies: policies:
- high_latency_policy: - high_latency_policy:
type: eu.ict-flame.policies.StateChange type: eu.ict-flame.policies.Alert
triggers: triggers:
high_latency: high_latency:
description: This event triggers when the mean network latency in a given location exceeds a given threshold (in ms). description: This event triggers when the mean network latency in a given location exceeds a given threshold (in ms).
...@@ -28,10 +28,10 @@ topology_template: ...@@ -28,10 +28,10 @@ topology_template:
comparison_operator: gt comparison_operator: gt
action: action:
implementation: implementation:
- http://sfemc.flame.eu/notify - flame_sfemc
- http://companyA.alert-handler.flame.eu/high-latency - http://companyA.alert-handler.flame.eu/high-latency
- requests_diff_policy: - requests_diff_policy:
type: eu.ict-flame.policies.StateChange type: eu.ict-flame.policies.Alert
triggers: triggers:
increase_in_requests: increase_in_requests:
description: | description: |
...@@ -51,7 +51,7 @@ topology_template: ...@@ -51,7 +51,7 @@ topology_template:
implementation: implementation:
- http://sfemc.flame.eu/notify - http://sfemc.flame.eu/notify
- low_requests_policy: - low_requests_policy:
type: eu.ict-flame.policies.StateChange type: eu.ict-flame.policies.Alert
triggers: triggers:
low_requests: low_requests:
description: | description: |
......
...@@ -13,7 +13,7 @@ topology_template: ...@@ -13,7 +13,7 @@ topology_template:
policies: policies:
- high_latency_policy: - high_latency_policy:
type: eu.ict-flame.policies.StateChange type: eu.ict-flame.policies.Alert
triggers: triggers:
high_latency: high_latency:
description: This event triggers when the mean network latency in a given location exceeds a given threshold (in ms). description: This event triggers when the mean network latency in a given location exceeds a given threshold (in ms).
...@@ -28,10 +28,10 @@ topology_template: ...@@ -28,10 +28,10 @@ topology_template:
comparison_operator: gt comparison_operator: gt
action: action:
implementation: implementation:
- http://sfemc.flame.eu/notify - flame_sfemc
- http://companyA.alert-handler.flame.eu/high-latency - http://companyA.alert-handler.flame.eu/high-latency
- requests_diff_policy: - requests_diff_policy:
type: eu.ict-flame.policies.StateChange type: eu.ict-flame.policies.Alert
triggers: triggers:
decrease_in_requests: decrease_in_requests:
description: | description: |
...@@ -49,9 +49,9 @@ topology_template: ...@@ -49,9 +49,9 @@ topology_template:
comparison_operator: lte comparison_operator: lte
action: action:
implementation: implementation:
- http://sfemc.flame.eu/notify - flame_sfemc
- low_requests_policy: - low_requests_policy:
type: eu.ict-flame.policies.StateChange type: eu.ict-flame.policies.Alert
triggers: triggers:
low_requests: low_requests:
description: | description: |
...@@ -70,5 +70,5 @@ topology_template: ...@@ -70,5 +70,5 @@ topology_template:
comparison_operator: lt comparison_operator: lt
action: action:
implementation: implementation:
- http://sfemc.flame.eu/notify - flame_sfemc
- http://companyA.alert-handler.flame.eu/low-requests - http://companyA.alert-handler.flame.eu/low-requests
tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0
description: TOSCA Alerts Configuration document
imports:
- flame_clmc_alerts_definitions.yaml
metadata:
sfc: companyA-VR
sfci: companyA-VR-premium
topology_template:
policies:
- high_latency_policy:
type: eu.ict-flame.policies.Alert
triggers:
high_latency:
description: This event triggers when the mean network latency in a given location exceeds a given threshold (in ms).
event_type: threshold
metric: network.latency
condition:
threshold: 45
granularity: 120
aggregation_method: mean
resource_type:
flame_sfc: companyA-VR # not allowed - sfc tag is automatically added in the filters
flame_location: watershed
comparison_operator: gt
action:
implementation:
- flame_sfemc
- http://companyA.alert-handler.flame.eu/high-latency
- requests_diff_policy:
type: eu.ict-flame.policies.Alert
triggers:
decrease_in_requests:
description: |
This event triggers when the number of requests has decreased relative to the number of requests received
120 seconds ago.
event_type: relative
metric: storage.requests
condition:
threshold: -100 # requests have decreased by at least 100
granularity: 120
resource_type:
flame_sfp: storage
flame_sf: storage-users
flame_location: watershed
comparison_operator: lte
action:
implementation:
- http://sfemc.flame.eu/notify
- low_requests_policy:
type: eu.ict-flame.policies.Alert
triggers:
low_requests:
description: |
This event triggers when the last reported number of requests for a given service function
falls behind a given threshold.
event_type: threshold
metric: storage.requests
condition:
threshold: 5
granularity: 60
aggregation_method: last
resource_type:
flame_sfp: storage
flame_sf: storage-users
flame_location: watershed
comparison_operator: lt
action:
implementation:
- http://sfemc.flame.eu/notify
- http://companyA.alert-handler.flame.eu/low-requests
tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0
description: TOSCA Alerts Configuration document
imports:
- flame_clmc_alerts_definitions.yaml
metadata:
sfc: companyA-VR
sfci: companyA-VR-premium
topology_template:
policies:
- high_latency_policy:
type: eu.ict-flame.policies.Alert
triggers:
high_latency:
description: This event triggers when the mean network latency in a given location exceeds a given threshold (in ms).
event_type: threshold
metric: network.latency
condition:
threshold: 45
granularity: 120
aggregation_method: mean
resource_type:
flame_sfci: companyA-VR-premium # not allowed - sfci tag is automatically added in the filters
flame_location: watershed
comparison_operator: gt
action:
implementation:
- flame_sfemc
- http://companyA.alert-handler.flame.eu/high-latency
- requests_diff_policy:
type: eu.ict-flame.policies.Alert
triggers:
decrease_in_requests:
description: |
This event triggers when the number of requests has decreased relative to the number of requests received
120 seconds ago.
event_type: relative
metric: storage.requests
condition:
threshold: -100 # requests have decreased by at least 100
granularity: 120
resource_type:
flame_sfp: storage
flame_sf: storage-users
flame_location: watershed
comparison_operator: lte
action:
implementation:
- http://sfemc.flame.eu/notify
- low_requests_policy:
type: eu.ict-flame.policies.Alert
triggers:
low_requests:
description: |
This event triggers when the last reported number of requests for a given service function
falls behind a given threshold.
event_type: threshold
metric: storage.requests
condition:
threshold: 5
granularity: 60
aggregation_method: last
resource_type:
flame_sfp: storage
flame_sf: storage-users
flame_location: watershed
comparison_operator: lt
action:
implementation:
- http://sfemc.flame.eu/notify
- http://companyA.alert-handler.flame.eu/low-requests
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