
Updated all templates with Standard shortname Change-Id: I4d591da41351659cc2d81e4fe835c1637a7c69d1 Closes-Bug: #1454340
209 lines
9.6 KiB
Python
209 lines
9.6 KiB
Python
# 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 logging
|
|
|
|
from translator.toscalib.common.exception import TypeMismatchError
|
|
from translator.toscalib.common.exception import UnknownFieldError
|
|
from translator.toscalib.elements.interfaces import CONFIGURE
|
|
from translator.toscalib.elements.interfaces import CONFIGURE_SHORTNAME
|
|
from translator.toscalib.elements.interfaces import InterfacesDef
|
|
from translator.toscalib.elements.interfaces import LIFECYCLE
|
|
from translator.toscalib.elements.interfaces import LIFECYCLE_SHORTNAME
|
|
from translator.toscalib.elements.relationshiptype import RelationshipType
|
|
from translator.toscalib.entity_template import EntityTemplate
|
|
from translator.toscalib.relationship_template import RelationshipTemplate
|
|
from translator.toscalib.utils.gettextutils import _
|
|
|
|
log = logging.getLogger('tosca')
|
|
|
|
|
|
class NodeTemplate(EntityTemplate):
|
|
'''Node template from a Tosca profile.'''
|
|
def __init__(self, name, node_templates, custom_def=None,
|
|
available_rel_tpls=None, available_rel_types=None):
|
|
super(NodeTemplate, self).__init__(name, node_templates[name],
|
|
'node_type',
|
|
custom_def)
|
|
self.templates = node_templates
|
|
self.custom_def = custom_def
|
|
self.related = {}
|
|
self.relationship_tpl = []
|
|
self.available_rel_tpls = available_rel_tpls
|
|
self.available_rel_types = available_rel_types
|
|
self._relationships = {}
|
|
|
|
@property
|
|
def relationships(self):
|
|
if not self._relationships:
|
|
requires = self.requirements
|
|
if requires:
|
|
for r in requires:
|
|
for r1, value in r.items():
|
|
if isinstance(value, dict):
|
|
explicit = self._get_explicit_relationship(
|
|
r, value)
|
|
if explicit:
|
|
for key, value in explicit.items():
|
|
self._relationships[key] = value
|
|
else:
|
|
# need to check for short notation of requirements
|
|
keys = self.type_definition.relationship.keys()
|
|
for rtype in keys:
|
|
if r1 == rtype.capability_name:
|
|
related_tpl = NodeTemplate(
|
|
value, self.templates,
|
|
self.custom_def)
|
|
self._relationships[rtype] = related_tpl
|
|
related_tpl._add_relationship_template(
|
|
r, rtype.type)
|
|
|
|
return self._relationships
|
|
|
|
def _get_explicit_relationship(self, req, value):
|
|
"""Handle explicit relationship
|
|
|
|
For example,
|
|
- req:
|
|
node: DBMS
|
|
relationship: tosca.relationships.HostedOn
|
|
"""
|
|
explicit_relation = {}
|
|
node = value.get('node')
|
|
if node:
|
|
# TODO(spzala) implement look up once Glance meta data is available
|
|
# to find a matching TOSCA node using the TOSCA types
|
|
msg = _('Lookup by TOSCA types are not supported. '
|
|
'Requirement for %s can not be full-filled.') % self.name
|
|
if (node in list(self.type_definition.TOSCA_DEF.keys())
|
|
or node in self.custom_def):
|
|
raise NotImplementedError(msg)
|
|
related_tpl = NodeTemplate(node, self.templates, self.custom_def)
|
|
relationship = value.get('relationship')
|
|
# check if it's type has relationship defined
|
|
if not relationship:
|
|
parent_reqs = self.type_definition.get_all_requirements()
|
|
for key in req.keys():
|
|
for req_dict in parent_reqs:
|
|
if key in req_dict.keys():
|
|
relationship = (req_dict.get(key).
|
|
get('relationship'))
|
|
break
|
|
if relationship:
|
|
found_relationship_tpl = False
|
|
# apply available relationship templates if found
|
|
for tpl in self.available_rel_tpls:
|
|
if tpl.name == relationship:
|
|
rtype = RelationshipType(tpl.type)
|
|
explicit_relation[rtype] = related_tpl
|
|
self.relationship_tpl.append(tpl)
|
|
found_relationship_tpl = True
|
|
# create relationship template object.
|
|
if not found_relationship_tpl:
|
|
if isinstance(relationship, dict):
|
|
relationship = relationship.get('type')
|
|
rel_prfx = self.type_definition.RELATIONSHIP_PREFIX
|
|
if not relationship.startswith(rel_prfx):
|
|
relationship = rel_prfx + relationship
|
|
for rtype in self.type_definition.relationship.keys():
|
|
if rtype.type == relationship:
|
|
explicit_relation[rtype] = related_tpl
|
|
related_tpl._add_relationship_template(req,
|
|
rtype.type)
|
|
elif self.available_rel_types:
|
|
if relationship in self.available_rel_types.keys():
|
|
rel_type_def = self.available_rel_types.\
|
|
get(relationship)
|
|
if 'derived_from' in rel_type_def \
|
|
and rtype.type == \
|
|
rel_type_def.get('derived_from'):
|
|
explicit_relation[rtype] = related_tpl
|
|
related_tpl.\
|
|
_add_relationship_template(req,
|
|
rtype.type)
|
|
return explicit_relation
|
|
|
|
def _add_relationship_template(self, requirement, rtype):
|
|
req = requirement.copy()
|
|
req['type'] = rtype
|
|
tpl = RelationshipTemplate(req, rtype, None)
|
|
self.relationship_tpl.append(tpl)
|
|
|
|
def get_relationship_template(self):
|
|
return self.relationship_tpl
|
|
|
|
def _add_next(self, nodetpl, relationship):
|
|
self.related[nodetpl] = relationship
|
|
|
|
@property
|
|
def related_nodes(self):
|
|
if not self.related:
|
|
for relation, node in self.type_definition.relationship.items():
|
|
for tpl in self.templates:
|
|
if tpl == node.type:
|
|
self.related[NodeTemplate(tpl)] = relation
|
|
return self.related.keys()
|
|
|
|
def validate(self, tosca_tpl=None):
|
|
self._validate_capabilities()
|
|
self._validate_requirements()
|
|
self._validate_properties(self.entity_tpl, self.type_definition)
|
|
self._validate_interfaces()
|
|
for prop in self.get_properties_objects():
|
|
prop.validate()
|
|
|
|
def _validate_requirements(self):
|
|
type_requires = self.type_definition.get_all_requirements()
|
|
allowed_reqs = ["template"]
|
|
if type_requires:
|
|
for treq in type_requires:
|
|
for key, value in treq.items():
|
|
allowed_reqs.append(key)
|
|
if isinstance(value, dict):
|
|
for key in value:
|
|
allowed_reqs.append(key)
|
|
|
|
requires = self.type_definition.get_value(self.REQUIREMENTS,
|
|
self.entity_tpl)
|
|
if requires:
|
|
if not isinstance(requires, list):
|
|
raise TypeMismatchError(
|
|
what='Requirements of template %s' % self.name,
|
|
type='list')
|
|
for req in requires:
|
|
for r1, value in req.items():
|
|
if isinstance(value, dict):
|
|
allowed_reqs.append(r1)
|
|
self._common_validate_field(req, allowed_reqs, 'Requirements')
|
|
|
|
def _validate_interfaces(self):
|
|
ifaces = self.type_definition.get_value(self.INTERFACES,
|
|
self.entity_tpl)
|
|
if ifaces:
|
|
for i in ifaces:
|
|
for name, value in ifaces.items():
|
|
if name in (LIFECYCLE, LIFECYCLE_SHORTNAME):
|
|
self._common_validate_field(
|
|
value, InterfacesDef.
|
|
interfaces_node_lifecycle_operations,
|
|
'Interfaces')
|
|
elif name in (CONFIGURE, CONFIGURE_SHORTNAME):
|
|
self._common_validate_field(
|
|
value, InterfacesDef.
|
|
interfaces_relationship_confiure_operations,
|
|
'Interfaces')
|
|
else:
|
|
raise UnknownFieldError(
|
|
what='Interfaces of template %s' % self.name,
|
|
field=name)
|