TOSCA definition types for TOSCA library.
Create a TOSCA metamodel covering various TOSCA types including node type, relationship type, capabilities type, interfaces and properties. Also, a small change, renamed heat-translator subdir to 'translator' as tox doesn't like dash in the name. Change-Id: I59e496063f8f1d7fd8557278a690b65d2a400a43 Partially implements blueprint heat-translator-tosca
This commit is contained in:
parent
d4d826ef96
commit
0c1591bf15
@ -3,4 +3,4 @@
|
||||
# The list of modules to copy from oslo-incubator.git
|
||||
|
||||
# The base module to hold the copy of openstack.common
|
||||
base=heat-translator
|
||||
base=translator
|
@ -1,2 +1,3 @@
|
||||
pbr>=0.5.21,<1.0
|
||||
Babel>=0.9.6
|
||||
Babel>=0.9.6
|
||||
PyYAML>=3.1.0
|
14
setup.cfg
14
setup.cfg
@ -21,7 +21,7 @@ classifier =
|
||||
|
||||
[files]
|
||||
packages =
|
||||
heat-translator
|
||||
translator
|
||||
|
||||
[build_sphinx]
|
||||
source-dir = doc/source
|
||||
@ -32,15 +32,15 @@ all_files = 1
|
||||
upload-dir = doc/build/html
|
||||
|
||||
[compile_catalog]
|
||||
directory = heat-translator/locale
|
||||
domain = heat-translator
|
||||
directory = translator/locale
|
||||
domain = translator
|
||||
|
||||
[update_catalog]
|
||||
domain = heat-translator
|
||||
output_dir = heat-translator/locale
|
||||
input_file = heat-translator/locale/heat-translator.pot
|
||||
domain = translator
|
||||
output_dir = translator/locale
|
||||
input_file = translator/locale/translator.pot
|
||||
|
||||
[extract_messages]
|
||||
keywords = _ gettext ngettext l_ lazy_gettext
|
||||
mapping_file = babel.cfg
|
||||
output_file = heat-translator/locale/heat-translator.pot
|
||||
output_file = translator/locale/translator.pot
|
19
translator/__init__.py
Normal file
19
translator/__init__.py
Normal file
@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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 pbr.version
|
||||
|
||||
|
||||
__version__ = pbr.version.VersionInfo(
|
||||
'translator').version_string()
|
0
translator/toscalib/__init__.py
Normal file
0
translator/toscalib/__init__.py
Normal file
246
translator/toscalib/elements/TOSCA_definition.yaml
Normal file
246
translator/toscalib/elements/TOSCA_definition.yaml
Normal file
@ -0,0 +1,246 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
#
|
||||
# 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. It
|
||||
# describes the definition for TOSCA types including Node Type,
|
||||
# Relationship Type, Capability Type and Interfaces.
|
||||
##########################################################################
|
||||
|
||||
##########################################################################
|
||||
# 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.
|
||||
capabilities:
|
||||
feature: tosca.capabilities.Feature
|
||||
interfaces: [ tosca.interfaces.node.Lifecycle ]
|
||||
|
||||
tosca.nodes.Compute:
|
||||
derived_from: tosca.nodes.Root
|
||||
properties:
|
||||
num_cpus:
|
||||
required: no
|
||||
type: integer
|
||||
constraints:
|
||||
- greater_or_equal: 1
|
||||
description: >
|
||||
Number of (actual or virtual) CPUs associated with the Compute node.
|
||||
disk_size:
|
||||
required: no
|
||||
type: integer
|
||||
constraints:
|
||||
- greater_or_equal: 0
|
||||
description: >
|
||||
Size of the local disk, in Gigabytes (GB), available to applications
|
||||
running on the Compute node.
|
||||
mem_size:
|
||||
required: no
|
||||
type: integer
|
||||
constraints:
|
||||
- greater_or_equal: 0
|
||||
description: >
|
||||
Size of memory, in Megabytes (MB), available to applications running
|
||||
on the Compute node.
|
||||
os_arch:
|
||||
required: no
|
||||
default: x86_64
|
||||
type: string
|
||||
description: >
|
||||
The host Operating System (OS) architecture.
|
||||
os_type:
|
||||
required: yes
|
||||
type: string
|
||||
description: >
|
||||
The host Operating System (OS) type.
|
||||
os_distribution:
|
||||
required: no
|
||||
type: string
|
||||
description: >
|
||||
The host Operating System (OS) distribution. Examples of valid values
|
||||
for an “os_type” of “Linux” would include:
|
||||
debian, fedora, rhel and ubuntu.
|
||||
os_version:
|
||||
required: no
|
||||
type: integer
|
||||
description: >
|
||||
The host Operating System version.
|
||||
ip_address:
|
||||
required: no
|
||||
type: string
|
||||
description: >
|
||||
The primary IP address assigned by the cloud provider that applications
|
||||
may use to access the Compute node.
|
||||
capabilities:
|
||||
host:
|
||||
type: tosca.capabilities.Container
|
||||
|
||||
tosca.nodes.SoftwareComponent:
|
||||
derived_from: tosca.nodes.Root
|
||||
properties:
|
||||
version:
|
||||
required: no
|
||||
type: string
|
||||
description: >
|
||||
Software component version.
|
||||
requirements:
|
||||
- host: tosca.nodes.Compute
|
||||
|
||||
tosca.nodes.DBMS:
|
||||
derived_from: tosca.nodes.SoftwareComponent
|
||||
properties:
|
||||
dbms_port:
|
||||
required: no
|
||||
type: integer
|
||||
description: >
|
||||
The port the DBMS service will listen to for data and requests.
|
||||
dbms_root_password:
|
||||
required: yes
|
||||
type: string
|
||||
description: >
|
||||
The root password for the DBMS service.
|
||||
capabilities:
|
||||
host:
|
||||
type: tosca.capabilities.Container
|
||||
properties:
|
||||
containee_types: [tosca.nodes.Database]
|
||||
|
||||
tosca.nodes.Database:
|
||||
derived_from: tosca.nodes.Root
|
||||
properties:
|
||||
db_user:
|
||||
required: yes
|
||||
type: string
|
||||
description: >
|
||||
User account name for DB administration
|
||||
db_name:
|
||||
required: yes
|
||||
type: string
|
||||
description: >
|
||||
The name of the database.
|
||||
db_user:
|
||||
required: yes
|
||||
type: string
|
||||
description: >
|
||||
The user name of the DB user.
|
||||
db_password:
|
||||
required: yes
|
||||
type: string
|
||||
description: >
|
||||
The password for the DB user account
|
||||
requirements:
|
||||
- host: tosca.nodes.DBMS
|
||||
capabilities:
|
||||
database_endpoint:
|
||||
type: tosca.capabilities.Endpoint
|
||||
|
||||
tosca.nodes.WebServer:
|
||||
derived_from: tosca.nodes.SoftwareComponent
|
||||
capabilities:
|
||||
http_endpoint:
|
||||
type: tosca.capabilities.Endpoint
|
||||
https_endpoint:
|
||||
type: tosca.capabilities.Endpoint
|
||||
host:
|
||||
type: tosca.capabilities.Container
|
||||
properties:
|
||||
containee_types: [tosca.nodes.WebApplication]
|
||||
|
||||
tosca.nodes.WebApplication:
|
||||
derived_from: tosca.nodes.Root
|
||||
requirements:
|
||||
- host: tosca.nodes.WebServer
|
||||
|
||||
##########################################################################
|
||||
# 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:
|
||||
interfaces: [ tosca.interfaces.relationship.Configure ]
|
||||
|
||||
tosca.relationships.DependsOn:
|
||||
derived_from: tosca.relationships.Root
|
||||
valid_targets: [ tosca.capabilities.Feature ]
|
||||
|
||||
tosca.relationships.HostedOn:
|
||||
derived_from: tosca.relationships.DependsOn
|
||||
valid_targets: [ tosca.capabilities.Container ]
|
||||
|
||||
tosca.relationships.ConnectsTo:
|
||||
derived_from: tosca.relationships.DependsOn
|
||||
valid_targets: [ tosca.capabilities.Endpoint ]
|
||||
|
||||
##########################################################################
|
||||
# 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:
|
||||
|
||||
tosca.capabilities.Feature:
|
||||
derived_from: tosca.capabilities.Root
|
||||
|
||||
tosca.capabilities.Container:
|
||||
derived_from: tosca.capabilities.Feature
|
||||
|
||||
tosca.capabilities.Endpoint:
|
||||
derived_from: tosca.capabilities.Feature
|
||||
properties:
|
||||
protocol:
|
||||
type: string
|
||||
default: http
|
||||
port:
|
||||
type: integer
|
||||
constraints:
|
||||
- greater_or_equal: 1
|
||||
- less_or_equal: 65535
|
||||
secure:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
tosca.capabilities.DatabaseEndpoint:
|
||||
derived_from: tosca.capabilities.Endpoint
|
||||
|
||||
##########################################################################
|
||||
# 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:
|
||||
create:
|
||||
description: Basic lifecycle create operation.
|
||||
configure:
|
||||
description: Basic lifecycle configure operation.
|
||||
start:
|
||||
description: Basic lifecycle start operation.
|
||||
stop:
|
||||
description: Basic lifecycle stop operation.
|
||||
delete:
|
||||
description: Basic lifecycle delete operation.
|
||||
|
||||
tosca.interfaces.relationship.Configure:
|
||||
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.
|
0
translator/toscalib/elements/__init__.py
Normal file
0
translator/toscalib/elements/__init__.py
Normal file
54
translator/toscalib/elements/capabilitytype.py
Normal file
54
translator/toscalib/elements/capabilitytype.py
Normal file
@ -0,0 +1,54 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
#
|
||||
# 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.entitytype import EntityType
|
||||
from translator.toscalib.elements.properties import PropertyDef
|
||||
|
||||
|
||||
class CapabilityTypeDef(EntityType):
|
||||
'''TOSCA built-in capabilities type.'''
|
||||
|
||||
def __init__(self, name, ctype, ntype, properties):
|
||||
self.name = name
|
||||
self.type = ctype
|
||||
self.nodetype = ntype
|
||||
self.properties = properties
|
||||
self.defs = {}
|
||||
if ntype:
|
||||
self.defs = self.TOSCA_DEF[ctype]
|
||||
|
||||
@property
|
||||
def properties_def(self):
|
||||
'''Return a list of property objects.'''
|
||||
properties = []
|
||||
props = self.entity_value(self.defs, 'properties')
|
||||
if props:
|
||||
if isinstance(props, dict):
|
||||
for prop, schema in props.items():
|
||||
prop_val = None
|
||||
for k, v in schema.items():
|
||||
if k == 'default':
|
||||
prop_val = v
|
||||
properties.append(PropertyDef(prop, self.type,
|
||||
schema, prop_val))
|
||||
if self.properties:
|
||||
for prop, value in self.properties.items():
|
||||
properties.append(PropertyDef(prop, self.type, None, value))
|
||||
return properties
|
||||
|
||||
@property
|
||||
def parent_type(self):
|
||||
'''Return a capability this capability is derived from.'''
|
||||
return self.derived_from(self.defs)
|
102
translator/toscalib/elements/constraints.py
Normal file
102
translator/toscalib/elements/constraints.py
Normal file
@ -0,0 +1,102 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
#
|
||||
# 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 numbers
|
||||
from translator.toscalib.utils.gettextutils import _
|
||||
|
||||
|
||||
class Constraint(object):
|
||||
CONSTRAINTS = (EQUAL, GREATER_THAN,
|
||||
GREATER_OR_EQUAL, LESS_THAN, LESS_OR_EQUAL, IN_RANGE,
|
||||
VALID_VALUES, LENGTH, MIN_LENGHT, 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 __init__(self, propertyname, value, constraint):
|
||||
self.propertyname = propertyname
|
||||
self.value = value
|
||||
self.constraint = constraint
|
||||
|
||||
def validate(self):
|
||||
for key, value in self.constraint.items():
|
||||
if key == self.GREATER_OR_EQUAL:
|
||||
self.validate_greater_than(value)
|
||||
|
||||
def validate_equal(self):
|
||||
pass
|
||||
|
||||
def validate_greater_than(self, value):
|
||||
if self.value < value:
|
||||
raise ValueError(_("%(prop)s value requires to be "
|
||||
"greater than %(val)s")
|
||||
% {'prop': self.propertyname, 'val': value})
|
||||
|
||||
def validate_greater_or_equal(self):
|
||||
pass
|
||||
|
||||
def validate_less_than(self):
|
||||
pass
|
||||
|
||||
def validate_less_or_equal(self):
|
||||
pass
|
||||
|
||||
def validate_in_range(self):
|
||||
pass
|
||||
|
||||
def validate_valid_values(self):
|
||||
pass
|
||||
|
||||
def validate_length(self):
|
||||
pass
|
||||
|
||||
def validate_min_length(self):
|
||||
pass
|
||||
|
||||
def validate_max_length(self):
|
||||
pass
|
||||
|
||||
def validate_pattern(self):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def validate_integer(value):
|
||||
if not isinstance(value, (int, long)):
|
||||
raise TypeError(_('Value is not an integer for %s') % value)
|
||||
return Constraint.validate_number(value)
|
||||
|
||||
@staticmethod
|
||||
def validate_number(value):
|
||||
return Constraint.str_to_num(value)
|
||||
|
||||
@staticmethod
|
||||
def validate_string(value):
|
||||
if not isinstance(value, basestring):
|
||||
raise ValueError(_('Value must be a string %s') % value)
|
||||
return value
|
||||
|
||||
@staticmethod
|
||||
def validate_list(self, value):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
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)
|
44
translator/toscalib/elements/entitytype.py
Normal file
44
translator/toscalib/elements/entitytype.py
Normal file
@ -0,0 +1,44 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
#
|
||||
# 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.'''
|
||||
|
||||
'''TOSCA definition file.'''
|
||||
TOSCA_DEF_FILE = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"TOSCA_definition.yaml")
|
||||
|
||||
TOSCA_DEF = translator.toscalib.utils.yamlparser.load_yaml(TOSCA_DEF_FILE)
|
||||
|
||||
RELATIONSHIP_TYPE = (DEPENDSON, HOSTEDON, CONNECTSTO) = \
|
||||
('tosca.relationships.DependsOn',
|
||||
'tosca.relationships.HostedOn',
|
||||
'tosca.relationships.ConnectsTo')
|
||||
|
||||
def derived_from(self, defs):
|
||||
'''Return a type this type is derived from.'''
|
||||
return self.entity_value(defs, 'derived_from')
|
||||
|
||||
def entity_value(self, defs, key):
|
||||
if key in defs:
|
||||
return defs[key]
|
64
translator/toscalib/elements/interfaces.py
Normal file
64
translator/toscalib/elements/interfaces.py
Normal file
@ -0,0 +1,64 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
#
|
||||
# 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
|
||||
|
||||
SECTIONS = (LIFECYCLE, CONFIGURE) = \
|
||||
('tosca.interfaces.node.Lifecycle',
|
||||
'tosca.interfaces.relationship.Configure')
|
||||
|
||||
|
||||
class InterfacesDef(StatefulEntityType):
|
||||
'''TOSCA built-in interfaces type.'''
|
||||
|
||||
def __init__(self, ntype, interfacetype,
|
||||
tpl_name=None, name=None, value=None):
|
||||
self.nodetype = ntype
|
||||
self.tpl_name = tpl_name
|
||||
self.type = interfacetype
|
||||
self.name = name
|
||||
self.value = value
|
||||
self.implementation = None
|
||||
self.input = None
|
||||
self.defs = {}
|
||||
if ntype:
|
||||
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
|
||||
if i == 'input':
|
||||
self.input = j
|
||||
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
|
174
translator/toscalib/elements/nodetype.py
Normal file
174
translator/toscalib/elements/nodetype.py
Normal file
@ -0,0 +1,174 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
#
|
||||
# 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
|
||||
from translator.toscalib.elements.interfaces import InterfacesDef
|
||||
from translator.toscalib.elements.properties import PropertyDef
|
||||
from translator.toscalib.elements.relationshiptype import RelationshipType
|
||||
from translator.toscalib.elements.statefulentitytype import StatefulEntityType
|
||||
from translator.toscalib.utils.gettextutils import _
|
||||
|
||||
|
||||
SECTIONS = (DERIVED_FROM, PROPERTIES, REQUIREMENTS,
|
||||
INTERFACES, CAPABILITIES) = \
|
||||
('derived_from', 'properties', 'requirements', 'interfaces',
|
||||
'capabilities')
|
||||
|
||||
|
||||
class NodeType(StatefulEntityType):
|
||||
'''TOSCA built-in node type.'''
|
||||
|
||||
def __init__(self, ntype):
|
||||
super(NodeType, self).__init__()
|
||||
if ntype not in list(self.TOSCA_DEF.keys()):
|
||||
raise ValueError(_('Node type %(ntype)s is not a valid type.')
|
||||
% {'ntype': ntype})
|
||||
self.defs = self.TOSCA_DEF[ntype]
|
||||
self.type = ntype
|
||||
self.related = {}
|
||||
|
||||
@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 properties_def(self):
|
||||
'''Return a list of property definition objects.'''
|
||||
properties = []
|
||||
props = self._get_value(PROPERTIES)
|
||||
if props:
|
||||
for prop, schema in props.items():
|
||||
properties.append(PropertyDef(prop, self.type, schema))
|
||||
return properties
|
||||
|
||||
@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.requirements
|
||||
if requires is None:
|
||||
requires = self._get_value(REQUIREMENTS, None, True)
|
||||
if requires:
|
||||
for req in requires:
|
||||
for key, value in req.items():
|
||||
relation = self._get_relation(key, value)
|
||||
rtype = RelationshipType(relation)
|
||||
relatednode = NodeType(value)
|
||||
relationship[rtype] = relatednode
|
||||
return relationship
|
||||
|
||||
def _get_relation(self, key, ndtype):
|
||||
relation = None
|
||||
ntype = NodeType(ndtype)
|
||||
cap = ntype.capabilities
|
||||
for c in cap:
|
||||
if c.name == 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
|
||||
return relation
|
||||
|
||||
@property
|
||||
def capabilities(self):
|
||||
'''Return a list of capability objects.'''
|
||||
typecapabilities = []
|
||||
self.cap_prop = None
|
||||
self.cap_type = None
|
||||
caps = self._get_value(CAPABILITIES)
|
||||
if caps is None:
|
||||
caps = self._get_value(CAPABILITIES, None, True)
|
||||
if caps:
|
||||
cproperties = None
|
||||
for name, value in caps.items():
|
||||
ctype = value.get('type')
|
||||
if 'properties' in value:
|
||||
cproperties = value.get('properties')
|
||||
cap = CapabilityTypeDef(name, ctype,
|
||||
self.type, cproperties)
|
||||
typecapabilities.append(cap)
|
||||
return typecapabilities
|
||||
|
||||
@property
|
||||
def requirements(self):
|
||||
return self._get_value(REQUIREMENTS)
|
||||
|
||||
@property
|
||||
def interfaces(self):
|
||||
return self._get_value(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 == 'tosca.interfaces.node.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, 'tosca.interfaces.node.Lifecycle')
|
||||
ops = i.lifecycle_ops
|
||||
return ops
|
||||
|
||||
def get_capability(self, name):
|
||||
for key, value in self.capabilities:
|
||||
if key == name:
|
||||
return value
|
||||
|
||||
def get_capability_type(self, name):
|
||||
for key, value in self.get_capability(name):
|
||||
if key == type:
|
||||
return value
|
||||
|
||||
def _get_value(self, key, defs=None, parent=None):
|
||||
value = None
|
||||
if defs is None:
|
||||
defs = self.defs
|
||||
value = self.entity_value(defs, key)
|
||||
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 = self.entity_value(defs, key)
|
||||
p = p.parent_type
|
||||
return value
|
87
translator/toscalib/elements/properties.py
Normal file
87
translator/toscalib/elements/properties.py
Normal file
@ -0,0 +1,87 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
#
|
||||
# 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.constraints import Constraint
|
||||
|
||||
|
||||
class PropertyDef(object):
|
||||
'''TOSCA built-in Property type.'''
|
||||
|
||||
PROPERTY_KEYS = (
|
||||
TYPE, REQUIRED, DESCRIPTION, DEFAULT, CONSTRAINTS,
|
||||
) = (
|
||||
'type', 'required', 'description', 'default', 'constraints'
|
||||
)
|
||||
PROPERTIY_TYPES = (
|
||||
INTEGER,
|
||||
STRING, NUMBER, BOOLEAN,
|
||||
LIST
|
||||
) = (
|
||||
'integer',
|
||||
'string', 'number', 'boolean',
|
||||
'list'
|
||||
)
|
||||
|
||||
def __init__(self, name, nodetype, schema=None, value=None, tpl_name=None):
|
||||
self.name = name
|
||||
self.nodetype = nodetype
|
||||
self.schema = schema
|
||||
self.value = value
|
||||
self.tpl_name = tpl_name
|
||||
|
||||
@property
|
||||
def required(self):
|
||||
if self.schema:
|
||||
for prop_key, prop_vale in self.schema.items():
|
||||
if prop_key == self.REQUIRED and prop_vale:
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def constraints(self):
|
||||
if self.schema:
|
||||
if self.CONSTRAINTS in self.schema:
|
||||
return self.schema[self.CONSTRAINTS]
|
||||
|
||||
@property
|
||||
def description(self):
|
||||
if self.schema:
|
||||
if self.DESCRIPTION in self.schema:
|
||||
return self.schema[self.DESCRIPTION]
|
||||
return ''
|
||||
|
||||
def validate(self):
|
||||
'''Validate if not a reference property.'''
|
||||
if not isinstance(self.value, dict):
|
||||
self._validate_constraints()
|
||||
self._validate_datatype()
|
||||
|
||||
def _validate_datatype(self):
|
||||
if self.schema:
|
||||
dtype = self.schema[self.TYPE]
|
||||
if dtype == self.STRING:
|
||||
return Constraint.validate_string(self.value)
|
||||
elif dtype == self.INTEGER:
|
||||
return Constraint.validate_integer(self.value)
|
||||
elif dtype == self.NUMBER:
|
||||
return Constraint.validate_number(self.value)
|
||||
elif dtype == self.LIST:
|
||||
return Constraint.validate_list(self.value)
|
||||
|
||||
def _validate_constraints(self):
|
||||
constraints = self.constraints
|
||||
if constraints:
|
||||
for constraint in constraints:
|
||||
Constraint(self.name, self.value, constraint).validate()
|
34
translator/toscalib/elements/relationshiptype.py
Normal file
34
translator/toscalib/elements/relationshiptype.py
Normal file
@ -0,0 +1,34 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
#
|
||||
# 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):
|
||||
super(RelationshipType, self).__init__()
|
||||
self.defs = self.TOSCA_DEF[type]
|
||||
self.type = type
|
||||
|
||||
@property
|
||||
def valid_targets(self):
|
||||
return self.entity_value(self.defs, 'valid_targets')
|
||||
|
||||
@property
|
||||
def parent_type(self):
|
||||
'''Return a relationship this relationship is derived from.'''
|
||||
return self.derived_from(self.defs)
|
29
translator/toscalib/elements/statefulentitytype.py
Normal file
29
translator/toscalib/elements/statefulentitytype.py
Normal file
@ -0,0 +1,29 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
#
|
||||
# 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.entitytype import EntityType
|
||||
|
||||
|
||||
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']
|
13
translator/toscalib/tests/__init__.py
Normal file
13
translator/toscalib/tests/__init__.py
Normal file
@ -0,0 +1,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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.
|
53
translator/toscalib/tests/base.py
Normal file
53
translator/toscalib/tests/base.py
Normal file
@ -0,0 +1,53 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright 2010-2011 OpenStack Foundation
|
||||
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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 os
|
||||
|
||||
import fixtures
|
||||
import testtools
|
||||
|
||||
_TRUE_VALUES = ('True', 'true', '1', 'yes')
|
||||
|
||||
|
||||
class TestCase(testtools.TestCase):
|
||||
|
||||
"""Test case base class for all unit tests."""
|
||||
|
||||
def setUp(self):
|
||||
"""Run before each test method to initialize test environment."""
|
||||
|
||||
super(TestCase, self).setUp()
|
||||
test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
|
||||
try:
|
||||
test_timeout = int(test_timeout)
|
||||
except ValueError:
|
||||
# If timeout value is invalid do not set a timeout.
|
||||
test_timeout = 0
|
||||
if test_timeout > 0:
|
||||
self.useFixture(fixtures.Timeout(test_timeout, gentle=True))
|
||||
|
||||
self.useFixture(fixtures.NestedTempfile())
|
||||
self.useFixture(fixtures.TempHomeDir())
|
||||
|
||||
if os.environ.get('OS_STDOUT_CAPTURE') in _TRUE_VALUES:
|
||||
stdout = self.useFixture(fixtures.StringStream('stdout')).stream
|
||||
self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
|
||||
if os.environ.get('OS_STDERR_CAPTURE') in _TRUE_VALUES:
|
||||
stderr = self.useFixture(fixtures.StringStream('stderr')).stream
|
||||
self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
|
||||
|
||||
self.log_fixture = self.useFixture(fixtures.FakeLogger())
|
64
translator/toscalib/tests/test_toscadef.py
Normal file
64
translator/toscalib/tests/test_toscadef.py
Normal file
@ -0,0 +1,64 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
#
|
||||
# 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.nodetype import NodeType
|
||||
from translator.toscalib.tests.base import TestCase
|
||||
|
||||
compute_type = NodeType('tosca.nodes.Compute')
|
||||
component_type = NodeType('tosca.nodes.SoftwareComponent')
|
||||
|
||||
|
||||
class ToscaDefTest(TestCase):
|
||||
def test_type(self):
|
||||
self.assertEqual(compute_type.type, "tosca.nodes.Compute")
|
||||
self.assertRaises(ValueError, NodeType, 'tosca.nodes.Invalid')
|
||||
|
||||
def test_parent_type(self):
|
||||
self.assertEqual(compute_type.parent_type.type, "tosca.nodes.Root")
|
||||
|
||||
def test_capabilities(self):
|
||||
self.assertEqual(
|
||||
['tosca.capabilities.Container'],
|
||||
[c.type for c in compute_type.capabilities])
|
||||
|
||||
def test_properties_def(self):
|
||||
self.assertEqual(
|
||||
['disk_size', 'ip_address', 'mem_size',
|
||||
'num_cpus', 'os_arch', 'os_distribution',
|
||||
'os_type', 'os_version'],
|
||||
sorted([p.name for p in compute_type.properties_def]))
|
||||
self.assertTrue([p.required for p in compute_type.properties_def
|
||||
if p.name == 'os_type'])
|
||||
|
||||
def test_requirements(self):
|
||||
self.assertEqual(compute_type.requirements, None)
|
||||
self.assertEqual(
|
||||
[{'host': 'tosca.nodes.Compute'}],
|
||||
[r for r in component_type.requirements])
|
||||
|
||||
def test_relationship(self):
|
||||
self.assertEqual(
|
||||
[('tosca.relationships.HostedOn', 'tosca.nodes.Compute')],
|
||||
[(relation.type, node.type) for
|
||||
relation, node in component_type.relationship.items()])
|
||||
self.assertIn(
|
||||
('tosca.relationships.HostedOn', ['tosca.capabilities.Container']),
|
||||
[(relation.type, relation.valid_targets) for
|
||||
relation in list(component_type.relationship.keys())])
|
||||
|
||||
def test_interfaces(self):
|
||||
self.assertEqual(compute_type.interfaces, None)
|
||||
root_node = NodeType('tosca.nodes.Root')
|
||||
self.assertIn('tosca.interfaces.node.Lifecycle', root_node.interfaces)
|
0
translator/toscalib/utils/__init__.py
Normal file
0
translator/toscalib/utils/__init__.py
Normal file
25
translator/toscalib/utils/gettextutils.py
Normal file
25
translator/toscalib/utils/gettextutils.py
Normal file
@ -0,0 +1,25 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
#
|
||||
# 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)
|
@ -21,15 +21,6 @@ else:
|
||||
yaml_loader = yaml.SafeLoader
|
||||
|
||||
|
||||
class Loader(object):
|
||||
def __init__(self, file_name):
|
||||
self.file_name = file_name
|
||||
|
||||
def load(self):
|
||||
f = open(self.file_name, 'r')
|
||||
profile = f.read()
|
||||
try:
|
||||
doc = yaml.load(profile, Loader=yaml_loader)
|
||||
except yaml.YAMLError as error:
|
||||
raise ValueError(error)
|
||||
return doc
|
||||
def load_yaml(path):
|
||||
with open(path) as f:
|
||||
return yaml.load(f.read(), Loader=yaml_loader)
|
Loading…
x
Reference in New Issue
Block a user