Enable Translator with new TOSCA library (2)

Make changes to use new TOSCA pypi library.

Partially Implements: blueprint use-tosca-parser-library

Change-Id: I6520a2418ca5a9452babc27393aa5bee3870abfd
This commit is contained in:
spzala 2015-09-02 13:28:29 -07:00
parent 827e72e469
commit 717b855180
64 changed files with 135 additions and 4369 deletions

View File

@ -16,12 +16,13 @@ import math
import numbers
import os
import re
from translator.toscalib.tosca_template import ToscaTemplate
from translator.toscalib.utils.gettextutils import _
import translator.toscalib.utils.yamlparser
from toscaparser.tosca_template import ToscaTemplate
from toscaparser.utils.gettextutils import _
import toscaparser.utils.yamlparser
from translator.hot.tosca_translator import TOSCATranslator as Translator
import yaml
YAML_ORDER_PARSER = translator.toscalib.utils.yamlparser.simple_ordered_parse
YAML_ORDER_PARSER = toscaparser.utils.yamlparser.simple_ordered_parse
log = logging.getLogger('tosca')
@ -221,10 +222,9 @@ class TranslationUtils(object):
os.path.dirname(os.path.abspath(__file__)), hot_file)
tosca = ToscaTemplate(tosca_tpl, params)
translate = translator.hot.tosca_translator.TOSCATranslator(tosca,
params)
translate = Translator(tosca, params)
output = translate.translate()
output_dict = translator.toscalib.utils.yamlparser.simple_parse(output)
output_dict = toscaparser.utils.yamlparser.simple_parse(output)
expected_output_dict = YamlUtils.get_dict(expected_hot_tpl)
return CompareUtils.diff_dicts(output_dict, expected_output_dict)

View File

@ -14,9 +14,9 @@
from collections import OrderedDict
import six
from translator.toscalib.functions import GetInput
from translator.toscalib.nodetemplate import NodeTemplate
from translator.toscalib.utils.gettextutils import _
from toscaparser.functions import GetInput
from toscaparser.nodetemplate import NodeTemplate
from toscaparser.utils.gettextutils import _
SECTIONS = (TYPE, PROPERTIES, MEDADATA, DEPENDS_ON, UPDATE_POLICY,

View File

@ -12,6 +12,7 @@
from collections import OrderedDict
from toscaparser.tests.base import TestCase
from translator.hot.syntax.hot_parameter import CONSTRAINTS
from translator.hot.syntax.hot_parameter import DEFAULT
from translator.hot.syntax.hot_parameter import DESCRIPTION
@ -19,7 +20,6 @@ from translator.hot.syntax.hot_parameter import HIDDEN
from translator.hot.syntax.hot_parameter import HotParameter
from translator.hot.syntax.hot_parameter import LABEL
from translator.hot.syntax.hot_parameter import TYPE
from translator.toscalib.tests.base import TestCase
TEST_CONSTRAINTS = {'equal': 'allowed_values', 'greater_than': 'range'}

View File

@ -12,12 +12,12 @@
from collections import OrderedDict
from toscaparser.parameters import Input
from toscaparser.tests.base import TestCase
from toscaparser.utils.gettextutils import _
import toscaparser.utils.yamlparser
from translator.common.utils import CompareUtils
from translator.hot.translate_inputs import TranslateInputs
from translator.toscalib.parameters import Input
from translator.toscalib.tests.base import TestCase
from translator.toscalib.utils.gettextutils import _
import translator.toscalib.utils.yamlparser
class ToscaTemplateInputValidationTest(TestCase):
@ -25,7 +25,7 @@ class ToscaTemplateInputValidationTest(TestCase):
def _translate_input_test(self, tpl_snippet, input_params,
expectedmessage=None,
expected_hot_params=None):
inputs_dict = (translator.toscalib.utils.yamlparser.
inputs_dict = (toscaparser.utils.yamlparser.
simple_parse(tpl_snippet)['inputs'])
inputs = []
for name, attrs in inputs_dict.items():

View File

@ -11,10 +11,10 @@
# under the License.
import os
from toscaparser.tests.base import TestCase
from toscaparser.tosca_template import ToscaTemplate
import toscaparser.utils.yamlparser
from translator.hot.tosca_translator import TOSCATranslator
from translator.toscalib.tests.base import TestCase
from translator.toscalib.tosca_template import ToscaTemplate
import translator.toscalib.utils.yamlparser
class ToscaTemplateOutputTest(TestCase):
@ -41,7 +41,7 @@ class ToscaTemplateOutputTest(TestCase):
['mongo_server', 'networks', 'private', 0]}}}
hot_translation_dict = \
translator.toscalib.utils.yamlparser.simple_parse(hot_translation)
toscaparser.utils.yamlparser.simple_parse(hot_translation)
outputs = hot_translation_dict.get('outputs')
for resource_name in outputs:

View File

@ -10,18 +10,18 @@
# License for the specific language governing permissions and limitations
# under the License.
from toscaparser.common.exception import InvalidPropertyValueError
from toscaparser.nodetemplate import NodeTemplate
from toscaparser.tests.base import TestCase
from toscaparser.utils.gettextutils import _
import toscaparser.utils.yamlparser
from translator.hot.tosca.tosca_block_storage import ToscaBlockStorage
from translator.toscalib.common.exception import InvalidPropertyValueError
from translator.toscalib.nodetemplate import NodeTemplate
from translator.toscalib.tests.base import TestCase
from translator.toscalib.utils.gettextutils import _
import translator.toscalib.utils.yamlparser
class ToscaBlockStoreTest(TestCase):
def _tosca_blockstore_test(self, tpl_snippet, expectedprops):
nodetemplates = (translator.toscalib.utils.yamlparser.
nodetemplates = (toscaparser.utils.yamlparser.
simple_parse(tpl_snippet)['node_templates'])
name = list(nodetemplates.keys())[0]
try:

View File

@ -10,17 +10,17 @@
# License for the specific language governing permissions and limitations
# under the License.
from toscaparser.nodetemplate import NodeTemplate
from toscaparser.tests.base import TestCase
from toscaparser.utils.gettextutils import _
import toscaparser.utils.yamlparser
from translator.hot.tosca.tosca_compute import ToscaCompute
from translator.toscalib.nodetemplate import NodeTemplate
from translator.toscalib.tests.base import TestCase
from translator.toscalib.utils.gettextutils import _
import translator.toscalib.utils.yamlparser
class ToscaComputeTest(TestCase):
def _tosca_compute_test(self, tpl_snippet, expectedprops):
nodetemplates = (translator.toscalib.utils.yamlparser.
nodetemplates = (toscaparser.utils.yamlparser.
simple_parse(tpl_snippet)['node_templates'])
name = list(nodetemplates.keys())[0]
try:

View File

@ -11,15 +11,15 @@
# under the License.
import mock
from toscaparser.tests.base import TestCase
from translator.hot.tosca.custom_types.tosca_elasticsearch import (
ToscaElasticsearch
)
from translator.toscalib.tests.base import TestCase
class ToscaElasticsearchTest(TestCase):
@mock.patch('translator.toscalib.nodetemplate.NodeTemplate')
@mock.patch('toscaparser.nodetemplate.NodeTemplate')
@mock.patch('translator.hot.tosca.custom_types.tosca_elasticsearch.'
'HotResource.__init__')
def test_init(self, mock_hotres_init, mock_node):
@ -29,7 +29,7 @@ class ToscaElasticsearchTest(TestCase):
self.assertEqual(ToscaElasticsearch.toscatype,
'tosca.nodes.SoftwareComponent.Elasticsearch')
@mock.patch('translator.toscalib.nodetemplate.NodeTemplate')
@mock.patch('toscaparser.nodetemplate.NodeTemplate')
@mock.patch('translator.hot.tosca.custom_types.tosca_elasticsearch.'
'HotResource.__init__')
def test_handle_properties(self, mock_hotres_init, mock_node):

View File

@ -11,13 +11,13 @@
# under the License.
import mock
from toscaparser.tests.base import TestCase
from translator.hot.tosca.custom_types.tosca_kibana import ToscaKibana
from translator.toscalib.tests.base import TestCase
class ToscaKibanaTest(TestCase):
@mock.patch('translator.toscalib.nodetemplate.NodeTemplate')
@mock.patch('toscaparser.nodetemplate.NodeTemplate')
@mock.patch('translator.hot.tosca.custom_types.tosca_kibana.'
'HotResource.__init__')
def test_init(self, mock_hotres_init, mock_node):
@ -27,7 +27,7 @@ class ToscaKibanaTest(TestCase):
self.assertEqual(ToscaKibana.toscatype,
'tosca.nodes.SoftwareComponent.Kibana')
@mock.patch('translator.toscalib.nodetemplate.NodeTemplate')
@mock.patch('toscaparser.nodetemplate.NodeTemplate')
@mock.patch('translator.hot.tosca.custom_types.tosca_kibana.'
'HotResource.__init__')
def test_handle_properties(self, mock_hotres_init, mock_node):

View File

@ -10,17 +10,17 @@
# License for the specific language governing permissions and limitations
# under the License.
from toscaparser.nodetemplate import NodeTemplate
from toscaparser.tests.base import TestCase
from toscaparser.utils.gettextutils import _
import toscaparser.utils.yamlparser
from translator.hot.tosca.tosca_object_storage import ToscaObjectStorage
from translator.toscalib.nodetemplate import NodeTemplate
from translator.toscalib.tests.base import TestCase
from translator.toscalib.utils.gettextutils import _
import translator.toscalib.utils.yamlparser
class ToscaObjectStoreTest(TestCase):
def _tosca_objectstore_test(self, tpl_snippet, expectedprops):
nodetemplates = (translator.toscalib.utils.yamlparser.
nodetemplates = (toscaparser.utils.yamlparser.
simple_parse(tpl_snippet)['node_templates'])
name = list(nodetemplates.keys())[0]
try:

View File

@ -12,11 +12,11 @@
# under the License.
import logging
from toscaparser.common.exception import InvalidPropertyValueError
from toscaparser.elements.scalarunit import ScalarUnit_Size
from toscaparser.functions import GetInput
from toscaparser.utils.gettextutils import _
from translator.hot.syntax.hot_resource import HotResource
from translator.toscalib.common.exception import InvalidPropertyValueError
from translator.toscalib.elements.scalarunit import ScalarUnit_Size
from translator.toscalib.functions import GetInput
from translator.toscalib.utils.gettextutils import _
log = logging.getLogger("tosca")

View File

@ -11,8 +11,8 @@
# License for the specific language governing permissions and limitations
# under the License.
from toscaparser.functions import GetInput
from translator.hot.syntax.hot_resource import HotResource
from translator.toscalib.functions import GetInput
class ToscaBlockStorageAttachment(HotResource):

View File

@ -12,9 +12,9 @@
# under the License.
import logging
from translator.common.utils import MemoryUnit
from toscaparser.utils.validateutils import TOSCAVersionProperty
import translator.common.utils
from translator.hot.syntax.hot_resource import HotResource
from translator.toscalib.utils.validateutils import TOSCAVersionProperty
log = logging.getLogger('tosca')
# A design issue to be resolved is how to translate the generic TOSCA server
@ -123,15 +123,15 @@ class ToscaCompute(HotResource):
# flavors that fit the mem size
mem = properties.get('mem_size')
if mem:
mem = MemoryUnit.convert_unit_size_to_num(mem,
'MB')
mem = translator.common.utils.MemoryUnit.convert_unit_size_to_num(
mem, 'MB')
match_cpu_mem = self._match_flavors(match_cpu, FLAVORS,
'mem_size', mem)
# flavors that fit the disk size
disk = properties.get('disk_size')
if disk:
disk = MemoryUnit.convert_unit_size_to_num(disk,
'GB')
disk = translator.common.utils.MemoryUnit.\
convert_unit_size_to_num(disk, 'GB')
match_cpu_mem_disk = self._match_flavors(match_cpu_mem, FLAVORS,
'disk_size', disk)
# if multiple match, pick the flavor with the least memory

View File

@ -11,8 +11,8 @@
# License for the specific language governing permissions and limitations
# under the License.
from toscaparser.common.exception import InvalidPropertyValueError
from translator.hot.syntax.hot_resource import HotResource
from translator.toscalib.common.exception import InvalidPropertyValueError
class ToscaNetwork(HotResource):

View File

@ -11,8 +11,8 @@
# License for the specific language governing permissions and limitations
# under the License.
from toscaparser.elements.scalarunit import ScalarUnit_Size
from translator.hot.syntax.hot_resource import HotResource
from translator.toscalib.elements.scalarunit import ScalarUnit_Size
class ToscaObjectStorage(HotResource):

View File

@ -12,11 +12,11 @@
# under the License.
import logging
from toscaparser.dataentity import DataEntity
from toscaparser.elements.scalarunit import ScalarUnit_Size
from toscaparser.utils.gettextutils import _
from toscaparser.utils.validateutils import TOSCAVersionProperty
from translator.hot.syntax.hot_parameter import HotParameter
from translator.toscalib.dataentity import DataEntity
from translator.toscalib.elements.scalarunit import ScalarUnit_Size
from translator.toscalib.utils.gettextutils import _
from translator.toscalib.utils.validateutils import TOSCAVersionProperty
INPUT_CONSTRAINTS = (CONSTRAINTS, DESCRIPTION, LENGTH, RANGE,

View File

@ -13,6 +13,10 @@
import six
from toscaparser.functions import GetAttribute
from toscaparser.functions import GetInput
from toscaparser.functions import GetProperty
from toscaparser.relationship_template import RelationshipTemplate
from translator.hot.syntax.hot_resource import HotResource
from translator.hot.tosca.custom_types.tosca_collectd import ToscaCollectd
from translator.hot.tosca.custom_types.tosca_elasticsearch import (
@ -41,10 +45,6 @@ from translator.hot.tosca.tosca_software_component import (
)
from translator.hot.tosca.tosca_web_application import ToscaWebApplication
from translator.hot.tosca.tosca_webserver import ToscaWebserver
from translator.toscalib.functions import GetAttribute
from translator.toscalib.functions import GetInput
from translator.toscalib.functions import GetProperty
from translator.toscalib.relationship_template import RelationshipTemplate
SECTIONS = (TYPE, PROPERTIES, REQUIREMENTS, INTERFACES, LIFECYCLE, INPUT) = \

View File

@ -18,9 +18,9 @@ import sys
from cliff import command
from toscaparser.tosca_template import ToscaTemplate
from translator.hot.tosca_translator import TOSCATranslator
from translator.osc import utils
from translator.toscalib.tosca_template import ToscaTemplate
class TranslateTemplate(command.Command):

View File

@ -11,8 +11,8 @@
# under the License.
import os
from toscaparser.tosca_template import ToscaTemplate
from translator.tests.base import TestCase
from translator.toscalib.tosca_template import ToscaTemplate
class ToscaMongoNodejsTest(TestCase):

View File

@ -11,8 +11,8 @@
# under the License.
import os
from toscaparser.tests.base import TestCase
import translator.common.utils
from translator.toscalib.tests.base import TestCase
class CommonUtilsTest(TestCase):

View File

@ -1,45 +0,0 @@
# 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.
from translator.toscalib.properties import Property
class Capability(object):
'''TOSCA built-in capabilities type.'''
def __init__(self, name, properties, definition):
self.name = name
self._properties = properties
self.definition = definition
def get_properties_objects(self):
'''Return a list of property objects.'''
properties = []
props = self._properties
if props:
for name, value in props.items():
props_def = self.definition.get_properties_def()
if props_def and name in props_def:
properties.append(Property(name, value,
props_def[name].schema))
return properties
def get_properties(self):
'''Return a dictionary of property name-object pairs.'''
return {prop.name: prop
for prop in self.get_properties_objects()}
def get_property_value(self, name):
'''Return the value of a given property name.'''
props = self.get_properties()
if props and name in props:
return props[name].value

View File

@ -1,100 +0,0 @@
# 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.
'''
TOSCA exception classes
'''
import logging
import sys
from translator.toscalib.utils.gettextutils import _
log = logging.getLogger(__name__)
class TOSCAException(Exception):
'''Base exception class for TOSCA
To correctly use this class, inherit from it and define
a 'msg_fmt' property.
'''
_FATAL_EXCEPTION_FORMAT_ERRORS = False
message = _('An unknown exception occurred.')
def __init__(self, **kwargs):
try:
self.message = self.msg_fmt % kwargs
except KeyError:
exc_info = sys.exc_info()
log.exception(_('Exception in string format operation: %s')
% exc_info[1])
if TOSCAException._FATAL_EXCEPTION_FORMAT_ERRORS:
raise exc_info[0]
def __str__(self):
return self.message
@staticmethod
def set_fatal_format_exception(flag):
if isinstance(flag, bool):
TOSCAException._FATAL_EXCEPTION_FORMAT_ERRORS = flag
class MissingRequiredFieldError(TOSCAException):
msg_fmt = _('%(what)s is missing required field: "%(required)s".')
class UnknownFieldError(TOSCAException):
msg_fmt = _('%(what)s contain(s) unknown field: "%(field)s", '
'refer to the definition to verify valid values.')
class TypeMismatchError(TOSCAException):
msg_fmt = _('%(what)s must be of type: "%(type)s".')
class InvalidNodeTypeError(TOSCAException):
msg_fmt = _('Node type "%(what)s" is not a valid type.')
class InvalidTypeError(TOSCAException):
msg_fmt = _('Type "%(what)s" is not a valid type.')
class InvalidSchemaError(TOSCAException):
msg_fmt = _("%(message)s")
class ValidationError(TOSCAException):
msg_fmt = _("%(message)s")
class UnknownInputError(TOSCAException):
msg_fmt = _('Unknown input: %(input_name)s')
class InvalidPropertyValueError(TOSCAException):
msg_fmt = _('Value of property "%(what)s" is invalid.')
class InvalidTemplateVersion(TOSCAException):
msg_fmt = _('The template version "%(what)s" is invalid. '
'The valid versions are: "%(valid_versions)s"')
class InvalidTOSCAVersionPropertyException(TOSCAException):
msg_fmt = _('Value of TOSCA version property "%(what)s" is invalid.')

View File

@ -1,159 +0,0 @@
# 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.
from translator.toscalib.common.exception import MissingRequiredFieldError
from translator.toscalib.common.exception import TypeMismatchError
from translator.toscalib.common.exception import UnknownFieldError
from translator.toscalib.elements.constraints import Schema
from translator.toscalib.elements.datatype import DataType
from translator.toscalib.elements.scalarunit import ScalarUnit_Frequency
from translator.toscalib.elements.scalarunit import ScalarUnit_Size
from translator.toscalib.elements.scalarunit import ScalarUnit_Time
from translator.toscalib.utils.gettextutils import _
from translator.toscalib.utils import validateutils
class DataEntity(object):
'''A complex data value entity.'''
def __init__(self, datatypename, value_dict, custom_def=None):
self.custom_def = custom_def
self.datatype = DataType(datatypename, custom_def)
self.schema = self.datatype.get_all_properties()
self.value = value_dict
def validate(self):
'''Validate the value by the definition of the datatype.'''
# A datatype can not have both 'type' and 'properties' definitions.
# If the datatype has 'type' definition
if self.datatype.value_type:
self.value = DataEntity.validate_datatype(self.datatype.value_type,
self.value,
None,
self.custom_def)
schema = Schema(None, self.datatype.defs)
for constraint in schema.constraints:
constraint.validate(self.value)
# If the datatype has 'properties' definition
else:
if not isinstance(self.value, dict):
raise TypeMismatchError(what=self.value,
type=self.datatype.type)
allowed_props = []
required_props = []
default_props = {}
if self.schema:
allowed_props = self.schema.keys()
for name, prop_def in self.schema.items():
if prop_def.required:
required_props.append(name)
if prop_def.default:
default_props[name] = prop_def.default
# check allowed field
for value_key in list(self.value.keys()):
if value_key not in allowed_props:
raise UnknownFieldError(what=_('Data value of type %s')
% self.datatype.type,
field=value_key)
# check default field
for def_key, def_value in list(default_props.items()):
if def_key not in list(self.value.keys()):
self.value[def_key] = def_value
# check missing field
missingprop = []
for req_key in required_props:
if req_key not in list(self.value.keys()):
missingprop.append(req_key)
if missingprop:
raise MissingRequiredFieldError(what=_('Data value of type %s')
% self.datatype.type,
required=missingprop)
# check every field
for name, value in list(self.value.items()):
prop_schema = Schema(name, self._find_schema(name))
# check if field value meets type defined
DataEntity.validate_datatype(prop_schema.type, value,
prop_schema.entry_schema,
self.custom_def)
# check if field value meets constraints defined
if prop_schema.constraints:
for constraint in prop_schema.constraints:
constraint.validate(value)
return self.value
def _find_schema(self, name):
if self.schema and name in self.schema.keys():
return self.schema[name].schema
@staticmethod
def validate_datatype(type, value, entry_schema=None, custom_def=None):
'''Validate value with given type.
If type is list or map, validate its entry by entry_schema(if defined)
If type is a user-defined complex datatype, custom_def is required.
'''
if type == Schema.STRING:
return validateutils.validate_string(value)
elif type == Schema.INTEGER:
return validateutils.validate_integer(value)
elif type == Schema.FLOAT:
return validateutils.validate_float(value)
elif type == Schema.NUMBER:
return validateutils.validate_number(value)
elif type == Schema.BOOLEAN:
return validateutils.validate_boolean(value)
elif type == Schema.TIMESTAMP:
validateutils.validate_timestamp(value)
return value
elif type == Schema.LIST:
validateutils.validate_list(value)
if entry_schema:
DataEntity.validate_entry(value, entry_schema, custom_def)
return value
elif type == Schema.SCALAR_UNIT_SIZE:
return ScalarUnit_Size(value).validate_scalar_unit()
elif type == Schema.SCALAR_UNIT_FREQUENCY:
return ScalarUnit_Frequency(value).validate_scalar_unit()
elif type == Schema.SCALAR_UNIT_TIME:
return ScalarUnit_Time(value).validate_scalar_unit()
elif type == Schema.VERSION:
return validateutils.TOSCAVersionProperty(value).get_version()
elif type == Schema.MAP:
validateutils.validate_map(value)
if entry_schema:
DataEntity.validate_entry(value, entry_schema, custom_def)
return value
else:
data = DataEntity(type, value, custom_def)
return data.validate()
@staticmethod
def validate_entry(value, entry_schema, custom_def=None):
'''Validate entries for map and list.'''
schema = Schema(None, entry_schema)
valuelist = value
if isinstance(value, dict):
valuelist = list(value.values())
for v in valuelist:
DataEntity.validate_datatype(schema.type, v, schema.entry_schema,
custom_def)
if schema.constraints:
for constraint in schema.constraints:
constraint.validate(v)
return value

View File

@ -1,720 +0,0 @@
# 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.
##########################################################################
# The content of this file reflects TOSCA Simple Profile in YAML version
# 1.0.0. It describes the definition for TOSCA types including Node Type,
# Relationship Type, Capability Type and Interfaces.
##########################################################################
tosca_definitions_version: tosca_simple_yaml_1_0
##########################################################################
# Node Type.
# A Node Type is a reusable entity that defines the type of one or more
# Node Templates.
##########################################################################
tosca.nodes.Root:
description: >
The TOSCA root node all other TOSCA base node types derive from.
attributes:
tosca_id:
type: string
tosca_name:
type: string
state:
type: string
capabilities:
feature:
type: tosca.capabilities.Node
requirements:
- dependency:
capability: tosca.capabilities.Node
node: tosca.nodes.Root
relationship: tosca.relationships.DependsOn
occurrences: [ 0, UNBOUNDED ]
interfaces:
Standard:
type: tosca.interfaces.node.lifecycle.Standard
tosca.nodes.Compute:
derived_from: tosca.nodes.Root
attributes:
private_address:
type: string
public_address:
type: string
capabilities:
host:
type: tosca.capabilities.Container
binding:
type: tosca.capabilities.network.Bindable
os:
type: tosca.capabilities.OperatingSystem
scalable:
type: tosca.capabilities.Scalable
requirements:
- local_storage:
capability: tosca.capabilities.Attachment
node: tosca.nodes.BlockStorage
relationship: tosca.relationships.AttachesTo
occurrences: [0, UNBOUNDED]
tosca.nodes.SoftwareComponent:
derived_from: tosca.nodes.Root
properties:
# domain-specific software component version
component_version:
type: version
required: false
description: >
Software component version.
admin_credential:
type: tosca.datatypes.Credential
required: false
requirements:
- host:
capability: tosca.capabilities.Container
node: tosca.nodes.Compute
relationship: tosca.relationships.HostedOn
tosca.nodes.DBMS:
derived_from: tosca.nodes.SoftwareComponent
properties:
port:
required: no
type: integer
description: >
The port the DBMS service will listen to for data and requests.
root_password:
required: no
type: string
description: >
The root password for the DBMS service.
capabilities:
host:
type: tosca.capabilities.Container
valid_source_types: [tosca.nodes.Database]
tosca.nodes.Database:
derived_from: tosca.nodes.Root
properties:
user:
required: no
type: string
description: >
User account name for DB administration
name:
required: no
type: string
description: >
The name of the database.
password:
required: no
type: string
description: >
The password for the DB user account
requirements:
- host:
capability: tosca.capabilities.Container
node: tosca.nodes.DBMS
relationship: tosca.relationships.HostedOn
capabilities:
database_endpoint:
type: tosca.capabilities.Endpoint.Database
tosca.nodes.WebServer:
derived_from: tosca.nodes.SoftwareComponent
capabilities:
data_endpoint:
type: tosca.capabilities.Endpoint
admin_endpoint:
type: tosca.capabilities.Endpoint.Admin
host:
type: tosca.capabilities.Container
valid_source_types: [tosca.nodes.WebApplication]
tosca.nodes.WebApplication:
derived_from: tosca.nodes.Root
properties:
context_root:
type: string
required: false
requirements:
- host:
capability: tosca.capabilities.Container
node: tosca.nodes.WebServer
relationship: tosca.relationships.HostedOn
capabilities:
app_endpoint:
type: tosca.capabilities.Endpoint
tosca.nodes.BlockStorage:
derived_from: tosca.nodes.Root
properties:
size:
type: scalar-unit.size
constraints:
- greater_or_equal: 1 MB
volume_id:
type: string
required: false
snapshot_id:
type: string
required: false
attributes:
volume_id:
type: string
capabilities:
attachment:
type: tosca.capabilities.Attachment
tosca.nodes.network.Network:
derived_from: tosca.nodes.Root
description: >
The TOSCA Network node represents a simple, logical network service.
properties:
ip_version:
type: integer
required: no
default: 4
constraints:
- valid_values: [ 4, 6 ]
description: >
The IP version of the requested network. Valid values are 4 for ipv4
or 6 for ipv6.
cidr:
type: string
required: no
description: >
The cidr block of the requested network.
start_ip:
type: string
required: no
description: >
The IP address to be used as the start of a pool of addresses within
the full IP range derived from the cidr block.
end_ip:
type: string
required: no
description: >
The IP address to be used as the end of a pool of addresses within
the full IP range derived from the cidr block.
gateway_ip:
type: string
required: no
description: >
The gateway IP address.
network_name:
type: string
required: no
description: >
An identifier that represents an existing Network instance in the
underlying cloud infrastructure or can be used as the name of the
newly created network. If network_name is provided and no other
properties are provided (with exception of network_id), then an
existing network instance will be used. If network_name is provided
alongside with more properties then a new network with this name will
be created.
network_id:
type: string
required: no
description: >
An identifier that represents an existing Network instance in the
underlying cloud infrastructure. This property is mutually exclusive
with all other properties except network_name. This can be used alone
or together with network_name to identify an existing network.
segmentation_id:
type: string
required: no
description: >
A segmentation identifier in the underlying cloud infrastructure.
E.g. VLAN ID, GRE tunnel ID, etc..
dhcp_enabled:
type: boolean
required: no
default: true
description: >
Indicates should DHCP service be enabled on the network or not.
capabilities:
link:
type: tosca.capabilities.network.Linkable
tosca.nodes.network.Port:
derived_from: tosca.nodes.Root
description: >
The TOSCA Port node represents a logical entity that associates between
Compute and Network normative types. The Port node type effectively
represents a single virtual NIC on the Compute node instance.
properties:
ip_address:
type: string
required: no
description: >
Allow the user to set a static IP.
order:
type: integer
required: no
default: 0
constraints:
- greater_or_equal: 0
description: >
The order of the NIC on the compute instance (e.g. eth2).
is_default:
type: boolean
required: no
default: false
description: >
If is_default=true this port will be used for the default gateway
route. Only one port that is associated to single compute node can
set as is_default=true.
ip_range_start:
type: string
required: no
description: >
Defines the starting IP of a range to be allocated for the compute
instances that are associated with this Port.
ip_range_end:
type: string
required: no
description: >
Defines the ending IP of a range to be allocated for the compute
instances that are associated with this Port.
attributes:
ip_address:
type: string
requirements:
- binding:
description: >
Binding requirement expresses the relationship between Port and
Compute nodes. Effectevely it indicates that the Port will be
attached to specific Compute node instance
capability: tosca.capabilities.network.Bindable
relationship: tosca.relationships.network.BindsTo
- link:
description: >
Link requirement expresses the relationship between Port and Network
nodes. It indicates which network this port will connect to.
capability: tosca.capabilities.network.Linkable
relationship: tosca.relationships.network.LinksTo
tosca.nodes.ObjectStorage:
derived_from: tosca.nodes.Root
description: >
The TOSCA ObjectStorage node represents storage that provides the ability
to store data as objects (or BLOBs of data) without consideration for the
underlying filesystem or devices
properties:
name:
type: string
required: yes
description: >
The logical name of the object store (or container).
size:
type: scalar-unit.size
required: no
constraints:
- greater_or_equal: 0 GB
description: >
The requested initial storage size.
maxsize:
type: scalar-unit.size
required: no
constraints:
- greater_or_equal: 0 GB
description: >
The requested maximum storage size.
capabilities:
storage_endpoint:
type: tosca.capabilities.Endpoint
##########################################################################
# Relationship Type.
# A Relationship Type is a reusable entity that defines the type of one
# or more relationships between Node Types or Node Templates.
##########################################################################
tosca.relationships.Root:
description: >
The TOSCA root Relationship Type all other TOSCA base Relationship Types
derive from.
attributes:
tosca_id:
type: string
tosca_name:
type: string
interfaces:
Configure:
type: tosca.interfaces.relationship.Configure
tosca.relationships.DependsOn:
derived_from: tosca.relationships.Root
tosca.relationships.HostedOn:
derived_from: tosca.relationships.Root
valid_target_types: [ tosca.capabilities.Container ]
tosca.relationships.ConnectsTo:
derived_from: tosca.relationships.Root
valid_target_types: [ tosca.capabilities.Endpoint ]
credential:
type: tosca.datatypes.Credential
required: false
tosca.relationships.AttachesTo:
derived_from: tosca.relationships.Root
valid_target_types: [ tosca.capabilities.Attachment ]
properties:
location:
required: true
type: string
constraints:
- min_length: 1
device:
required: false
type: string
tosca.relationships.network.LinksTo:
derived_from: tosca.relationships.DependsOn
valid_target_types: [ tosca.capabilities.network.Linkable ]
tosca.relationships.network.BindsTo:
derived_from: tosca.relationships.DependsOn
valid_target_types: [ tosca.capabilities.network.Bindable ]
##########################################################################
# Capability Type.
# A Capability Type is a reusable entity that describes a kind of
# capability that a Node Type can declare to expose.
##########################################################################
tosca.capabilities.Root:
description: >
The TOSCA root Capability Type all other TOSCA base Capability Types
derive from.
tosca.capabilities.Node:
derived_from: tosca.capabilities.Root
tosca.capabilities.Container:
derived_from: tosca.capabilities.Root
properties:
num_cpus:
required: no
type: integer
constraints:
- greater_or_equal: 1
cpu_frequency:
required: no
type: scalar-unit.frequency
constraints:
- greater_or_equal: 0.1 GHz
disk_size:
required: no
type: scalar-unit.size
constraints:
- greater_or_equal: 0 MB
mem_size:
required: no
type: scalar-unit.size
constraints:
- greater_or_equal: 0 MB
tosca.capabilities.Endpoint:
derived_from: tosca.capabilities.Root
properties:
protocol:
type: string
default: tcp
port:
type: tosca.datatypes.network.PortDef
required: false
secure:
type: boolean
default: false
url_path:
type: string
required: false
port_name:
type: string
required: false
network_name:
type: string
required: false
initiator:
type: string
default: source
constraints:
- valid_values: [source, target, peer]
ports:
type: map
required: false
constraints:
- min_length: 1
entry_schema:
type: tosca.datatypes.network.PortDef
attributes:
public_address:
type: string
private_address:
type: string
tosca.capabilities.Endpoint.Admin:
derived_from: tosca.capabilities.Endpoint
properties:
secure: true
tosca.capabilities.Scalable:
derived_from: tosca.capabilities.Root
properties:
min_instances:
type: integer
required: yes
default: 1
description: >
This property is used to indicate the minimum number of instances
that should be created for the associated TOSCA Node Template by
a TOSCA orchestrator.
max_instances:
type: integer
required: yes
default: 1
description: >
This property is used to indicate the maximum number of instances
that should be created for the associated TOSCA Node Template by
a TOSCA orchestrator.
default_instances:
type: integer
required: no
description: >
An optional property that indicates the requested default number
of instances that should be the starting number of instances a
TOSCA orchestrator should attempt to allocate.
The value for this property MUST be in the range between the values
set for min_instances and max_instances properties.
tosca.capabilities.Endpoint.Database:
derived_from: tosca.capabilities.Endpoint
tosca.capabilities.Attachment:
derived_from: tosca.capabilities.Root
tosca.capabilities.network.Linkable:
derived_from: tosca.capabilities.Root
description: >
A node type that includes the Linkable capability indicates that it can
be pointed by tosca.relationships.network.LinksTo relationship type, which
represents an association relationship between Port and Network node types.
tosca.capabilities.network.Bindable:
derived_from: tosca.capabilities.Root
description: >
A node type that includes the Bindable capability indicates that it can
be pointed by tosca.relationships.network.BindsTo relationship type, which
represents a network association relationship between Port and Compute node
types.
tosca.capabilities.OperatingSystem:
derived_from: tosca.capabilities.Root
properties:
architecture:
required: false
type: string
description: >
The host Operating System (OS) architecture.
type:
required: false
type: string
description: >
The host Operating System (OS) type.
distribution:
required: false
type: string
description: >
The host Operating System (OS) distribution. Examples of valid values
for an “type” of “Linux” would include:
debian, fedora, rhel and ubuntu.
version:
required: false
type: version
description: >
The host Operating System version.
##########################################################################
# Interfaces Type.
# The Interfaces element describes a list of one or more interface
# definitions for a modelable entity (e.g., a Node or Relationship Type)
# as defined within the TOSCA Simple Profile specification.
##########################################################################
tosca.interfaces.node.lifecycle.Standard:
create:
description: Standard lifecycle create operation.
configure:
description: Standard lifecycle configure operation.
start:
description: Standard lifecycle start operation.
stop:
description: Standard lifecycle stop operation.
delete:
description: Standard lifecycle delete operation.
tosca.interfaces.relationship.Configure:
pre_configure_source:
description: Operation to pre-configure the source endpoint.
pre_configure_target:
description: Operation to pre-configure the target endpoint.
post_configure_source:
description: Operation to post-configure the source endpoint.
post_configure_target:
description: Operation to post-configure the target endpoint.
add_target:
description: Operation to add a target node.
remove_target:
description: Operation to remove a target node.
add_source: >
description: Operation to notify the target node of a source node which
is now available via a relationship.
description:
target_changed: >
description: Operation to notify source some property or attribute of the
target changed
##########################################################################
# Data Type.
# A Datatype is a complex data type declaration which contains other
# complex or simple data types.
##########################################################################
tosca.datatypes.network.NetworkInfo:
properties:
network_name:
type: string
network_id:
type: string
addresses:
type: list
entry_schema:
type: string
tosca.datatypes.network.PortInfo:
properties:
port_name:
type: string
port_id:
type: string
network_id:
type: string
mac_address:
type: string
addresses:
type: list
entry_schema:
type: string
tosca.datatypes.network.PortDef:
type: integer
constraints:
- in_range: [ 1, 65535 ]
tosca.datatypes.network.PortSpec:
properties:
protocol:
type: string
required: true
default: tcp
constraints:
- valid_values: [ udp, tcp, igmp ]
target:
type: list
entry_schema:
type: PortDef
target_range:
type: range
constraints:
- in_range: [ 1, 65535 ]
source:
type: list
entry_schema:
type: PortDef
source_range:
type: range
constraints:
- in_range: [ 1, 65535 ]
tosca.datatypes.Credential:
properties:
protocol:
type: string
token_type:
type: string
token:
type: string
keys:
type: map
entry_schema:
type: string
user:
type: string
required: false
##########################################################################
# Artifact Type.
# An Artifact Type is a reusable entity that defines the type of one or more
# files which Node Types or Node Templates can have dependent relationships
# and used during operations such as during installation or deployment.
##########################################################################
tosca.artifacts.Root:
description: >
The TOSCA Artifact Type all other TOSCA Artifact Types derive from
properties:
version: version
tosca.artifacts.File:
derived_from: tosca.artifacts.Root
tosca.artifacts.Deployment:
derived_from: tosca.artifacts.Root
description: TOSCA base type for deployment artifacts
tosca.artifacts.Deployment.Image:
derived_from: tosca.artifacts.Deployment
tosca.artifacts.Deployment.Image.VM:
derived_from: tosca.artifacts.Deployment.Image
tosca.artifacts.Implementation:
derived_from: tosca.artifacts.Root
description: TOSCA base type for implementation artifacts
tosca.artifacts.Implementation.Bash:
derived_from: tosca.artifacts.Implementation
description: Script artifact for the Unix Bash shell
mime_type: application/x-sh
file_ext: [ sh ]
tosca.artifacts.Implementation.Python:
derived_from: tosca.artifacts.Implementation
description: Artifact for the interpreted Python language
mime_type: application/x-python
file_ext: [ py ]
tosca.artifacts.Deployment.Image.Container.Docker:
derived_from: tosca.artifacts.Deployment.Image
description: Docker container image
tosca.artifacts.Deployment.Image.VM.ISO:
derived_from: tosca.artifacts.Deployment.Image
description: Virtual Machine (VM) image in ISO disk format
mime_type: application/octet-stream
file_ext: [ iso ]
tosca.artifacts.Deployment.Image.VM.QCOW2:
derived_from: tosca.artifacts.Deployment.Image
description: Virtual Machine (VM) image in QCOW v2 standard disk format
mime_type: application/octet-stream
file_ext: [ qcow2 ]

View File

@ -1,45 +0,0 @@
# 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.
from translator.toscalib.elements.statefulentitytype import StatefulEntityType
class ArtifactTypeDef(StatefulEntityType):
'''TOSCA built-in artifacts type.'''
def __init__(self, atype, custom_def=None):
super(ArtifactTypeDef, self).__init__(atype, self.ARTIFACT_PREFIX,
custom_def)
self.type = atype
self.properties = None
if self.PROPERTIES in self.defs:
self.properties = self.defs[self.PROPERTIES]
self.parent_artifacts = self._get_parent_artifacts()
def _get_parent_artifacts(self):
artifacts = {}
parent_artif = self.parent_type
if parent_artif:
while parent_artif != 'tosca.artifacts.Root':
artifacts[parent_artif] = self.TOSCA_DEF[parent_artif]
parent_artif = artifacts[parent_artif]['derived_from']
return artifacts
@property
def parent_type(self):
'''Return an artifact this artifact is derived from.'''
return self.derived_from(self.defs)
def get_artifact(self, name):
'''Return the definition of an artifact field by name.'''
if name in self.defs:
return self.defs[name]

View File

@ -1,20 +0,0 @@
# 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.
class AttributeDef(object):
'''TOSCA built-in Attribute type.'''
def __init__(self, name, value=None, schema=None):
self.name = name
self.value = value
self.schema = schema

View File

@ -1,69 +0,0 @@
# 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.
from translator.toscalib.elements.property_definition import PropertyDef
from translator.toscalib.elements.statefulentitytype import StatefulEntityType
class CapabilityTypeDef(StatefulEntityType):
'''TOSCA built-in capabilities type.'''
def __init__(self, name, ctype, ntype, custom_def=None):
self.name = name
super(CapabilityTypeDef, self).__init__(ctype, self.CAPABILITY_PREFIX,
custom_def)
self.nodetype = ntype
self.properties = None
if self.PROPERTIES in self.defs:
self.properties = self.defs[self.PROPERTIES]
self.parent_capabilities = self._get_parent_capabilities()
def get_properties_def_objects(self):
'''Return a list of property definition objects.'''
properties = []
parent_properties = {}
if self.parent_capabilities:
for type, value in self.parent_capabilities.items():
parent_properties[type] = value.get('properties')
if self.properties:
for prop, schema in self.properties.items():
properties.append(PropertyDef(prop, None, schema))
if parent_properties:
for parent, props in parent_properties.items():
for prop, schema in props.items():
properties.append(PropertyDef(prop, None, schema))
return properties
def get_properties_def(self):
'''Return a dictionary of property definition name-object pairs.'''
return {prop.name: prop
for prop in self.get_properties_def_objects()}
def get_property_def_value(self, name):
'''Return the definition of a given property name.'''
props_def = self.get_properties_def()
if props_def and name in props_def:
return props_def[name].value
def _get_parent_capabilities(self):
capabilities = {}
parent_cap = self.parent_type
if parent_cap:
while parent_cap != 'tosca.capabilities.Root':
capabilities[parent_cap] = self.TOSCA_DEF[parent_cap]
parent_cap = capabilities[parent_cap]['derived_from']
return capabilities
@property
def parent_type(self):
'''Return a capability this capability is derived from.'''
return self.derived_from(self.defs)

View File

@ -1,569 +0,0 @@
# 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 collections
import datetime
import re
from translator.toscalib.common.exception import InvalidSchemaError
from translator.toscalib.common.exception import ValidationError
from translator.toscalib.elements import scalarunit
from translator.toscalib.functions import is_function
from translator.toscalib.utils.gettextutils import _
class Schema(collections.Mapping):
KEYS = (
TYPE, REQUIRED, DESCRIPTION,
DEFAULT, CONSTRAINTS, ENTRYSCHEMA
) = (
'type', 'required', 'description',
'default', 'constraints', 'entry_schema'
)
PROPERTY_TYPES = (
INTEGER, STRING, BOOLEAN, FLOAT,
NUMBER, TIMESTAMP, LIST, MAP,
SCALAR_UNIT_SIZE, SCALAR_UNIT_FREQUENCY, SCALAR_UNIT_TIME,
PORTDEF, VERSION
) = (
'integer', 'string', 'boolean', 'float',
'number', 'timestamp', 'list', 'map',
'scalar-unit.size', 'scalar-unit.frequency', 'scalar-unit.time',
'PortDef', 'version'
)
SCALAR_UNIT_SIZE_DEFAULT = 'B'
SCALAR_UNIT_SIZE_DICT = {'B': 1, 'KB': 1000, 'KIB': 1024, 'MB': 1000000,
'MIB': 1048576, 'GB': 1000000000,
'GIB': 1073741824, 'TB': 1000000000000,
'TIB': 1099511627776}
def __init__(self, name, schema_dict):
self.name = name
if not isinstance(schema_dict, collections.Mapping):
msg = _("Schema %(pname)s must be a dict.") % dict(pname=name)
raise InvalidSchemaError(message=msg)
try:
schema_dict['type']
except KeyError:
msg = _("Schema %(pname)s must have type.") % dict(pname=name)
raise InvalidSchemaError(message=msg)
self.schema = schema_dict
self._len = None
self.constraints_list = []
@property
def type(self):
return self.schema[self.TYPE]
@property
def required(self):
return self.schema.get(self.REQUIRED, True)
@property
def description(self):
return self.schema.get(self.DESCRIPTION, '')
@property
def default(self):
return self.schema.get(self.DEFAULT)
@property
def constraints(self):
if not self.constraints_list:
constraint_schemata = self.schema.get(self.CONSTRAINTS)
if constraint_schemata:
self.constraints_list = [Constraint(self.name,
self.type,
cschema)
for cschema in constraint_schemata]
return self.constraints_list
@property
def entry_schema(self):
return self.schema.get(self.ENTRYSCHEMA)
def __getitem__(self, key):
return self.schema[key]
def __iter__(self):
for k in self.KEYS:
try:
self.schema[k]
except KeyError:
pass
else:
yield k
def __len__(self):
if self._len is None:
self._len = len(list(iter(self)))
return self._len
class Constraint(object):
'''Parent class for constraints for a Property or Input.'''
CONSTRAINTS = (EQUAL, GREATER_THAN,
GREATER_OR_EQUAL, LESS_THAN, LESS_OR_EQUAL, IN_RANGE,
VALID_VALUES, LENGTH, MIN_LENGTH, MAX_LENGTH, PATTERN) = \
('equal', 'greater_than', 'greater_or_equal', 'less_than',
'less_or_equal', 'in_range', 'valid_values', 'length',
'min_length', 'max_length', 'pattern')
def __new__(cls, property_name, property_type, constraint):
if cls is not Constraint:
return super(Constraint, cls).__new__(cls)
if(not isinstance(constraint, collections.Mapping) or
len(constraint) != 1):
raise InvalidSchemaError(message=_('Invalid constraint schema.'))
for type in constraint.keys():
ConstraintClass = get_constraint_class(type)
if not ConstraintClass:
msg = _('Invalid constraint type "%s".') % type
raise InvalidSchemaError(message=msg)
return ConstraintClass(property_name, property_type, constraint)
def __init__(self, property_name, property_type, constraint):
self.property_name = property_name
self.property_type = property_type
self.constraint_value = constraint[self.constraint_key]
self.constraint_value_msg = self.constraint_value
if self.property_type in scalarunit.ScalarUnit.SCALAR_UNIT_TYPES:
self.constraint_value = self._get_scalarunit_constraint_value()
# check if constraint is valid for property type
if property_type not in self.valid_prop_types:
msg = _('Constraint type "%(ctype)s" is not valid '
'for data type "%(dtype)s".') % dict(
ctype=self.constraint_key,
dtype=property_type)
raise InvalidSchemaError(message=msg)
def _get_scalarunit_constraint_value(self):
if self.property_type in scalarunit.ScalarUnit.SCALAR_UNIT_TYPES:
ScalarUnit_Class = (scalarunit.
get_scalarunit_class(self.property_type))
if isinstance(self.constraint_value, list):
return [ScalarUnit_Class(v).get_num_from_scalar_unit()
for v in self.constraint_value]
else:
return (ScalarUnit_Class(self.constraint_value).
get_num_from_scalar_unit())
def _err_msg(self, value):
return _('Property %s could not be validated.') % self.property_name
def validate(self, value):
self.value_msg = value
if self.property_type in scalarunit.ScalarUnit.SCALAR_UNIT_TYPES:
value = scalarunit.get_scalarunit_value(self.property_type, value)
if not self._is_valid(value):
err_msg = self._err_msg(value)
raise ValidationError(message=err_msg)
class Equal(Constraint):
"""Constraint class for "equal"
Constrains a property or parameter to a value equal to ('=')
the value declared.
"""
constraint_key = Constraint.EQUAL
valid_prop_types = Schema.PROPERTY_TYPES
def _is_valid(self, value):
if value == self.constraint_value:
return True
return False
def _err_msg(self, value):
return (_('%(pname)s: %(pvalue)s is not equal to "%(cvalue)s".') %
dict(pname=self.property_name,
pvalue=self.value_msg,
cvalue=self.constraint_value_msg))
class GreaterThan(Constraint):
"""Constraint class for "greater_than"
Constrains a property or parameter to a value greater than ('>')
the value declared.
"""
constraint_key = Constraint.GREATER_THAN
valid_types = (int, float, datetime.date,
datetime.time, datetime.datetime)
valid_prop_types = (Schema.INTEGER, Schema.FLOAT, Schema.TIMESTAMP,
Schema.SCALAR_UNIT_SIZE, Schema.SCALAR_UNIT_FREQUENCY,
Schema.SCALAR_UNIT_TIME)
def __init__(self, property_name, property_type, constraint):
super(GreaterThan, self).__init__(property_name, property_type,
constraint)
if not isinstance(constraint[self.GREATER_THAN], self.valid_types):
raise InvalidSchemaError(message=_('greater_than must '
'be comparable.'))
def _is_valid(self, value):
if value > self.constraint_value:
return True
return False
def _err_msg(self, value):
return (_('%(pname)s: %(pvalue)s must be greater than "%(cvalue)s".') %
dict(pname=self.property_name,
pvalue=self.value_msg,
cvalue=self.constraint_value_msg))
class GreaterOrEqual(Constraint):
"""Constraint class for "greater_or_equal"
Constrains a property or parameter to a value greater than or equal
to ('>=') the value declared.
"""
constraint_key = Constraint.GREATER_OR_EQUAL
valid_types = (int, float, datetime.date,
datetime.time, datetime.datetime)
valid_prop_types = (Schema.INTEGER, Schema.FLOAT, Schema.TIMESTAMP,
Schema.SCALAR_UNIT_SIZE, Schema.SCALAR_UNIT_FREQUENCY,
Schema.SCALAR_UNIT_TIME)
def __init__(self, property_name, property_type, constraint):
super(GreaterOrEqual, self).__init__(property_name, property_type,
constraint)
if not isinstance(self.constraint_value, self.valid_types):
raise InvalidSchemaError(message=_('greater_or_equal must '
'be comparable.'))
def _is_valid(self, value):
if is_function(value) or value >= self.constraint_value:
return True
return False
def _err_msg(self, value):
return (_('%(pname)s: %(pvalue)s must be greater or equal '
'to "%(cvalue)s".') %
dict(pname=self.property_name,
pvalue=self.value_msg,
cvalue=self.constraint_value_msg))
class LessThan(Constraint):
"""Constraint class for "less_than"
Constrains a property or parameter to a value less than ('<')
the value declared.
"""
constraint_key = Constraint.LESS_THAN
valid_types = (int, float, datetime.date,
datetime.time, datetime.datetime)
valid_prop_types = (Schema.INTEGER, Schema.FLOAT, Schema.TIMESTAMP,
Schema.SCALAR_UNIT_SIZE, Schema.SCALAR_UNIT_FREQUENCY,
Schema.SCALAR_UNIT_TIME)
def __init__(self, property_name, property_type, constraint):
super(LessThan, self).__init__(property_name, property_type,
constraint)
if not isinstance(self.constraint_value, self.valid_types):
raise InvalidSchemaError(message=_('less_than must '
'be comparable.'))
def _is_valid(self, value):
if value < self.constraint_value:
return True
return False
def _err_msg(self, value):
return (_('%(pname)s: %(pvalue)s must be less than "%(cvalue)s".') %
dict(pname=self.property_name,
pvalue=self.value_msg,
cvalue=self.constraint_value_msg))
class LessOrEqual(Constraint):
"""Constraint class for "less_or_equal"
Constrains a property or parameter to a value less than or equal
to ('<=') the value declared.
"""
constraint_key = Constraint.LESS_OR_EQUAL
valid_types = (int, float, datetime.date,
datetime.time, datetime.datetime)
valid_prop_types = (Schema.INTEGER, Schema.FLOAT, Schema.TIMESTAMP,
Schema.SCALAR_UNIT_SIZE, Schema.SCALAR_UNIT_FREQUENCY,
Schema.SCALAR_UNIT_TIME)
def __init__(self, property_name, property_type, constraint):
super(LessOrEqual, self).__init__(property_name, property_type,
constraint)
if not isinstance(self.constraint_value, self.valid_types):
raise InvalidSchemaError(message=_('less_or_equal must '
'be comparable.'))
def _is_valid(self, value):
if value <= self.constraint_value:
return True
return False
def _err_msg(self, value):
return (_('%(pname)s: %(pvalue)s must be less or '
'equal to "%(cvalue)s".') %
dict(pname=self.property_name,
pvalue=self.value_msg,
cvalue=self.constraint_value_msg))
class InRange(Constraint):
"""Constraint class for "in_range"
Constrains a property or parameter to a value in range of (inclusive)
the two values declared.
"""
constraint_key = Constraint.IN_RANGE
valid_types = (int, float, datetime.date,
datetime.time, datetime.datetime)
valid_prop_types = (Schema.INTEGER, Schema.FLOAT, Schema.TIMESTAMP,
Schema.SCALAR_UNIT_SIZE, Schema.SCALAR_UNIT_FREQUENCY,
Schema.SCALAR_UNIT_TIME)
def __init__(self, property_name, property_type, constraint):
super(InRange, self).__init__(property_name, property_type, constraint)
if(not isinstance(self.constraint_value, collections.Sequence) or
(len(constraint[self.IN_RANGE]) != 2)):
raise InvalidSchemaError(message=_('in_range must be a list.'))
for value in self.constraint_value:
if not isinstance(value, self.valid_types):
raise InvalidSchemaError(_('in_range value must '
'be comparable.'))
self.min = self.constraint_value[0]
self.max = self.constraint_value[1]
def _is_valid(self, value):
if value < self.min:
return False
if value > self.max:
return False
return True
def _err_msg(self, value):
return (_('%(pname)s: %(pvalue)s is out of range '
'(min:%(vmin)s, max:%(vmax)s).') %
dict(pname=self.property_name,
pvalue=self.value_msg,
vmin=self.constraint_value_msg[0],
vmax=self.constraint_value_msg[1]))
class ValidValues(Constraint):
"""Constraint class for "valid_values"
Constrains a property or parameter to a value that is in the list of
declared values.
"""
constraint_key = Constraint.VALID_VALUES
valid_prop_types = Schema.PROPERTY_TYPES
def __init__(self, property_name, property_type, constraint):
super(ValidValues, self).__init__(property_name, property_type,
constraint)
if not isinstance(self.constraint_value, collections.Sequence):
raise InvalidSchemaError(message=_('valid_values must be a list.'))
def _is_valid(self, value):
if isinstance(value, list):
return all(v in self.constraint_value for v in value)
return value in self.constraint_value
def _err_msg(self, value):
allowed = '[%s]' % ', '.join(str(a) for a in self.constraint_value)
return (_('%(pname)s: %(pvalue)s is not an valid '
'value "%(cvalue)s".') %
dict(pname=self.property_name,
pvalue=value,
cvalue=allowed))
class Length(Constraint):
"""Constraint class for "length"
Constrains the property or parameter to a value of a given length.
"""
constraint_key = Constraint.LENGTH
valid_types = (int, )
valid_prop_types = (Schema.STRING, )
def __init__(self, property_name, property_type, constraint):
super(Length, self).__init__(property_name, property_type, constraint)
if not isinstance(self.constraint_value, self.valid_types):
raise InvalidSchemaError(message=_('length must be integer.'))
def _is_valid(self, value):
if isinstance(value, str) and len(value) == self.constraint_value:
return True
return False
def _err_msg(self, value):
return (_('length of %(pname)s: %(pvalue)s must be equal '
'to "%(cvalue)s".') %
dict(pname=self.property_name,
pvalue=value,
cvalue=self.constraint_value))
class MinLength(Constraint):
"""Constraint class for "min_length"
Constrains the property or parameter to a value to a minimum length.
"""
constraint_key = Constraint.MIN_LENGTH
valid_types = (int, )
valid_prop_types = (Schema.STRING, )
def __init__(self, property_name, property_type, constraint):
super(MinLength, self).__init__(property_name, property_type,
constraint)
if not isinstance(self.constraint_value, self.valid_types):
raise InvalidSchemaError(message=_('min_length must be integer.'))
def _is_valid(self, value):
if isinstance(value, str) and len(value) >= self.constraint_value:
return True
return False
def _err_msg(self, value):
return (_('length of %(pname)s: %(pvalue)s must be '
'at least "%(cvalue)s".') %
dict(pname=self.property_name,
pvalue=value,
cvalue=self.constraint_value))
class MaxLength(Constraint):
"""Constraint class for "max_length"
Constrains the property or parameter to a value to a maximum length.
"""
constraint_key = Constraint.MAX_LENGTH
valid_types = (int, )
valid_prop_types = (Schema.STRING, )
def __init__(self, property_name, property_type, constraint):
super(MaxLength, self).__init__(property_name, property_type,
constraint)
if not isinstance(self.constraint_value, self.valid_types):
raise InvalidSchemaError(message=_('max_length must be integer.'))
def _is_valid(self, value):
if isinstance(value, str) and len(value) <= self.constraint_value:
return True
return False
def _err_msg(self, value):
return (_('length of %(pname)s: %(pvalue)s must be no greater '
'than "%(cvalue)s".') %
dict(pname=self.property_name,
pvalue=value,
cvalue=self.constraint_value))
class Pattern(Constraint):
"""Constraint class for "pattern"
Constrains the property or parameter to a value that is allowed by
the provided regular expression.
"""
constraint_key = Constraint.PATTERN
valid_types = (str, )
valid_prop_types = (Schema.STRING, )
def __init__(self, property_name, property_type, constraint):
super(Pattern, self).__init__(property_name, property_type, constraint)
if not isinstance(self.constraint_value, self.valid_types):
raise InvalidSchemaError(message=_('pattern must be string.'))
self.match = re.compile(self.constraint_value).match
def _is_valid(self, value):
match = self.match(value)
return match is not None and match.end() == len(value)
def _err_msg(self, value):
return (_('%(pname)s: "%(pvalue)s" does not match '
'pattern "%(cvalue)s".') %
dict(pname=self.property_name,
pvalue=value,
cvalue=self.constraint_value))
constraint_mapping = {
Constraint.EQUAL: Equal,
Constraint.GREATER_THAN: GreaterThan,
Constraint.GREATER_OR_EQUAL: GreaterOrEqual,
Constraint.LESS_THAN: LessThan,
Constraint.LESS_OR_EQUAL: LessOrEqual,
Constraint.IN_RANGE: InRange,
Constraint.VALID_VALUES: ValidValues,
Constraint.LENGTH: Length,
Constraint.MIN_LENGTH: MinLength,
Constraint.MAX_LENGTH: MaxLength,
Constraint.PATTERN: Pattern
}
def get_constraint_class(type):
return constraint_mapping.get(type)

View File

@ -1,56 +0,0 @@
# 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.
from translator.toscalib.elements.statefulentitytype import StatefulEntityType
class DataType(StatefulEntityType):
'''TOSCA built-in and user defined complex data type.'''
def __init__(self, datatypename, custom_def=None):
super(DataType, self).__init__(datatypename, self.DATATYPE_PREFIX,
custom_def)
self.custom_def = custom_def
@property
def parent_type(self):
'''Return a datatype this datatype is derived from.'''
ptype = self.derived_from(self.defs)
if ptype:
return DataType(ptype, self.custom_def)
return None
@property
def value_type(self):
'''Return 'type' section in the datatype schema.'''
return self.entity_value(self.defs, 'type')
def get_all_properties_objects(self):
'''Return all properties objects defined in type and parent type.'''
props_def = self.get_properties_def_objects()
ptype = self.parent_type
while ptype:
props_def.extend(ptype.get_properties_def_objects())
ptype = ptype.parent_type
return props_def
def get_all_properties(self):
'''Return a dictionary of all property definition name-object pairs.'''
return {prop.name: prop
for prop in self.get_all_properties_objects()}
def get_all_property_value(self, name):
'''Return the value of a given property name.'''
props_def = self.get_all_properties()
if props_def and name in props_def.key():
return props_def[name].value

View File

@ -1,95 +0,0 @@
# 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
import os
import translator.toscalib.utils.yamlparser
log = logging.getLogger('tosca')
class EntityType(object):
'''Base class for TOSCA elements.'''
SECTIONS = (DERIVED_FROM, PROPERTIES, ATTRIBUTES, REQUIREMENTS,
INTERFACES, CAPABILITIES, TYPE, ARTIFACTS) = \
('derived_from', 'properties', 'attributes', 'requirements',
'interfaces', 'capabilities', 'type', 'artifacts')
'''TOSCA definition file.'''
TOSCA_DEF_FILE = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
"TOSCA_definition_1_0.yaml")
loader = translator.toscalib.utils.yamlparser.load_yaml
TOSCA_DEF = loader(TOSCA_DEF_FILE)
RELATIONSHIP_TYPE = (DEPENDSON, HOSTEDON, CONNECTSTO, ATTACHESTO,
LINKSTO, BINDSTO) = \
('tosca.relationships.DependsOn',
'tosca.relationships.HostedOn',
'tosca.relationships.ConnectsTo',
'tosca.relationships.AttachesTo',
'tosca.relationships.network.LinksTo',
'tosca.relationships.network.BindsTo')
NODE_PREFIX = 'tosca.nodes.'
RELATIONSHIP_PREFIX = 'tosca.relationships.'
CAPABILITY_PREFIX = 'tosca.capabilities.'
INTERFACE_PREFIX = 'tosca.interfaces.'
ARTIFACT_PREFIX = 'tosca.artifacts.'
# currently the data types are defined only for network
# but may have changes in the future.
DATATYPE_PREFIX = 'tosca.datatypes.network.'
TOSCA = 'tosca'
def derived_from(self, defs):
'''Return a type this type is derived from.'''
return self.entity_value(defs, 'derived_from')
def is_derived_from(self, type_str):
'''Check if object inherits from the given type.
Returns true if this object is derived from 'type_str'.
False otherwise.
'''
if not self.type:
return False
elif self.type == type_str:
return True
elif self.parent_type:
return self.parent_type.is_derived_from(type_str)
else:
return False
def entity_value(self, defs, key):
if key in defs:
return defs[key]
def get_value(self, ndtype, defs=None, parent=None):
value = None
if defs is None:
defs = self.defs
if ndtype in defs:
value = defs[ndtype]
if parent and not value:
p = self.parent_type
while value is None:
# check parent node
if not p:
break
if p and p.type == 'tosca.nodes.Root':
break
value = p.get_value(ndtype)
p = p.parent_type
return value

View File

@ -1,74 +0,0 @@
# 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.
from translator.toscalib.common.exception import UnknownFieldError
from translator.toscalib.elements.statefulentitytype import StatefulEntityType
SECTIONS = (LIFECYCLE, CONFIGURE, LIFECYCLE_SHORTNAME,
CONFIGURE_SHORTNAME) = \
('tosca.interfaces.node.lifecycle.Standard',
'tosca.interfaces.relationship.Configure',
'Standard', 'Configure')
INTERFACEVALUE = (IMPLEMENTATION, INPUTS) = ('implementation', 'inputs')
class InterfacesDef(StatefulEntityType):
'''TOSCA built-in interfaces type.'''
def __init__(self, node_type, interfacetype,
node_template=None, name=None, value=None):
self.ntype = node_type
self.node_template = node_template
self.type = interfacetype
self.name = name
self.value = value
self.implementation = None
self.inputs = None
self.defs = {}
if interfacetype == LIFECYCLE_SHORTNAME:
interfacetype = LIFECYCLE
if interfacetype == CONFIGURE_SHORTNAME:
interfacetype = CONFIGURE
if node_type:
self.defs = self.TOSCA_DEF[interfacetype]
if value:
if isinstance(self.value, dict):
for i, j in self.value.items():
if i == IMPLEMENTATION:
self.implementation = j
elif i == INPUTS:
self.inputs = j
else:
what = ('Interfaces of template %s' %
self.node_template.name)
raise UnknownFieldError(what=what, field=i)
else:
self.implementation = value
@property
def lifecycle_ops(self):
if self.defs:
if self.type == LIFECYCLE:
return self._ops()
@property
def configure_ops(self):
if self.defs:
if self.type == CONFIGURE:
return self._ops()
def _ops(self):
ops = []
for name in list(self.defs.keys()):
ops.append(name)
return ops

View File

@ -1,200 +0,0 @@
# 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.
from translator.toscalib.elements.capabilitytype import CapabilityTypeDef
import translator.toscalib.elements.interfaces as ifaces
from translator.toscalib.elements.interfaces import InterfacesDef
from translator.toscalib.elements.relationshiptype import RelationshipType
from translator.toscalib.elements.statefulentitytype import StatefulEntityType
class NodeType(StatefulEntityType):
'''TOSCA built-in node type.'''
def __init__(self, ntype, custom_def=None):
super(NodeType, self).__init__(ntype, self.NODE_PREFIX, custom_def)
self.custom_def = custom_def
@property
def parent_type(self):
'''Return a node this node is derived from.'''
pnode = self.derived_from(self.defs)
if pnode:
return NodeType(pnode)
@property
def relationship(self):
'''Return a dictionary of relationships to other node types.
This method returns a dictionary of named relationships that nodes
of the current node type (self) can have to other nodes (of specific
types) in a TOSCA template.
'''
relationship = {}
requires = self.get_all_requirements()
if requires:
# NOTE(sdmonov): Check if requires is a dict.
# If it is a dict convert it to a list of dicts.
# This is needed because currently the code below supports only
# lists as requirements definition. The following check will
# make sure if a map (dict) was provided it will be converted to
# a list before proceeding to the parsing.
if isinstance(requires, dict):
requires = [{key: value} for key, value in requires.items()]
keyword = None
node_type = None
for require in requires:
for key, req in require.items():
if 'relationship' in req:
relation = req.get('relationship')
if 'type' in relation:
relation = relation.get('type')
node_type = req.get('node')
value = req
if node_type:
keyword = 'node'
else:
# If value is a dict and has a type key
# we need to lookup the node type using
# the capability type
value = req
if isinstance(value, dict):
captype = value['capability']
value = (self.
_get_node_type_by_cap(key, captype))
relation = self._get_relation(key, value)
keyword = key
node_type = value
rtype = RelationshipType(relation, keyword, req)
relatednode = NodeType(node_type, self.custom_def)
relationship[rtype] = relatednode
return relationship
def _get_node_type_by_cap(self, key, cap):
'''Find the node type that has the provided capability
This method will lookup all node types if they have the
provided capability.
'''
# Filter the node types
node_types = [node_type for node_type in self.TOSCA_DEF.keys()
if node_type.startswith(self.NODE_PREFIX) and
node_type != 'tosca.nodes.Root']
for node_type in node_types:
node_def = self.TOSCA_DEF[node_type]
if isinstance(node_def, dict) and 'capabilities' in node_def:
node_caps = node_def['capabilities']
for value in node_caps.values():
if isinstance(value, dict) and \
'type' in value and value['type'] == cap:
return node_type
def _get_relation(self, key, ndtype):
relation = None
ntype = NodeType(ndtype)
caps = ntype.get_capabilities()
if caps and key in caps.keys():
c = caps[key]
for r in self.RELATIONSHIP_TYPE:
rtypedef = ntype.TOSCA_DEF[r]
for properties in rtypedef.values():
if c.type in properties:
relation = r
break
if relation:
break
else:
for properties in rtypedef.values():
if c.parent_type in properties:
relation = r
break
return relation
def get_capabilities_objects(self):
'''Return a list of capability objects.'''
typecapabilities = []
caps = self.get_value(self.CAPABILITIES)
if caps is None:
caps = self.get_value(self.CAPABILITIES, None, True)
if caps:
for name, value in caps.items():
ctype = value.get('type')
cap = CapabilityTypeDef(name, ctype, self.type,
self.custom_def)
typecapabilities.append(cap)
return typecapabilities
def get_capabilities(self):
'''Return a dictionary of capability name-objects pairs.'''
return {cap.name: cap
for cap in self.get_capabilities_objects()}
@property
def requirements(self):
return self.get_value(self.REQUIREMENTS)
def get_all_requirements(self):
requires = self.requirements
parent_node = self.parent_type
if requires is None:
requires = self.get_value(self.REQUIREMENTS, None, True)
parent_node = parent_node.parent_type
if parent_node:
while parent_node.type != 'tosca.nodes.Root':
req = parent_node.get_value(self.REQUIREMENTS, None, True)
for r in req:
if r not in requires:
requires.append(r)
parent_node = parent_node.parent_type
return requires
@property
def interfaces(self):
return self.get_value(self.INTERFACES)
@property
def lifecycle_inputs(self):
'''Return inputs to life cycle operations if found.'''
inputs = []
interfaces = self.interfaces
if interfaces:
for name, value in interfaces.items():
if name == ifaces.LIFECYCLE:
for x, y in value.items():
if x == 'inputs':
for i in y.iterkeys():
inputs.append(i)
return inputs
@property
def lifecycle_operations(self):
'''Return available life cycle operations if found.'''
ops = None
interfaces = self.interfaces
if interfaces:
i = InterfacesDef(self.type, ifaces.LIFECYCLE)
ops = i.lifecycle_ops
return ops
def get_capability(self, name):
caps = self.get_capabilities()
if caps and name in caps.keys():
return caps[name].value
def get_capability_type(self, name):
captype = self.get_capability(name)
if captype and name in captype.keys():
return captype[name].value

View File

@ -1,45 +0,0 @@
# 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.
from translator.toscalib.common.exception import InvalidSchemaError
class PropertyDef(object):
'''TOSCA built-in Property type.'''
def __init__(self, name, value=None, schema=None):
self.name = name
self.value = value
self.schema = schema
try:
self.schema['type']
except KeyError:
msg = (_("Property definition of %(pname)s must have type.") %
dict(pname=self.name))
raise InvalidSchemaError(message=msg)
@property
def required(self):
if self.schema:
for prop_key, prop_value in self.schema.items():
if prop_key == 'required' and prop_value:
return True
return False
@property
def default(self):
if self.schema:
for prop_key, prop_value in self.schema.items():
if prop_key == 'default':
return prop_value
return None

View File

@ -1,33 +0,0 @@
# 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.
from translator.toscalib.elements.statefulentitytype import StatefulEntityType
class RelationshipType(StatefulEntityType):
'''TOSCA built-in relationship type.'''
def __init__(self, type, capability_name=None, custom_def=None):
super(RelationshipType, self).__init__(type, self.RELATIONSHIP_PREFIX,
custom_def)
self.capability_name = capability_name
self.custom_def = custom_def
@property
def parent_type(self):
'''Return a relationship this reletionship is derived from.'''
prel = self.derived_from(self.defs)
if prel:
return RelationshipType(prel)
@property
def valid_target_types(self):
return self.entity_value(self.defs, 'valid_target_types')

View File

@ -1,124 +0,0 @@
# 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
import re
from translator.toscalib.utils.gettextutils import _
from translator.toscalib.utils import validateutils
log = logging.getLogger('tosca')
class ScalarUnit(object):
'''Parent class for scalar-unit type.'''
SCALAR_UNIT_TYPES = (
SCALAR_UNIT_SIZE, SCALAR_UNIT_FREQUENCY, SCALAR_UNIT_TIME
) = (
'scalar-unit.size', 'scalar-unit.frequency', 'scalar-unit.time'
)
def __init__(self, value):
self.value = value
def _check_unit_in_scalar_standard_units(self, input_unit):
"""Check whether the input unit is following specified standard
If unit is not following specified standard, convert it to standard
unit after displaying a warning message.
"""
if input_unit in self.SCALAR_UNIT_DICT.keys():
return input_unit
else:
for key in self.SCALAR_UNIT_DICT.keys():
if key.upper() == input_unit.upper():
log.warning(_('Given unit %(unit)s does not follow scalar '
'unit standards; using %(key)s instead.') % {
'unit': input_unit, 'key': key})
return key
msg = (_('Provided unit "%(unit)s" is not valid. The valid units'
' are %(valid_units)s') % {'unit': input_unit,
'valid_units': sorted(self.SCALAR_UNIT_DICT.keys())})
raise ValueError(msg)
def validate_scalar_unit(self):
regex = re.compile('([0-9.]+)\s*(\w+)')
try:
result = regex.match(str(self.value)).groups()
validateutils.str_to_num(result[0])
scalar_unit = self._check_unit_in_scalar_standard_units(result[1])
self.value = ' '.join([result[0], scalar_unit])
return self.value
except Exception:
raise ValueError(_('"%s" is not a valid scalar-unit')
% self.value)
def get_num_from_scalar_unit(self, unit=None):
if unit:
unit = self._check_unit_in_scalar_standard_units(unit)
else:
unit = self.SCALAR_UNIT_DEFAULT
self.validate_scalar_unit()
regex = re.compile('([0-9.]+)\s*(\w+)')
result = regex.match(str(self.value)).groups()
converted = (float(validateutils.str_to_num(result[0]))
* self.SCALAR_UNIT_DICT[result[1]]
/ self.SCALAR_UNIT_DICT[unit])
if converted - int(converted) < 0.0000000000001:
converted = int(converted)
return converted
class ScalarUnit_Size(ScalarUnit):
SCALAR_UNIT_DEFAULT = 'B'
SCALAR_UNIT_DICT = {'B': 1, 'kB': 1000, 'KiB': 1024, 'MB': 1000000,
'MiB': 1048576, 'GB': 1000000000,
'GiB': 1073741824, 'TB': 1000000000000,
'TiB': 1099511627776}
class ScalarUnit_Time(ScalarUnit):
SCALAR_UNIT_DEFAULT = 'ms'
SCALAR_UNIT_DICT = {'d': 86400, 'h': 3600, 'm': 60, 's': 1,
'ms': 0.001, 'us': 0.000001, 'ns': 0.000000001}
class ScalarUnit_Frequency(ScalarUnit):
SCALAR_UNIT_DEFAULT = 'GHz'
SCALAR_UNIT_DICT = {'Hz': 1, 'kHz': 1000,
'MHz': 1000000, 'GHz': 1000000000}
scalarunit_mapping = {
ScalarUnit.SCALAR_UNIT_FREQUENCY: ScalarUnit_Frequency,
ScalarUnit.SCALAR_UNIT_SIZE: ScalarUnit_Size,
ScalarUnit.SCALAR_UNIT_TIME: ScalarUnit_Time,
}
def get_scalarunit_class(type):
return scalarunit_mapping.get(type)
def get_scalarunit_value(type, value, unit=None):
if type in ScalarUnit.SCALAR_UNIT_TYPES:
ScalarUnit_Class = get_scalarunit_class(type)
return (ScalarUnit_Class(value).
get_num_from_scalar_unit(unit))
else:
raise TypeError(_('"%s" is not a valid scalar-unit type') % type)

View File

@ -1,81 +0,0 @@
# 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.
from translator.toscalib.common.exception import InvalidTypeError
from translator.toscalib.elements.attribute_definition import AttributeDef
from translator.toscalib.elements.entitytype import EntityType
from translator.toscalib.elements.property_definition import PropertyDef
class StatefulEntityType(EntityType):
'''Class representing TOSCA states.'''
interfaces_node_lifecycle_operations = ['create',
'configure', 'start',
'stop', 'delete']
interfaces_relationship_confiure_operations = ['post_configure_source',
'post_configure_target',
'add_target',
'remove_target']
def __init__(self, entitytype, prefix, custom_def=None):
entire_entitytype = entitytype
if not entitytype.startswith(self.TOSCA):
entire_entitytype = prefix + entitytype
if entire_entitytype in list(self.TOSCA_DEF.keys()):
self.defs = self.TOSCA_DEF[entire_entitytype]
entitytype = entire_entitytype
elif custom_def and entitytype in list(custom_def.keys()):
self.defs = custom_def[entitytype]
else:
raise InvalidTypeError(what=entitytype)
self.type = entitytype
def get_properties_def_objects(self):
'''Return a list of property definition objects.'''
properties = []
props = self.get_value(self.PROPERTIES)
if props:
for prop, schema in props.items():
properties.append(PropertyDef(prop, None, schema))
return properties
def get_properties_def(self):
'''Return a dictionary of property definition name-object pairs.'''
return {prop.name: prop
for prop in self.get_properties_def_objects()}
def get_property_def_value(self, name):
'''Return the property definition associated with a given name.'''
props_def = self.get_properties_def()
if props_def and name in props_def.keys():
return props_def[name].value
def get_attributes_def_objects(self):
'''Return a list of attribute definition objects.'''
attrs = self.get_value(self.ATTRIBUTES)
if attrs:
return [AttributeDef(attr, None, schema)
for attr, schema in attrs.items()]
return []
def get_attributes_def(self):
'''Return a dictionary of attribute definition name-object pairs.'''
return {attr.name: attr
for attr in self.get_attributes_def_objects()}
def get_attribute_def_value(self, name):
'''Return the attribute definition associated with a given name.'''
attrs_def = self.get_attributes_def()
if attrs_def and name in attrs_def.keys():
return attrs_def[name].value

View File

@ -1,276 +0,0 @@
# 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.
from translator.toscalib.capabilities import Capability
from translator.toscalib.common.exception import MissingRequiredFieldError
from translator.toscalib.common.exception import UnknownFieldError
from translator.toscalib.common.exception import ValidationError
from translator.toscalib.elements.interfaces import InterfacesDef
from translator.toscalib.elements.nodetype import NodeType
from translator.toscalib.elements.relationshiptype import RelationshipType
from translator.toscalib.properties import Property
class EntityTemplate(object):
'''Base class for TOSCA templates.'''
SECTIONS = (DERIVED_FROM, PROPERTIES, REQUIREMENTS,
INTERFACES, CAPABILITIES, TYPE, DESCRIPTION, DIRECTIVES,
ATTRIBUTES, ARTIFACTS, NODE_FILTER, COPY) = \
('derived_from', 'properties', 'requirements', 'interfaces',
'capabilities', 'type', 'description', 'directives',
'attributes', 'artifacts', 'node_filter', 'copy')
REQUIREMENTS_SECTION = (NODE, CAPABILITY, RELATIONSHIP, OCCURRENCES) = \
('node', 'capability', 'relationship',
'occurrences')
def __init__(self, name, template, entity_name, custom_def=None):
self.name = name
self.entity_tpl = template
self.custom_def = custom_def
self._validate_field(self.entity_tpl)
if entity_name == 'node_type':
self.type_definition = NodeType(self.entity_tpl['type'],
custom_def)
if entity_name == 'relationship_type':
relationship = template.get('relationship')
type = None
if relationship and isinstance(relationship, dict):
type = relationship.get('type')
elif isinstance(relationship, str):
type = self.entity_tpl['relationship']
else:
type = self.entity_tpl['type']
self.type_definition = RelationshipType(type,
None, custom_def)
self._properties = None
self._interfaces = None
self._requirements = None
self._capabilities = None
@property
def type(self):
return self.type_definition.type
@property
def requirements(self):
if self._requirements is None:
self._requirements = self.type_definition.get_value(
self.REQUIREMENTS,
self.entity_tpl) or []
return self._requirements
def get_properties_objects(self):
'''Return properties objects for this template.'''
if self._properties is None:
self._properties = self._create_properties()
return self._properties
def get_properties(self):
'''Return a dictionary of property name-object pairs.'''
return {prop.name: prop
for prop in self.get_properties_objects()}
def get_property_value(self, name):
'''Return the value of a given property name.'''
props = self.get_properties()
if props and name in props.keys():
return props[name].value
@property
def interfaces(self):
if self._interfaces is None:
self._interfaces = self._create_interfaces()
return self._interfaces
def get_capabilities_objects(self):
'''Return capabilities objects for this template.'''
if not self._capabilities:
self._capabilities = self._create_capabilities()
return self._capabilities
def get_capabilities(self):
'''Return a dictionary of capability name-object pairs.'''
return {cap.name: cap
for cap in self.get_capabilities_objects()}
def is_derived_from(self, type_str):
'''Check if object inherits from the given type.
Returns true if this object is derived from 'type_str'.
False otherwise.
'''
if not self.type:
return False
elif self.type == type_str:
return True
elif self.parent_type:
return self.parent_type.is_derived_from(type_str)
else:
return False
def _create_capabilities(self):
capability = []
caps = self.type_definition.get_value(self.CAPABILITIES,
self.entity_tpl)
if caps:
for name, props in caps.items():
capabilities = self.type_definition.get_capabilities()
if name in capabilities.keys():
c = capabilities[name]
cap = Capability(name, props['properties'], c)
capability.append(cap)
return capability
def _validate_properties(self, template, entitytype):
properties = entitytype.get_value(self.PROPERTIES, template)
self._common_validate_properties(entitytype, properties)
def _validate_capabilities(self):
type_capabilities = self.type_definition.get_capabilities()
allowed_caps = \
type_capabilities.keys() if type_capabilities else []
capabilities = self.type_definition.get_value(self.CAPABILITIES,
self.entity_tpl)
if capabilities:
self._common_validate_field(capabilities, allowed_caps,
'Capabilities')
self._validate_capabilities_properties(capabilities)
def _validate_capabilities_properties(self, capabilities):
for cap, props in capabilities.items():
capabilitydef = self.get_capability(cap).definition
self._common_validate_properties(capabilitydef,
props[self.PROPERTIES])
# validating capability properties values
for prop in self.get_capability(cap).get_properties_objects():
prop.validate()
# TODO(srinivas_tadepalli): temporary work around to validate
# default_instances until standardized in specification
if cap == "scalable" and prop.name == "default_instances":
prop_dict = props[self.PROPERTIES]
min_instances = prop_dict.get("min_instances")
max_instances = prop_dict.get("max_instances")
default_instances = prop_dict.get("default_instances")
if not (min_instances <= default_instances
<= max_instances):
err_msg = ("Properties of template %s : "
"default_instances value is not"
" between min_instances and "
"max_instances" % self.name)
raise ValidationError(message=err_msg)
def _common_validate_properties(self, entitytype, properties):
allowed_props = []
required_props = []
for p in entitytype.get_properties_def_objects():
allowed_props.append(p.name)
if p.required:
required_props.append(p.name)
if properties:
self._common_validate_field(properties, allowed_props,
'Properties')
# make sure it's not missing any property required by a tosca type
missingprop = []
for r in required_props:
if r not in properties.keys():
missingprop.append(r)
if missingprop:
raise MissingRequiredFieldError(
what='Properties of template %s' % self.name,
required=missingprop)
else:
if required_props:
raise MissingRequiredFieldError(
what='Properties of template %s' % self.name,
required=missingprop)
def _validate_field(self, template):
if not isinstance(template, dict):
raise MissingRequiredFieldError(
what='Template %s' % self.name, required=self.TYPE)
try:
relationship = template.get('relationship')
if relationship and not isinstance(relationship, str):
relationship[self.TYPE]
elif isinstance(relationship, str):
template['relationship']
else:
template[self.TYPE]
except KeyError:
raise MissingRequiredFieldError(
what='Template %s' % self.name, required=self.TYPE)
def _common_validate_field(self, schema, allowedlist, section):
for name in schema:
if name not in allowedlist:
raise UnknownFieldError(
what='%(section)s of template %(nodename)s'
% {'section': section, 'nodename': self.name},
field=name)
def _create_properties(self):
props = []
properties = self.type_definition.get_value(self.PROPERTIES,
self.entity_tpl) or {}
for name, value in properties.items():
props_def = self.type_definition.get_properties_def()
if props_def and name in props_def:
prop = Property(name, value,
props_def[name].schema, self.custom_def)
props.append(prop)
for p in self.type_definition.get_properties_def_objects():
if p.default is not None and p.name not in properties.keys():
prop = Property(p.name, p.default, p.schema, self.custom_def)
props.append(prop)
return props
def _create_interfaces(self):
interfaces = []
type_interfaces = None
if isinstance(self.type_definition, RelationshipType):
if isinstance(self.entity_tpl, dict):
for rel_def, value in self.entity_tpl.items():
if rel_def != 'type':
rel_def = self.entity_tpl.get(rel_def)
rel = None
if isinstance(rel_def, dict):
rel = rel_def.get('relationship')
if rel:
if self.INTERFACES in rel:
type_interfaces = rel[self.INTERFACES]
break
else:
type_interfaces = self.type_definition.get_value(self.INTERFACES,
self.entity_tpl)
if type_interfaces:
for interface_type, value in type_interfaces.items():
for op, op_def in value.items():
iface = InterfacesDef(self.type_definition,
interfacetype=interface_type,
node_template=self,
name=op,
value=op_def)
interfaces.append(iface)
return interfaces
def get_capability(self, name):
"""Provide named capability
:param name: name of capability
:return: capability object if found, None otherwise
"""
caps = self.get_capabilities()
if caps and name in caps.keys():
return caps[name]

View File

@ -1,378 +0,0 @@
#
# 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 abc
import six
from translator.toscalib.common.exception import UnknownInputError
from translator.toscalib.utils.gettextutils import _
GET_PROPERTY = 'get_property'
GET_ATTRIBUTE = 'get_attribute'
GET_INPUT = 'get_input'
SELF = 'SELF'
HOST = 'HOST'
HOSTED_ON = 'tosca.relationships.HostedOn'
@six.add_metaclass(abc.ABCMeta)
class Function(object):
"""An abstract type for representing a Tosca template function."""
def __init__(self, tosca_tpl, context, name, args):
self.tosca_tpl = tosca_tpl
self.context = context
self.name = name
self.args = args
self.validate()
@abc.abstractmethod
def result(self):
"""Invokes the function and returns its result
Some methods invocation may only be relevant on runtime (for example,
getting runtime properties) and therefore its the responsibility of
the orchestrator/translator to take care of such functions invocation.
:return: Function invocation result.
"""
return {self.name: self.args}
@abc.abstractmethod
def validate(self):
"""Validates function arguments."""
pass
class GetInput(Function):
"""Get a property value declared within the input of the service template.
Arguments:
* Input name.
Example:
* get_input: port
"""
def validate(self):
if len(self.args) != 1:
raise ValueError(_(
'Expected one argument for get_input function but received: '
'{0}.').format(self.args))
inputs = [input.name for input in self.tosca_tpl.inputs]
if self.args[0] not in inputs:
raise UnknownInputError(input_name=self.args[0])
def result(self):
found_input = [input_def for input_def in self.tosca_tpl.inputs
if self.input_name == input_def.name][0]
return found_input.default
@property
def input_name(self):
return self.args[0]
class GetAttribute(Function):
"""Get an attribute value of an entity defined in the service template
Node template attributes values are set in runtime and therefore its the
responsibility of the Tosca engine to implement the evaluation of
get_attribute functions.
Arguments:
* Node template name | HOST.
* Attribute name.
If the HOST keyword is passed as the node template name argument the
function will search each node template along the HostedOn relationship
chain until a node which contains the attribute is found.
Examples:
* { get_attribute: [ server, private_address ] }
* { get_attribute: [ HOST, private_address ] }
"""
def validate(self):
if len(self.args) != 2:
raise ValueError(_(
'Illegal arguments for {0} function. Expected arguments: '
'node-template-name, attribute-name').format(GET_ATTRIBUTE))
self._find_node_template_containing_attribute()
def result(self):
return self.args
def get_referenced_node_template(self):
"""Gets the NodeTemplate instance the get_attribute function refers to.
If HOST keyword was used as the node template argument, the node
template which contains the attribute along the HostedOn relationship
chain will be returned.
"""
return self._find_node_template_containing_attribute()
def _find_node_template_containing_attribute(self):
if self.node_template_name == HOST:
# Currently this is the only way to tell whether the function
# is used within the outputs section of the TOSCA template.
if isinstance(self.context, list):
raise ValueError(_(
"get_attribute HOST keyword is not allowed within the "
"outputs section of the TOSCA template"))
node_tpl = self._find_host_containing_attribute()
if not node_tpl:
raise ValueError(_(
"get_attribute HOST keyword is used in '{0}' node "
"template but {1} was not found "
"in relationship chain").format(self.context.name,
HOSTED_ON))
else:
node_tpl = self._find_node_template(self.args[0])
if not self._attribute_exists_in_type(node_tpl.type_definition):
raise KeyError(_(
"Attribute '{0}' not found in node template: {1}.").format(
self.attribute_name, node_tpl.name))
return node_tpl
def _attribute_exists_in_type(self, type_definition):
attrs_def = type_definition.get_attributes_def()
found = [attrs_def[self.attribute_name]] \
if self.attribute_name in attrs_def else []
return len(found) == 1
def _find_host_containing_attribute(self, node_template_name=SELF):
node_template = self._find_node_template(node_template_name)
from translator.toscalib.elements.entitytype import EntityType
hosted_on_rel = EntityType.TOSCA_DEF[HOSTED_ON]
for r in node_template.requirements:
for requirement, target_name in r.items():
target_node = self._find_node_template(target_name)
target_type = target_node.type_definition
for capability in target_type.get_capabilities_objects():
if capability.type in hosted_on_rel['valid_target_types']:
if self._attribute_exists_in_type(target_type):
return target_node
return self._find_host_containing_attribute(
target_name)
return None
def _find_node_template(self, node_template_name):
name = self.context.name if node_template_name == SELF else \
node_template_name
for node_template in self.tosca_tpl.nodetemplates:
if node_template.name == name:
return node_template
raise KeyError(_(
'No such node template: {0}.').format(node_template_name))
@property
def node_template_name(self):
return self.args[0]
@property
def attribute_name(self):
return self.args[1]
class GetProperty(Function):
"""Get a property value of an entity defined in the same service template.
Arguments:
* Node template name.
* Requirement or capability name (optional).
* Property name.
If requirement or capability name is specified, the behavior is as follows:
The req or cap name is first looked up in the specified node template's
requirements.
If found, it would search for a matching capability
of an other node template and get its property as specified in function
arguments.
Otherwise, the req or cap name would be looked up in the specified
node template's capabilities and if found, it would return the property of
the capability as specified in function arguments.
Examples:
* { get_property: [ mysql_server, port ] }
* { get_property: [ SELF, db_port ] }
* { get_property: [ SELF, database_endpoint, port ] }
"""
def validate(self):
if len(self.args) < 2 or len(self.args) > 3:
raise ValueError(_(
'Expected arguments: [node-template-name, req-or-cap '
'(optional), property name.'))
if len(self.args) == 2:
prop = self._find_property(self.args[1]).value
if not isinstance(prop, Function):
get_function(self.tosca_tpl, self.context, prop)
elif len(self.args) == 3:
get_function(self.tosca_tpl,
self.context,
self._find_req_or_cap_property(self.args[1],
self.args[2]))
else:
raise NotImplementedError(_(
'Nested properties are not supported.'))
def _find_req_or_cap_property(self, req_or_cap, property_name):
node_tpl = self._find_node_template(self.args[0])
# Find property in node template's requirements
for r in node_tpl.requirements:
for req, node_name in r.items():
if req == req_or_cap:
node_template = self._find_node_template(node_name)
return self._get_capability_property(
node_template,
req,
property_name)
# If requirement was not found, look in node template's capabilities
return self._get_capability_property(node_tpl,
req_or_cap,
property_name)
def _get_capability_property(self,
node_template,
capability_name,
property_name):
"""Gets a node template capability property."""
caps = node_template.get_capabilities()
if caps and capability_name in caps.keys():
cap = caps[capability_name]
property = None
props = cap.get_properties()
if props and property_name in props.keys():
property = props[property_name].value
if not property:
raise KeyError(_(
"Property '{0}' not found in capability '{1}' of node"
" template '{2}' referenced from node template"
" '{3}'.").format(property_name,
capability_name,
node_template.name,
self.context.name))
return property
msg = _("Requirement/Capability '{0}' referenced from '{1}' node "
"template not found in '{2}' node template.").format(
capability_name,
self.context.name,
node_template.name)
raise KeyError(msg)
def _find_property(self, property_name):
node_tpl = self._find_node_template(self.args[0])
props = node_tpl.get_properties()
found = [props[property_name]] if property_name in props else []
if len(found) == 0:
raise KeyError(_(
"Property: '{0}' not found in node template: {1}.").format(
property_name, node_tpl.name))
return found[0]
def _find_node_template(self, node_template_name):
if node_template_name == SELF:
return self.context
for node_template in self.tosca_tpl.nodetemplates:
if node_template.name == node_template_name:
return node_template
raise KeyError(_(
'No such node template: {0}.').format(node_template_name))
def result(self):
if len(self.args) == 3:
property_value = self._find_req_or_cap_property(self.args[1],
self.args[2])
else:
property_value = self._find_property(self.args[1]).value
if isinstance(property_value, Function):
return property_value
return get_function(self.tosca_tpl,
self.context,
property_value)
@property
def node_template_name(self):
return self.args[0]
@property
def property_name(self):
if len(self.args) > 2:
return self.args[2]
return self.args[1]
@property
def req_or_cap(self):
if len(self.args) > 2:
return self.args[1]
return None
function_mappings = {
GET_PROPERTY: GetProperty,
GET_INPUT: GetInput,
GET_ATTRIBUTE: GetAttribute
}
def is_function(function):
"""Returns True if the provided function is a Tosca intrinsic function.
Examples:
* "{ get_property: { SELF, port } }"
* "{ get_input: db_name }"
* Function instance
:param function: Function as string or a Function instance.
:return: True if function is a Tosca intrinsic function, otherwise False.
"""
if isinstance(function, dict) and len(function) == 1:
func_name = list(function.keys())[0]
return func_name in function_mappings
return isinstance(function, Function)
def get_function(tosca_tpl, node_template, raw_function):
"""Gets a Function instance representing the provided template function.
If the format provided raw_function format is not relevant for template
functions or if the function name doesn't exist in function mapping the
method returns the provided raw_function.
:param tosca_tpl: The tosca template.
:param node_template: The node template the function is specified for.
:param raw_function: The raw function as dict.
:return: Template function as Function instance or the raw_function if
parsing was unsuccessful.
"""
if is_function(raw_function):
func_name = list(raw_function.keys())[0]
if func_name in function_mappings:
func = function_mappings[func_name]
func_args = list(raw_function.values())[0]
if not isinstance(func_args, list):
func_args = [func_args]
return func(tosca_tpl, node_template, func_name, func_args)
return raw_function

View File

@ -1,27 +0,0 @@
# 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.
class NodeGroup(object):
def __init__(self, name, group_templates, member_nodes):
self.name = name
self.tpl = group_templates
self.members = member_nodes
@property
def member_names(self):
return self.tpl.get('members')
@property
def policies(self):
return self.tpl.get('policies')

View File

@ -1,218 +0,0 @@
# 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._validate_fields(node_templates[name])
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():
explicit = self._get_explicit_relationship(r, value)
if explicit:
for key, value in explicit.items():
self._relationships[key] = value
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 isinstance(value, dict) else value
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') \
if isinstance(value, dict) else None
# 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, None,
self.custom_def)
explicit_relation[rtype] = related_tpl
self.relationship_tpl.append(tpl)
found_relationship_tpl = True
# create relationship template object.
rel_prfx = self.type_definition.RELATIONSHIP_PREFIX
if not found_relationship_tpl:
if isinstance(relationship, dict):
relationship = relationship.get('type')
if self.available_rel_types and \
relationship in self.available_rel_types.keys():
pass
elif 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:
super_type = \
rel_type_def.get('derived_from')
if not super_type.startswith(rel_prfx):
super_type = rel_prfx + super_type
if rtype.type == super_type:
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):
self._validate_requirements_keys(value)
allowed_reqs.append(r1)
self._common_validate_field(req, allowed_reqs, 'Requirements')
def _validate_requirements_keys(self, requirement):
for key in requirement.keys():
if key not in self.REQUIREMENTS_SECTION:
raise UnknownFieldError(
what='Requirements of template %s' % self.name,
field=key)
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)
def _validate_fields(self, nodetemplate):
for name in nodetemplate.keys():
if name not in self.SECTIONS:
raise UnknownFieldError(what='Node template %s'
% self.name, field=name)

View File

@ -1,110 +0,0 @@
# 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 MissingRequiredFieldError
from translator.toscalib.common.exception import UnknownFieldError
from translator.toscalib.dataentity import DataEntity
from translator.toscalib.elements.constraints import Schema
from translator.toscalib.elements.entitytype import EntityType
from translator.toscalib.utils.gettextutils import _
log = logging.getLogger('tosca')
class Input(object):
INPUTFIELD = (TYPE, DESCRIPTION, DEFAULT, CONSTRAINTS) = \
('type', 'description', 'default', 'constraints')
def __init__(self, name, schema_dict):
self.name = name
self.schema = Schema(name, schema_dict)
@property
def type(self):
return self.schema.type
@property
def description(self):
return self.schema.description
@property
def default(self):
return self.schema.default
@property
def constraints(self):
return self.schema.constraints
def validate(self, value=None):
self._validate_field()
self.validate_type(self.type)
if value:
self._validate_value(value)
def _validate_field(self):
for name in self.schema:
if name not in self.INPUTFIELD:
raise UnknownFieldError(what='Input %s' % self.name,
field=name)
def validate_type(self, input_type):
if input_type not in Schema.PROPERTY_TYPES:
raise ValueError(_('Invalid type %s') % type)
def _validate_value(self, value):
tosca = EntityType.TOSCA_DEF
datatype = None
if self.type in tosca:
datatype = tosca[self.type]
elif EntityType.DATATYPE_PREFIX + self.type in tosca:
datatype = tosca[EntityType.DATATYPE_PREFIX + self.type]
DataEntity.validate_datatype(self.type, value, None, datatype)
class Output(object):
OUTPUTFIELD = (DESCRIPTION, VALUE) = ('description', 'value')
def __init__(self, name, attrs):
self.name = name
self.attrs = attrs
@property
def description(self):
return self.attrs[self.DESCRIPTION]
@property
def value(self):
return self.attrs[self.VALUE]
def validate(self):
self._validate_field()
def _validate_field(self):
if not isinstance(self.attrs, dict):
raise MissingRequiredFieldError(what='Output %s' % self.name,
required=self.VALUE)
try:
self.value
except KeyError:
raise MissingRequiredFieldError(what='Output %s' % self.name,
required=self.VALUE)
for name in self.attrs:
if name not in self.OUTPUTFIELD:
raise UnknownFieldError(what='Output %s' % self.name,
field=name)

View File

@ -1,76 +0,0 @@
# 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.
from translator.toscalib.dataentity import DataEntity
from translator.toscalib.elements.constraints import Schema
from translator.toscalib.functions import is_function
class Property(object):
'''TOSCA built-in Property type.'''
PROPERTY_KEYS = (
TYPE, REQUIRED, DESCRIPTION, DEFAULT, CONSTRAINTS
) = (
'type', 'required', 'description', 'default', 'constraints'
)
ENTRY_SCHEMA_KEYS = (
ENTRYTYPE, ENTRYPROPERTIES
) = (
'type', 'properties'
)
def __init__(self, property_name, value, schema_dict, custom_def=None):
self.name = property_name
self.value = value
self.custom_def = custom_def
self.schema = Schema(property_name, schema_dict)
@property
def type(self):
return self.schema.type
@property
def required(self):
return self.schema.required
@property
def description(self):
return self.schema.description
@property
def default(self):
return self.schema.default
@property
def constraints(self):
return self.schema.constraints
@property
def entry_schema(self):
return self.schema.entry_schema
def validate(self):
'''Validate if not a reference property.'''
if not is_function(self.value):
if self.type == Schema.STRING:
self.value = str(self.value)
self.value = DataEntity.validate_datatype(self.type, self.value,
self.entry_schema,
self.custom_def)
self._validate_constraints()
def _validate_constraints(self):
if self.constraints:
for constraint in self.constraints:
constraint.validate(self.value)

View File

@ -1,68 +0,0 @@
# 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.entity_template import EntityTemplate
from translator.toscalib.properties import Property
SECTIONS = (DERIVED_FROM, PROPERTIES, REQUIREMENTS,
INTERFACES, CAPABILITIES, TYPE) = \
('derived_from', 'properties', 'requirements', 'interfaces',
'capabilities', 'type')
log = logging.getLogger('tosca')
class RelationshipTemplate(EntityTemplate):
'''Relationship template.'''
def __init__(self, relationship_template, name, custom_def=None):
super(RelationshipTemplate, self).__init__(name,
relationship_template,
'relationship_type',
custom_def)
self.name = name.lower()
def get_properties_objects(self):
'''Return properties objects for this template.'''
if self._properties is None:
self._properties = self._create_relationship_properties()
return self._properties
def _create_relationship_properties(self):
props = []
properties = {}
relationship = self.entity_tpl.get('relationship')
if relationship:
properties = self.type_definition.get_value(self.PROPERTIES,
relationship) or {}
if not properties:
properties = self.entity_tpl.get(self.PROPERTIES) or {}
if properties:
for name, value in properties.items():
props_def = self.type_definition.get_properties_def()
if props_def and name in props_def:
if name in properties.keys():
value = properties.get(name)
prop = Property(name, value,
props_def[name].schema, self.custom_def)
props.append(prop)
for p in self.type_definition.get_properties_def_objects():
if p.default is not None and p.name not in properties.keys():
prop = Property(p.name, p.default, p.schema, self.custom_def)
props.append(prop)
return props
def validate(self):
self._validate_properties(self.entity_tpl, self.type_definition)

View File

@ -21,7 +21,7 @@ import fixtures
import testscenarios
import testtools
from translator.toscalib.tosca_template import ToscaTemplate
from toscaparser.tosca_template import ToscaTemplate
_TRUE_VALUES = ('True', 'true', '1', 'yes')

View File

@ -13,11 +13,11 @@
import datetime
import yaml
from translator.toscalib.common import exception
from translator.toscalib.elements.constraints import Constraint
from translator.toscalib.elements.constraints import Schema
from translator.toscalib.tests.base import TestCase
from translator.toscalib.utils import yamlparser
from toscaparser.common import exception
from toscaparser.elements.constraints import Constraint
from toscaparser.elements.constraints import Schema
from toscaparser.tests.base import TestCase
from toscaparser.utils import yamlparser
class ConstraintTest(TestCase):

View File

@ -13,13 +13,13 @@
import os
from testtools.testcase import skip
from translator.toscalib.common import exception
from translator.toscalib.dataentity import DataEntity
from translator.toscalib.elements.datatype import DataType
from translator.toscalib.parameters import Input
from translator.toscalib.tests.base import TestCase
from translator.toscalib.tosca_template import ToscaTemplate
from translator.toscalib.utils import yamlparser
from toscaparser.common import exception
from toscaparser.dataentity import DataEntity
from toscaparser.elements.datatype import DataType
from toscaparser.parameters import Input
from toscaparser.tests.base import TestCase
from toscaparser.tosca_template import ToscaTemplate
from toscaparser.utils import yamlparser
class DataTypeTest(TestCase):

View File

@ -10,8 +10,8 @@
# License for the specific language governing permissions and limitations
# under the License.
from translator.toscalib.common import exception
from translator.toscalib.tests.base import TestCase
from toscaparser.common import exception
from toscaparser.tests.base import TestCase
class ExceptionTest(TestCase):

View File

@ -12,10 +12,10 @@
import os
import six
from translator.toscalib.common import exception
from translator.toscalib import functions
from translator.toscalib.tests.base import TestCase
from translator.toscalib.tosca_template import ToscaTemplate
from toscaparser.common import exception
from toscaparser import functions
from toscaparser.tests.base import TestCase
from toscaparser.tosca_template import ToscaTemplate
class IntrinsicFunctionsTest(TestCase):

View File

@ -10,10 +10,10 @@
# License for the specific language governing permissions and limitations
# under the License.
from translator.toscalib.common import exception
from translator.toscalib.properties import Property
from translator.toscalib.tests.base import TestCase
from translator.toscalib.utils import yamlparser
from toscaparser.common import exception
from toscaparser.properties import Property
from toscaparser.tests.base import TestCase
from toscaparser.utils import yamlparser
class PropertyTest(TestCase):

View File

@ -10,13 +10,13 @@
# License for the specific language governing permissions and limitations
# under the License.
from translator.toscalib.common import exception
from translator.toscalib.elements.scalarunit import ScalarUnit_Frequency
from translator.toscalib.elements.scalarunit import ScalarUnit_Size
from translator.toscalib.elements.scalarunit import ScalarUnit_Time
from translator.toscalib.nodetemplate import NodeTemplate
from translator.toscalib.tests.base import TestCase
from translator.toscalib.utils import yamlparser
from toscaparser.common import exception
from toscaparser.elements.scalarunit import ScalarUnit_Frequency
from toscaparser.elements.scalarunit import ScalarUnit_Size
from toscaparser.elements.scalarunit import ScalarUnit_Time
from toscaparser.nodetemplate import NodeTemplate
from toscaparser.tests.base import TestCase
from toscaparser.utils import yamlparser
class ScalarUnitPositiveTest(TestCase):

View File

@ -12,11 +12,11 @@
import os
from translator.toscalib.tests.base import TestCase
from translator.toscalib.topology_template import TopologyTemplate
import translator.toscalib.utils.yamlparser
from toscaparser.tests.base import TestCase
from toscaparser.topology_template import TopologyTemplate
import toscaparser.utils.yamlparser
YAML_LOADER = translator.toscalib.utils.yamlparser.load_yaml
YAML_LOADER = toscaparser.utils.yamlparser.load_yaml
class TopologyTemplateTest(TestCase):

View File

@ -10,11 +10,11 @@
# License for the specific language governing permissions and limitations
# under the License.
from translator.toscalib.common import exception
from translator.toscalib.elements.artifacttype import ArtifactTypeDef
import translator.toscalib.elements.interfaces as ifaces
from translator.toscalib.elements.nodetype import NodeType
from translator.toscalib.tests.base import TestCase
from toscaparser.common import exception
from toscaparser.elements.artifacttype import ArtifactTypeDef
import toscaparser.elements.interfaces as ifaces
from toscaparser.elements.nodetype import NodeType
from toscaparser.tests.base import TestCase
compute_type = NodeType('tosca.nodes.Compute')
component_type = NodeType('tosca.nodes.SoftwareComponent')

View File

@ -13,15 +13,15 @@
import os
import six
from translator.toscalib.common import exception
import translator.toscalib.elements.interfaces as ifaces
from translator.toscalib.elements.nodetype import NodeType
from translator.toscalib.functions import GetInput
from translator.toscalib.functions import GetProperty
from translator.toscalib.nodetemplate import NodeTemplate
from translator.toscalib.tests.base import TestCase
from translator.toscalib.tosca_template import ToscaTemplate
import translator.toscalib.utils.yamlparser
from toscaparser.common import exception
import toscaparser.elements.interfaces as ifaces
from toscaparser.elements.nodetype import NodeType
from toscaparser.functions import GetInput
from toscaparser.functions import GetProperty
from toscaparser.nodetemplate import NodeTemplate
from toscaparser.tests.base import TestCase
from toscaparser.tosca_template import ToscaTemplate
import toscaparser.utils.yamlparser
class ToscaTemplateTest(TestCase):
@ -324,7 +324,7 @@ class ToscaTemplateTest(TestCase):
self._requirements_not_implemented(tpl_snippet_3, 'my_webserver2')
def _requirements_not_implemented(self, tpl_snippet, tpl_name):
nodetemplates = (translator.toscalib.utils.yamlparser.
nodetemplates = (toscaparser.utils.yamlparser.
simple_parse(tpl_snippet))['node_templates']
self.assertRaises(
NotImplementedError,
@ -355,9 +355,9 @@ class ToscaTemplateTest(TestCase):
required: no
'''
expected_capabilities = ['test_cap']
nodetemplates = (translator.toscalib.utils.yamlparser.
nodetemplates = (toscaparser.utils.yamlparser.
simple_parse(tpl_snippet))['node_templates']
custom_def = (translator.toscalib.utils.yamlparser.
custom_def = (toscaparser.utils.yamlparser.
simple_parse(custom_def))
name = list(nodetemplates.keys())[0]
tpl = NodeTemplate(name, nodetemplates, custom_def)
@ -373,7 +373,7 @@ class ToscaTemplateTest(TestCase):
test_cap:
type: tosca.capabilities.TestCapability
'''
custom_def = (translator.toscalib.utils.yamlparser.
custom_def = (toscaparser.utils.yamlparser.
simple_parse(custom_def))
tpl = NodeTemplate(name, nodetemplates, custom_def)
err = self.assertRaises(

View File

@ -13,14 +13,14 @@
import os
import six
from translator.toscalib.common import exception
from translator.toscalib.nodetemplate import NodeTemplate
from translator.toscalib.parameters import Input
from translator.toscalib.parameters import Output
from translator.toscalib.relationship_template import RelationshipTemplate
from translator.toscalib.tests.base import TestCase
from translator.toscalib.tosca_template import ToscaTemplate
import translator.toscalib.utils.yamlparser
from toscaparser.common import exception
from toscaparser.nodetemplate import NodeTemplate
from toscaparser.parameters import Input
from toscaparser.parameters import Output
from toscaparser.relationship_template import RelationshipTemplate
from toscaparser.tests.base import TestCase
from toscaparser.tosca_template import ToscaTemplate
import toscaparser.utils.yamlparser
class ToscaTemplateValidationTest(TestCase):
@ -58,7 +58,7 @@ class ToscaTemplateValidationTest(TestCase):
constraint:
- valid_values: [ 1, 2, 4, 8 ]
'''
inputs = (translator.toscalib.utils.yamlparser.
inputs = (toscaparser.utils.yamlparser.
simple_parse(tpl_snippet)['inputs'])
name, attrs = list(inputs.items())[0]
input = Input(name, attrs)
@ -77,7 +77,7 @@ class ToscaTemplateValidationTest(TestCase):
description: IP address of server instance.
values: { get_property: [server, private_address] }
'''
outputs = (translator.toscalib.utils.yamlparser.
outputs = (toscaparser.utils.yamlparser.
simple_parse(tpl_snippet)['outputs'])
name, attrs = list(outputs.items())[0]
output = Output(name, attrs)
@ -95,7 +95,7 @@ class ToscaTemplateValidationTest(TestCase):
descriptions: IP address of server instance.
value: { get_property: [server, private_address] }
'''
outputs = (translator.toscalib.utils.yamlparser.
outputs = (toscaparser.utils.yamlparser.
simple_parse(tpl_snippet)['outputs'])
name, attrs = list(outputs.items())[0]
output = Output(name, attrs)
@ -113,7 +113,7 @@ class ToscaTemplateValidationTest(TestCase):
def_file = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
"data/custom_types/wordpress.yaml")
custom_type = translator.toscalib.utils.yamlparser.load_yaml(def_file)
custom_type = toscaparser.utils.yamlparser.load_yaml(def_file)
node_types = custom_type['node_types']
for name in node_types:
defintion = node_types[name]
@ -122,7 +122,7 @@ class ToscaTemplateValidationTest(TestCase):
def _single_node_template_content_test(self, tpl_snippet, expectederror,
expectedmessage):
nodetemplates = (translator.toscalib.utils.yamlparser.
nodetemplates = (toscaparser.utils.yamlparser.
simple_ordered_parse(tpl_snippet))['node_templates']
name = list(nodetemplates.keys())[0]
try:
@ -648,7 +648,7 @@ class ToscaTemplateValidationTest(TestCase):
def _single_rel_template_content_test(self, tpl_snippet, expectederror,
expectedmessage):
rel_template = (translator.toscalib.utils.yamlparser.
rel_template = (toscaparser.utils.yamlparser.
simple_parse(tpl_snippet))['relationship_templates']
name = list(rel_template.keys())[0]
rel_template = RelationshipTemplate(rel_template[name], name)

View File

@ -10,10 +10,10 @@
# License for the specific language governing permissions and limitations
# under the License.
from translator.toscalib.common.exception import (
from toscaparser.common.exception import (
InvalidTOSCAVersionPropertyException)
from translator.toscalib.tests.base import TestCase
from translator.toscalib.utils.validateutils import TOSCAVersionProperty
from toscaparser.tests.base import TestCase
from toscaparser.utils.validateutils import TOSCAVersionProperty
class TOSCAVersionPropertyTest(TestCase):

View File

@ -1,213 +0,0 @@
# 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 import exception
from translator.toscalib import functions
from translator.toscalib.groups import NodeGroup
from translator.toscalib.nodetemplate import NodeTemplate
from translator.toscalib.parameters import Input
from translator.toscalib.parameters import Output
from translator.toscalib.relationship_template import RelationshipTemplate
from translator.toscalib.tpl_relationship_graph import ToscaGraph
# Topology template key names
SECTIONS = (DESCRIPTION, INPUTS, NODE_TEMPLATES,
RELATIONSHIP_TEMPLATES, OUTPUTS, GROUPS,
SUBSTITUION_MAPPINGS) = \
('description', 'inputs', 'node_templates',
'relationship_templates', 'outputs', 'groups',
'substitution_mappings')
log = logging.getLogger("tosca.model")
class TopologyTemplate(object):
'''Load the template data.'''
def __init__(self, template, custom_defs,
rel_types=None, parsed_params=None):
self.tpl = template
self.custom_defs = custom_defs
self.rel_types = rel_types
self.parsed_params = parsed_params
self._validate_field()
self.description = self._tpl_description()
self.inputs = self._inputs()
self.relationship_templates = self._relationship_templates()
self.nodetemplates = self._nodetemplates()
self.outputs = self._outputs()
self.graph = ToscaGraph(self.nodetemplates)
self.groups = self._groups()
self._process_intrinsic_functions()
def _inputs(self):
inputs = []
for name, attrs in self._tpl_inputs().items():
input = Input(name, attrs)
if self.parsed_params and name in self.parsed_params:
input.validate(self.parsed_params[name])
inputs.append(input)
return inputs
def _nodetemplates(self):
nodetemplates = []
tpls = self._tpl_nodetemplates()
for name in tpls:
tpl = NodeTemplate(name, tpls, self.custom_defs,
self.relationship_templates,
self.rel_types)
tpl.validate(self)
nodetemplates.append(tpl)
return nodetemplates
def _relationship_templates(self):
rel_templates = []
tpls = self._tpl_relationship_templates()
for name in tpls:
tpl = RelationshipTemplate(tpls[name], name, self.custom_defs)
rel_templates.append(tpl)
return rel_templates
def _outputs(self):
outputs = []
for name, attrs in self._tpl_outputs().items():
output = Output(name, attrs)
output.validate()
outputs.append(output)
return outputs
def _substitution_mappings(self):
pass
def _groups(self):
groups = []
for group_name, group_tpl in self._tpl_groups().items():
member_names = group_tpl.get('members')
if member_names and len(member_names) > 1:
group = NodeGroup(group_name, group_tpl,
self._get_group_memerbs(member_names))
groups.append(group)
else:
raise ValueError
return groups
def _get_group_memerbs(self, member_names):
member_nodes = []
for member in member_names:
for node in self.nodetemplates:
if node.name == member:
member_nodes.append(node)
return member_nodes
# topology template can act like node template
# it is exposed by substitution_mappings.
def nodetype(self):
pass
def capabilities(self):
pass
def requirements(self):
pass
def _tpl_description(self):
description = self.tpl.get(DESCRIPTION)
if description:
description = description.rstrip()
return description
def _tpl_inputs(self):
return self.tpl.get(INPUTS) or {}
def _tpl_nodetemplates(self):
return self.tpl[NODE_TEMPLATES]
def _tpl_relationship_templates(self):
return self.tpl.get(RELATIONSHIP_TEMPLATES) or {}
def _tpl_outputs(self):
return self.tpl.get(OUTPUTS) or {}
def _tpl_substitution_mappings(self):
return self.tpl.get(SUBSTITUION_MAPPINGS) or {}
def _tpl_groups(self):
return self.tpl.get(GROUPS) or {}
def _validate_field(self):
for name in self.tpl:
if name not in SECTIONS:
raise exception.UnknownFieldError(what='Template', field=name)
def _process_intrinsic_functions(self):
"""Process intrinsic functions
Current implementation processes functions within node template
properties, requirements, interfaces inputs and template outputs.
"""
for node_template in self.nodetemplates:
for prop in node_template.get_properties_objects():
prop.value = functions.get_function(self,
node_template,
prop.value)
for interface in node_template.interfaces:
if interface.inputs:
for name, value in interface.inputs.items():
interface.inputs[name] = functions.get_function(
self,
node_template,
value)
if node_template.requirements:
for req in node_template.requirements:
rel = req
for req_name, req_item in req.items():
if isinstance(req_item, dict):
rel = req_item.get('relationship')
break
if rel and 'properties' in rel:
for key, value in rel['properties'].items():
rel['properties'][key] = functions.get_function(
self,
req,
value)
if node_template.get_capabilities_objects():
for cap in node_template.get_capabilities_objects():
if cap.get_properties_objects():
for prop in cap.get_properties_objects():
propvalue = functions.get_function(
self,
node_template,
prop.value)
if isinstance(propvalue, functions.GetInput):
propvalue = propvalue.result()
for p, v in cap._properties.items():
if p == prop.name:
cap._properties[p] = propvalue
for rel, node in node_template.relationships.items():
rel_tpls = node.relationship_tpl
if rel_tpls:
for rel_tpl in rel_tpls:
for interface in rel_tpl.interfaces:
if interface.inputs:
for name, value in interface.inputs.items():
interface.inputs[name] = \
functions.get_function(self,
rel_tpl,
value)
for output in self.outputs:
func = functions.get_function(self, self.outputs, output.value)
if isinstance(func, functions.GetAttribute):
output.attrs[output.VALUE] = func

View File

@ -1,150 +0,0 @@
# 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
import os
from translator.toscalib.common.exception import InvalidTemplateVersion
from translator.toscalib.common.exception import MissingRequiredFieldError
from translator.toscalib.common.exception import UnknownFieldError
from translator.toscalib.topology_template import TopologyTemplate
from translator.toscalib.tpl_relationship_graph import ToscaGraph
import translator.toscalib.utils.yamlparser
# TOSCA template key names
SECTIONS = (DEFINITION_VERSION, DEFAULT_NAMESPACE, TEMPLATE_NAME,
TOPOLOGY_TEMPLATE, TEMPLATE_AUTHOR, TEMPLATE_VERSION,
DESCRIPTION, IMPORTS, DSL_DEFINITIONS, NODE_TYPES,
RELATIONSHIP_TYPES, RELATIONSHIP_TEMPLATES,
CAPABILITY_TYPES, ARTIFACT_TYPES, DATATYPE_DEFINITIONS) = \
('tosca_definitions_version', 'tosca_default_namespace',
'template_name', 'topology_template', 'template_author',
'template_version', 'description', 'imports', 'dsl_definitions',
'node_types', 'relationship_types', 'relationship_templates',
'capability_types', 'artifact_types', 'datatype_definitions')
log = logging.getLogger("tosca.model")
YAML_LOADER = translator.toscalib.utils.yamlparser.load_yaml
class ToscaTemplate(object):
VALID_TEMPLATE_VERSIONS = ['tosca_simple_yaml_1_0']
'''Load the template data.'''
def __init__(self, path, parsed_params=None):
self.tpl = YAML_LOADER(path)
self.path = path
self.parsed_params = parsed_params
self._validate_field()
self.version = self._tpl_version()
self.relationship_types = self._tpl_relationship_types()
self.description = self._tpl_description()
self.topology_template = self._topology_template()
self.inputs = self._inputs()
self.relationship_templates = self._relationship_templates()
self.nodetemplates = self._nodetemplates()
self.outputs = self._outputs()
self.graph = ToscaGraph(self.nodetemplates)
def _topology_template(self):
return TopologyTemplate(self._tpl_topology_template(),
self._get_all_custom_defs(),
self.relationship_types,
self.parsed_params)
def _inputs(self):
return self.topology_template.inputs
def _nodetemplates(self):
return self.topology_template.nodetemplates
def _relationship_templates(self):
return self.topology_template.relationship_templates
def _outputs(self):
return self.topology_template.outputs
def _tpl_version(self):
return self.tpl[DEFINITION_VERSION]
def _tpl_description(self):
return self.tpl[DESCRIPTION].rstrip()
def _tpl_imports(self):
if IMPORTS in self.tpl:
return self.tpl[IMPORTS]
def _tpl_relationship_types(self):
return self._get_custom_types(RELATIONSHIP_TYPES)
def _tpl_relationship_templates(self):
topology_template = self._tpl_topology_template()
if RELATIONSHIP_TEMPLATES in topology_template.keys():
return topology_template[RELATIONSHIP_TEMPLATES]
else:
return None
def _tpl_topology_template(self):
return self.tpl.get(TOPOLOGY_TEMPLATE)
def _get_all_custom_defs(self):
types = [NODE_TYPES, CAPABILITY_TYPES, RELATIONSHIP_TYPES,
DATATYPE_DEFINITIONS]
custom_defs = {}
for type in types:
custom_def = self._get_custom_types(type)
if custom_def:
custom_defs.update(custom_def)
return custom_defs
def _get_custom_types(self, type_definition):
# Handle custom types defined in outer template file
custom_defs = {}
imports = self._tpl_imports()
if imports:
for definition in imports:
if os.path.isabs(definition):
def_file = definition
else:
tpl_dir = os.path.dirname(os.path.abspath(self.path))
def_file = os.path.join(tpl_dir, definition)
custom_type = YAML_LOADER(def_file)
outer_custom_types = custom_type.get(type_definition)
if outer_custom_types:
custom_defs.update(outer_custom_types)
# Handle custom types defined in current template file
inner_custom_types = self.tpl.get(type_definition) or {}
if inner_custom_types:
custom_defs.update(inner_custom_types)
return custom_defs
def _validate_field(self):
try:
version = self._tpl_version()
self._validate_version(version)
except KeyError:
raise MissingRequiredFieldError(what='Template',
required=DEFINITION_VERSION)
for name in self.tpl:
if name not in SECTIONS:
raise UnknownFieldError(what='Template', field=name)
def _validate_version(self, version):
if version not in self.VALID_TEMPLATE_VERSIONS:
raise InvalidTemplateVersion(
what=version,
valid_versions=', '. join(self.VALID_TEMPLATE_VERSIONS))

View File

@ -1,46 +0,0 @@
# 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.
class ToscaGraph(object):
'''Graph of Tosca Node Templates.'''
def __init__(self, nodetemplates):
self.nodetemplates = nodetemplates
self.vertices = {}
self._create()
def _create_vertex(self, node):
if node not in self.vertices:
self.vertices[node.name] = node
def _create_edge(self, node1, node2, relationship):
if node1 not in self.vertices:
self._create_vertex(node1)
self.vertices[node1.name]._add_next(node2,
relationship)
def vertex(self, node):
if node in self.vertices:
return self.vertices[node]
def __iter__(self):
return iter(self.vertices.values())
def _create(self):
for node in self.nodetemplates:
relation = node.relationships
if relation:
for rel, nodetpls in relation.items():
for tpl in self.nodetemplates:
if tpl.name == nodetpls.name:
self._create_edge(node, tpl, rel)
self._create_vertex(node)

View File

@ -1,22 +0,0 @@
# 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 gettext
import os
_localedir = os.environ.get('heat-translator'.upper() + '_LOCALEDIR')
_t = gettext.translation('heat-translator', localedir=_localedir,
fallback=True)
def _(msg):
return _t.gettext(msg)

View File

@ -1,154 +0,0 @@
# 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 collections
import dateutil.parser
import logging
import numbers
import re
import six
from translator.toscalib.common.exception import (
InvalidTOSCAVersionPropertyException)
from translator.toscalib.utils.gettextutils import _
log = logging.getLogger('tosca')
def str_to_num(value):
'''Convert a string representation of a number into a numeric type.'''
if isinstance(value, numbers.Number):
return value
try:
return int(value)
except ValueError:
return float(value)
def validate_number(value):
return str_to_num(value)
def validate_integer(value):
if not isinstance(value, int):
try:
value = int(value)
except Exception:
raise ValueError(_('"%s" is not an integer') % value)
return value
def validate_float(value):
if not isinstance(value, float):
raise ValueError(_('"%s" is not a float') % value)
return validate_number(value)
def validate_string(value):
if not isinstance(value, six.string_types):
raise ValueError(_('"%s" is not a string') % value)
return value
def validate_list(value):
if not isinstance(value, list):
raise ValueError(_('"%s" is not a list') % value)
return value
def validate_map(value):
if not isinstance(value, collections.Mapping):
raise ValueError(_('"%s" is not a map') % value)
return value
def validate_boolean(value):
if isinstance(value, bool):
return value
if isinstance(value, str):
normalised = value.lower()
if normalised in ['true', 'false']:
return normalised == 'true'
raise ValueError(_('"%s" is not a boolean') % value)
def validate_timestamp(value):
return dateutil.parser.parse(value)
class TOSCAVersionProperty(object):
VERSION_RE = re.compile('^(?P<major_version>([0-9][0-9]*))'
'(\.(?P<minor_version>([0-9][0-9]*)))?'
'(\.(?P<fix_version>([0-9][0-9]*)))?'
'(\.(?P<qualifier>([0-9A-Za-z]+)))?'
'(\-(?P<build_version>[0-9])*)?$')
def __init__(self, version):
self.version = str(version)
match = self.VERSION_RE.match(self.version)
if not match:
raise InvalidTOSCAVersionPropertyException(what=(self.version))
ver = match.groupdict()
if self.version in ['0', '0.0', '0.0.0']:
log.warning(_('Version assumed as not provided'))
self.version = None
self.minor_version = ver['minor_version']
self.major_version = ver['major_version']
self.fix_version = ver['fix_version']
self.qualifier = self._validate_qualifier(ver['qualifier'])
self.build_version = self._validate_build(ver['build_version'])
self._validate_major_version(self.major_version)
def _validate_major_version(self, value):
"""Validate major version
Checks if only major version is provided and assumes
minor version as 0.
Eg: If version = 18, then it returns version = '18.0'
"""
if self.minor_version is None and self.build_version is None and \
value != '0':
log.warning(_('Minor version assumed "0"'))
self.version = '.'.join([value, '0'])
return value
def _validate_qualifier(self, value):
"""Validate qualifier
TOSCA version is invalid if a qualifier is present without the
fix version or with all of major, minor and fix version 0s.
For example, the following versions are invalid
18.0.abc
0.0.0.abc
"""
if (self.fix_version is None and value) or \
(self.minor_version == self.major_version ==
self.fix_version == '0' and value):
raise InvalidTOSCAVersionPropertyException(what=(self.version))
return value
def _validate_build(self, value):
"""Validate build version
TOSCA version is invalid if build version is present without the
qualifier.
Eg: version = 18.0.0-1 is invalid.
"""
if not self.qualifier and value:
raise InvalidTOSCAVersionPropertyException(what=(self.version))
return value
def get_version(self):
return self.version

View File

@ -1,61 +0,0 @@
# 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 codecs
from collections import OrderedDict
import yaml
if hasattr(yaml, 'CSafeLoader'):
yaml_loader = yaml.CSafeLoader
else:
yaml_loader = yaml.SafeLoader
def load_yaml(path):
with codecs.open(path, encoding='utf-8', errors='strict') as f:
return yaml.load(f.read(), Loader=yaml_loader)
def simple_parse(tmpl_str):
try:
tpl = yaml.load(tmpl_str, Loader=yaml_loader)
except yaml.YAMLError as yea:
raise ValueError(yea)
else:
if tpl is None:
tpl = {}
return tpl
def ordered_load(stream, Loader=yaml.Loader, object_pairs_hook=OrderedDict):
class OrderedLoader(Loader):
pass
def construct_mapping(loader, node):
loader.flatten_mapping(node)
return object_pairs_hook(loader.construct_pairs(node))
OrderedLoader.add_constructor(
yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
construct_mapping)
return yaml.load(stream, OrderedLoader)
def simple_ordered_parse(tmpl_str):
try:
tpl = ordered_load(tmpl_str)
except yaml.YAMLError as yea:
raise ValueError(yea)
else:
if tpl is None:
tpl = {}
return tpl