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:
Sahdev Zala 2014-04-18 14:28:30 -05:00
parent d4d826ef96
commit 0c1591bf15
21 changed files with 1021 additions and 21 deletions

View File

@ -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

View File

@ -1,2 +1,3 @@
pbr>=0.5.21,<1.0
Babel>=0.9.6
Babel>=0.9.6
PyYAML>=3.1.0

View File

@ -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
View 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()

View File

View 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.

View File

View 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)

View 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)

View 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]

View 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

View 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

View 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()

View 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)

View 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']

View 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.

View 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())

View 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)

View File

View 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)

View File

@ -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)