template validate API controller and API handler

Change-Id: I1fd681e14eb544e7eddfe17c51c70485c05f041c
This commit is contained in:
liathartal 2016-06-05 08:37:23 +00:00
parent 9a7fbdb4d7
commit 81e232a1af
11 changed files with 115 additions and 28 deletions

View File

@ -3,5 +3,6 @@
"get resource": "role:admin",
"list resources": "role:admin",
"list alarms": "role:admin",
"get rca": "role:admin"
"get rca": "role:admin",
"template validate": "role:admin"
}

View File

@ -38,20 +38,20 @@ class AlarmsController(RootRestController):
enforce("list alarms", pecan.request.headers,
pecan.request.enforcer, {})
LOG.info(_LI('received list alarms with vitrage id %s') %
LOG.info(_LI('returns list alarms with vitrage id %s') %
vitrage_id)
try:
if pecan.request.cfg.api.use_mock_file:
return self.get_mock_data('alarms.sample.json')
else:
return self.get_alarms(vitrage_id)
return self._get_alarms(vitrage_id)
except Exception as e:
LOG.exception('failed to get alarms %s', e)
abort(404, str(e))
@staticmethod
def get_alarms(vitrage_id=None):
def _get_alarms(vitrage_id=None):
alarms_json = pecan.request.client.call(pecan.request.context,
'get_alarms',
arg=vitrage_id)

View File

@ -13,6 +13,7 @@
from vitrage.api.controllers.v1 import alarms
from vitrage.api.controllers.v1 import rca
from vitrage.api.controllers.v1 import resource
from vitrage.api.controllers.v1 import template
from vitrage.api.controllers.v1 import topology
@ -21,3 +22,4 @@ class V1Controller(object):
resources = resource.ResourcesController()
alarms = alarms.AlarmsController()
rca = rca.RCAController()
template = template.TemplateController()

View File

@ -0,0 +1,58 @@
# Copyright 2016 - Nokia Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import json
import pecan
from oslo_log import log
from pecan.core import abort
from vitrage.api.controllers.rest import RootRestController
from vitrage.api.policy import enforce
from vitrage.i18n import _LI
LOG = log.getLogger(__name__)
class TemplateController(RootRestController):
@pecan.expose('json')
def post(self, **kwargs):
LOG.info(_LI('validate template. args: %s') % kwargs)
enforce("template validate",
pecan.request.headers,
pecan.request.enforcer,
{})
template_def = kwargs['template_def']
try:
return self._validate(template_def)
except Exception as e:
LOG.exception('failed to validate template(s) %s', e)
abort(404, str(e))
@staticmethod
def _validate(template_def):
result_json = pecan.request.client.call(pecan.request.context,
'validate_template',
template_def=template_def)
try:
return json.loads(result_json)
except Exception as e:
LOG.exception('failed to open file %s ', e)
abort(404, str(e))

View File

@ -1,4 +1,4 @@
# Copyright 2016 - Alcatel-Lucent
# Copyright 2016 - Nokia Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain

View File

@ -23,6 +23,8 @@ from vitrage.datasources.nova.host import NOVA_HOST_DATASOURCE
from vitrage.datasources.nova.instance import NOVA_INSTANCE_DATASOURCE
from vitrage.datasources.nova.zone import NOVA_ZONE_DATASOURCE
from vitrage.datasources import OPENSTACK_CLUSTER
from vitrage.evaluator.template_validation.template_syntax_validator import \
syntax_validation
from vitrage.graph import create_algorithm
from vitrage.graph import Direction
@ -112,7 +114,7 @@ class EntityGraphApis(object):
root_id=root,
depth=depth)
return found_graph.output_graph()
return found_graph.json_output_graph()
def get_rca(self, ctx, root):
LOG.debug("EntityGraphApis get_rca root:%s", str(root))
@ -128,7 +130,7 @@ class EntityGraphApis(object):
direction=Direction.OUT)
unified_graph = found_graph_in
unified_graph.union(found_graph_out)
json_graph = unified_graph.output_graph(
json_graph = unified_graph.json_output_graph(
inspected_index=self._find_rca_index(unified_graph, root))
return json_graph
@ -168,3 +170,26 @@ class EntityGraphApis(object):
if vertex == root:
return root_index
return 0
class TemplateApis(object):
def validate_template(self, ctx, template_def):
LOG.debug("EntityGraphApis validate_template template definition:"
"%s", str(template_def))
result = syntax_validation(template_def)
if not result.is_valid:
return self._extract_json_result('validation failed', result)
return self._extract_json_result('validation OK', result)
@staticmethod
def _extract_json_result(status, result):
return json.dumps({
'status': status,
'description': result.description,
'message': str(result.comment)
})

View File

@ -17,7 +17,8 @@ from oslo_log import log
import oslo_messaging
from oslo_service import service as os_service
from vitrage.entity_graph.api_handler.entity_graph_api import EntityGraphApis
from vitrage.api_handler.entity_graph_api import EntityGraphApis
from vitrage.api_handler.entity_graph_api import TemplateApis
from vitrage import messaging
from vitrage import rpc as vitrage_rpc
@ -43,7 +44,7 @@ class VitrageApiHandlerService(os_service.Service):
target = oslo_messaging.Target(topic=self.conf.rpc_topic,
server=rabbit_hosts)
endpoints = [EntityGraphApis(self.entity_graph), ]
endpoints = [EntityGraphApis(self.entity_graph), TemplateApis()]
server = vitrage_rpc.get_server(target, endpoints, transport)

View File

@ -19,10 +19,10 @@ import sys
from oslo_service import service as os_service
from vitrage.api_handler import service as api_handler_svc
from vitrage.common.constants import EntityCategory
from vitrage.datasources import launcher as datasource_launcher
from vitrage.datasources import OPENSTACK_CLUSTER
from vitrage.entity_graph.api_handler import service as api_handler_svc
from vitrage.entity_graph.consistency import service as consistency_svc
from vitrage.entity_graph.initialization_status import InitializationStatus
from vitrage.entity_graph.processor import entity_graph

View File

@ -18,49 +18,49 @@ from vitrage.evaluator.actions.base import action_types
error_msgs = {
# General 1-19
1: '"template_id" field contains incorrect string value.',
1: 'template_id field contains incorrect string value.',
2: 'Duplicate template_id definition.',
3: '"template_id" does not appear in the definition block.',
3: 'template_id does not appear in the definition block.',
# definitions section 20-39
20: 'definitions section must contain "entities" field.',
21: '"definitions" section is a mandatory section.',
20: 'definitions section must contain entities field.',
21: 'definitions section is a mandatory section.',
# Entities syntax error messages 40-59
41: 'Entity definition must contain "template_id" field.',
42: 'Entity definition must contain "category" field.',
41: 'Entity definition must contain template_id field.',
42: 'Entity definition must contain category field.',
43: 'At least one entity must be defined.',
45: 'Invalid entity category. Category must be from types: '
'%s' % entities_categories,
46: 'Entity field is required.',
# metadata section syntax error messages 60-79
60: 'metadata section must contain "id" field.',
62: '"metadata" is a mandatory section.',
60: 'metadata section must contain id field.',
62: 'metadata is a mandatory section.',
# scenarios section 80-99
80: '"scenarios" is a mandatory section].',
80: 'scenarios is a mandatory section].',
81: 'At least one scenario must be defined.',
82: 'scenario field is required.',
83: 'Entity definition must contain "condition" field.',
84: 'Entity definition must contain "actions" field.',
83: 'Entity definition must contain condition field.',
84: 'Entity definition must contain actions field.',
85: 'Failed to convert condition.',
# relationships syntax error messages 100-119
100: 'Invalid relation type. Relation type must be from types: '
'%s' % edge_labels,
101: 'Relationship field is required.',
102: 'Relationship definition must contain "source" field.',
103: 'Relationship definition must contain "target" field.',
104: 'Relationship definition must contain "template_id" field.',
102: 'Relationship definition must contain source field.',
103: 'Relationship definition must contain target field.',
104: 'Relationship definition must contain template_id field.',
# actions syntax error messages 120-139
120: 'Invalid action type. Action type must be from types: '
'%s' % action_types,
121: 'At least one action must be defined.',
122: 'Action field is required.',
123: 'Relationship definition must contain "action_type" field.',
124: 'Relationship definition must contain "action_target" field.',
123: 'Relationship definition must contain action_type field.',
124: 'Relationship definition must contain action_target field.',
125: 'raise_alarm action must contain alarm_name field in properties '
'block.',
126: 'raise_alarm action must contain severity field in properties block.',

View File

@ -323,7 +323,7 @@ class Graph(object):
pass
@abc.abstractmethod
def output_graph(self, **kwargs):
def json_output_graph(self, **kwargs):
pass
@abc.abstractmethod

View File

@ -260,7 +260,7 @@ class NXGraph(Graph):
nodes.append((node_id_to_test, node_data))
return nodes, edges_filtered2
def output_graph(self, **kwargs):
def json_output_graph(self, **kwargs):
node_link_data = json_graph.node_link_data(self._g)
node_link_data.update(kwargs)