Newer
Older
#!/usr/bin/python3
"""
// © University of Southampton IT Innovation Centre, 2018
//
// Copyright in this software belongs to University of Southampton
// IT Innovation Centre of Gamma House, Enterprise Road,
// Chilworth Science Park, Southampton, SO16 7NS, UK.
//
// This software may not be used, sold, licensed, transferred, copied
// or reproduced in whole or in part in any manner or form or in or
// on any media by any person other than in accordance with the terms
// of the Licence Agreement supplied with the software, or otherwise
// without the prior written consent of the copyright owners.
//
// This software is distributed WITHOUT ANY WARRANTY, without even the
// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE, except where stated in the Licence Agreement supplied with
// the software.
//
// Created By : Nikolay Stanchev
// Created Date : 16-08-2018
// Created for Project : FLAME
"""
# Python standard libs
# PIP installed libs
from schema import Schema, And, Or, Optional, SchemaError
# This module defines the schema objects for the TOSCA Alert Specification:
#
# * flame_clmc_alerts_definitions.yaml must be the only import
# * metadata section must be present (with key-value pairs for sfc and sfci)
# * 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 is of type eu.ict-flame.policies.Alert
# * 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
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 = (
Nikolay Stanchev
committed
"count", "mean", "median", "mode", "sum", "first", "last", "max", "min", "spread", "stddev"
)
# Kapacitor Tick Script template IDs
TICK_SCRIPT_TEMPLATES = ("threshold", "relative", "deadman")
# Allowed comparison operators and their logical values
COMPARISON_OPERATORS = {"lt": "<", "gt": ">", "lte": "<=", "gte": ">=", "eq": "==", "neq": "!="}
# Regular expression for validating http handlers
r'^https?://' # http:// or https://
r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' # domain, e.g. example.domain.com
r'localhost|' # or localhost...
r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # or IP address (IPv4 format)
r'(?::\d{2,5})?' # optional port number
r'(?:[/?#][^\s]*)?$', # URL path or query parameters
# Global tags allowed to be used for filtering in the trigger condition
Nikolay Stanchev
committed
CLMC_INFORMATION_MODEL_GLOBAL_TAGS = {"flame_sfp", "flame_sf", "flame_server", "flame_location"}
# NOTICE that "flame_sfc", "flame_sfci" are not allowed, even though they are part of the CLMC Information Model
Nikolay Stanchev
committed
# This is because those two tags are automatically added to the InfluxDB queries - the required values are retrieved from the alert spec. metadata
Nikolay Stanchev
committed
# "flame_sfe" cannot be used as well, because the value of this tag is only known at runtime.
ALERTS_SPECIFICATION_SCHEMA = Schema({
"tosca_definitions_version": And(str, lambda v: v == "tosca_simple_profile_for_nfv_1_0_0"),
Optional("description"): str,
"imports": And([lambda s: s.endswith("flame_clmc_alerts_definitions.yaml")], lambda l: len(l) == 1),
"metadata": {
Nikolay Stanchev
committed
"servicefunctionchain": str
Nikolay Stanchev
committed
# TODO next release - uncomment
# "sfc": str,
# "sfci": str
},
"topology_template": {
"policies": [
{
str: {
"type": "eu.ict-flame.policies.Alert",
"triggers": And({
str: {
Optional("description"): str,
"event_type": And(str, lambda s: s in TICK_SCRIPT_TEMPLATES),
"metric": And(str, lambda s: len(s.split('.', 1)) == 2),
"condition": {
"threshold": Or(int, float),
"granularity": And(int, lambda p: p > 0),
Optional("aggregation_method"): And(str, lambda s: s in INFLUX_QL_FUNCTIONS),
Optional("resource_type"): {
And(str, lambda s: s in CLMC_INFORMATION_MODEL_GLOBAL_TAGS): str
},
Optional("comparison_operator"): And(str, lambda s: s in COMPARISON_OPERATORS)
},
"action": {
"implementation":
[
Or(SFEMC, And(str, lambda s: URL_REGEX.match(s) is not None))
]
}
}
}, lambda l: len(l) > 0)
}
}
]
}
})
def validate_clmc_alerts_specification(tosca_yaml_tpl, include_error=False):
CLMC validation for the TOSCA alerts specification, uses the schema defined in alerts_specification_schema.py
:param tosca_yaml_tpl: the tosca template to validate (as python dictionary object)
:param include_error: a flag indicating whether the output of the function should include a caught SchemaError
(if set to True and no error is thrown, returns None as the error object)
:return: True/False if the tosca_tpl is valid/invalid along with any error (None if no error) that was thrown during validation (if argument include_error is set to True)
try:
ALERTS_SPECIFICATION_SCHEMA.validate(tosca_yaml_tpl)
valid, err = True, None
except SchemaError as schema_error:
valid, err = False, schema_error
if include_error:
return valid, err