summaryrefslogtreecommitdiffstats
path: root/tosca2heat
diff options
context:
space:
mode:
Diffstat (limited to 'tosca2heat')
-rw-r--r--tosca2heat/tosca-parser/toscaparser/elements/artifacttype.py14
-rw-r--r--tosca2heat/tosca-parser/toscaparser/elements/entity_type.py9
-rw-r--r--tosca2heat/tosca-parser/toscaparser/elements/nodetype.py4
-rw-r--r--tosca2heat/tosca-parser/toscaparser/elements/policytype.py11
-rw-r--r--tosca2heat/tosca-parser/toscaparser/elements/relationshiptype.py2
-rw-r--r--tosca2heat/tosca-parser/toscaparser/extensions/nfv/tests/data/vRNC/Definitions/rnc_definition.yaml157
-rw-r--r--tosca2heat/tosca-parser/toscaparser/extensions/nfv/tests/data/vRNC/Definitions/vRNC.yaml455
-rw-r--r--tosca2heat/tosca-parser/toscaparser/extensions/nfv/tests/data/vRNC/README.txt22
-rw-r--r--tosca2heat/tosca-parser/toscaparser/extensions/nfv/tests/data/vRNC/TOSCA-Metadata/TOSCA.meta4
-rw-r--r--tosca2heat/tosca-parser/toscaparser/extensions/nfv/tests/test_tosca_vRNC.py54
-rw-r--r--tosca2heat/tosca-parser/toscaparser/imports.py25
-rw-r--r--tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/subsystem.yaml3
-rw-r--r--tosca2heat/tosca-parser/toscaparser/tests/test_topology_template.py5
-rw-r--r--tosca2heat/tosca-parser/toscaparser/tests/test_toscadef.py22
-rw-r--r--tosca2heat/tosca-parser/toscaparser/tests/test_toscatpl.py6
-rw-r--r--tosca2heat/tosca-parser/toscaparser/tosca_template.py18
16 files changed, 783 insertions, 28 deletions
diff --git a/tosca2heat/tosca-parser/toscaparser/elements/artifacttype.py b/tosca2heat/tosca-parser/toscaparser/elements/artifacttype.py
index 3bfd7d0..887e99a 100644
--- a/tosca2heat/tosca-parser/toscaparser/elements/artifacttype.py
+++ b/tosca2heat/tosca-parser/toscaparser/elements/artifacttype.py
@@ -20,6 +20,7 @@ class ArtifactTypeDef(StatefulEntityType):
super(ArtifactTypeDef, self).__init__(atype, self.ARTIFACT_PREFIX,
custom_def)
self.type = atype
+ self.custom_def = custom_def
self.properties = None
if self.PROPERTIES in self.defs:
self.properties = self.defs[self.PROPERTIES]
@@ -27,17 +28,24 @@ class ArtifactTypeDef(StatefulEntityType):
def _get_parent_artifacts(self):
artifacts = {}
- parent_artif = self.parent_type
+ parent_artif = self.parent_type.type if self.parent_type else None
if parent_artif:
while parent_artif != 'tosca.artifacts.Root':
+ # only support normative artifact, shall be modified future
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)
+ '''Return a artifact entity from which this entity is derived.'''
+ if not hasattr(self, 'defs'):
+ return None
+ partifact_entity = self.derived_from(self.defs)
+ if partifact_entity:
+ return ArtifactTypeDef(partifact_entity, self.custom_def)
+ else:
+ return None
def get_artifact(self, name):
'''Return the definition of an artifact field by name.'''
diff --git a/tosca2heat/tosca-parser/toscaparser/elements/entity_type.py b/tosca2heat/tosca-parser/toscaparser/elements/entity_type.py
index 5d620a5..72e7e3f 100644
--- a/tosca2heat/tosca-parser/toscaparser/elements/entity_type.py
+++ b/tosca2heat/tosca-parser/toscaparser/elements/entity_type.py
@@ -106,8 +106,13 @@ class EntityType(object):
value[k] = v
if isinstance(value, list):
for p_value in parent_value:
- if p_value not in value:
- value.append(p_value)
+ if isinstance(p_value, dict):
+ if p_value.keys()[0] not in [
+ item.keys()[0] for item in value]:
+ value.append(p_value)
+ else:
+ if p_value not in value:
+ value.append(p_value)
else:
value = copy.copy(parent_value)
p = p.parent_type
diff --git a/tosca2heat/tosca-parser/toscaparser/elements/nodetype.py b/tosca2heat/tosca-parser/toscaparser/elements/nodetype.py
index 148d2b6..f5e4eb0 100644
--- a/tosca2heat/tosca-parser/toscaparser/elements/nodetype.py
+++ b/tosca2heat/tosca-parser/toscaparser/elements/nodetype.py
@@ -98,6 +98,10 @@ class NodeType(StatefulEntityType):
provided capability.
'''
+ # All types,include normative and custom types, here will
+ # be substituted because the global moification of TOSCA_DEF
+ self.TOSCA_DEF.update(self.custom_def)
+
# Filter the node types
node_types = [node_type for node_type in self.TOSCA_DEF.keys()
if node_type.startswith(self.NODE_PREFIX) and
diff --git a/tosca2heat/tosca-parser/toscaparser/elements/policytype.py b/tosca2heat/tosca-parser/toscaparser/elements/policytype.py
index 04cbab5..8fbb0f0 100644
--- a/tosca2heat/tosca-parser/toscaparser/elements/policytype.py
+++ b/tosca2heat/tosca-parser/toscaparser/elements/policytype.py
@@ -28,6 +28,7 @@ class PolicyType(StatefulEntityType):
super(PolicyType, self).__init__(ptype, self.POLICY_PREFIX,
custom_def)
self.type = ptype
+ self.custom_def = custom_def
self._validate_keys()
self.meta_data = None
@@ -55,7 +56,7 @@ class PolicyType(StatefulEntityType):
def _get_parent_policies(self):
policies = {}
- parent_policy = self.parent_type
+ parent_policy = self.parent_type.type if self.parent_type else None
if parent_policy:
while parent_policy != 'tosca.policies.Root':
policies[parent_policy] = self.TOSCA_DEF[parent_policy]
@@ -64,8 +65,12 @@ class PolicyType(StatefulEntityType):
@property
def parent_type(self):
- '''Return a policy this policy is derived from.'''
- return self.derived_from(self.defs)
+ '''Return a policy statefulentity of this node is derived from.'''
+ if not hasattr(self, 'defs'):
+ return None
+ ppolicy_entity = self.derived_from(self.defs)
+ if ppolicy_entity:
+ return PolicyType(ppolicy_entity, self.custom_def)
def get_policy(self, name):
'''Return the definition of a policy field by name.'''
diff --git a/tosca2heat/tosca-parser/toscaparser/elements/relationshiptype.py b/tosca2heat/tosca-parser/toscaparser/elements/relationshiptype.py
index 9462d38..25440ca 100644
--- a/tosca2heat/tosca-parser/toscaparser/elements/relationshiptype.py
+++ b/tosca2heat/tosca-parser/toscaparser/elements/relationshiptype.py
@@ -26,7 +26,7 @@ class RelationshipType(StatefulEntityType):
'''Return a relationship this reletionship is derived from.'''
prel = self.derived_from(self.defs)
if prel:
- return RelationshipType(prel)
+ return RelationshipType(prel, self.custom_def)
@property
def valid_target_types(self):
diff --git a/tosca2heat/tosca-parser/toscaparser/extensions/nfv/tests/data/vRNC/Definitions/rnc_definition.yaml b/tosca2heat/tosca-parser/toscaparser/extensions/nfv/tests/data/vRNC/Definitions/rnc_definition.yaml
new file mode 100644
index 0000000..c9d0901
--- /dev/null
+++ b/tosca2heat/tosca-parser/toscaparser/extensions/nfv/tests/data/vRNC/Definitions/rnc_definition.yaml
@@ -0,0 +1,157 @@
+## 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_definitions_version: tosca_simple_profile_for_nfv_1_0_0
+
+#metadata:
+# template_name: tosca_simple_profile_for_nfv_vRNC
+# template_author: opnfv_parser_project_from_zte
+# template_version: tosca_simple_profile_for_nfv_1_0
+
+# Optional description of the definitions inside the file.
+description: >
+ NFV TOSCA simple profile for RNC types
+ 1. Compute Node MM, CM, DM, LB...
+ 1.1 MM: MaintainModule;
+ 1.2 CM: Control Module;
+ 1.3 DM: Data Module;
+ 1.4 LB: LineCard Module.
+ 2. Network Node VL and CP
+
+# The import section shall be ignored if the value of tosca_definitions_version
+# is tosca_simple_profile_for_nfv_1_0_0, otherwise will be needed.
+
+# list of node type definitions
+node_types:
+ rnc.nodes.VNF:
+ derived_from: tosca.nodes.nfv.VNF
+ properties:
+ vnftype:
+ type: string
+ description: type of the RNC
+ default: UMTS
+ required: false
+ constraints:
+ - valid_values: [ TDS-CDMA, UMTS, CDMA ]
+ requirements:
+ - virtualLink_VNFM:
+ capability: tosca.capabilities.nfv.VirtualLinkable
+ relationship: tosca.relationships.nfv.VirtualLinksTo
+ node: rnc.nodes.VL
+ - virtualLink_EMS:
+ capability: tosca.capabilities.nfv.VirtualLinkable
+ relationship: tosca.relationships.nfv.VirtualLinksTo
+ node: rnc.nodes.VL
+ - virtualLink_TRAFFIC:
+ capability: tosca.capabilities.nfv.VirtualLinkable
+ relationship: tosca.relationships.nfv.VirtualLinksTo
+ node: rnc.nodes.VL
+
+ rnc.nodes.compute.MM:
+ derived_from: tosca.nodes.nfv.VDU
+ properties:
+ activestatus:
+ type: integer
+ description: 1 for active or 0 for passive
+ constraints:
+ - valid_values: [ 0, 1 ]
+ id:
+ type: string
+ defaule: MM
+ description: >
+ A identifier of this VDU within the scope of the VNFD,
+ including version functional description and other
+ identification information.
+
+ rnc.nodes.compute.CM:
+ derived_from: tosca.nodes.nfv.VDU
+ properties:
+ activestatus:
+ type: integer
+ description: 1 for active or 0 for passive
+ constraints:
+ - valid_values: [ 0, 1 ]
+
+ rnc.nodes.compute.DM:
+ derived_from: tosca.nodes.nfv.VDU
+
+ rnc.nodes.compute.LB:
+ derived_from: tosca.nodes.nfv.VDU
+
+ rnc.nodes.BlockStorage:
+ derived_from: tosca.nodes.BlockStorage
+
+ rnc.nodes.VL:
+ derived_from: tosca.nodes.nfv.VL
+
+ rnc.nodes.CP:
+ derived_from: tosca.nodes.nfv.CP
+
+ rnc.nodes.CP.MM:
+ derived_from: tosca.nodes.nfv.CP
+ # It's ok here because of the weakly validation.
+
+ rnc.nodes.CP.CM:
+ derived_from: tosca.nodes.nfv.CP
+ requirements:
+ - virtualLink:
+ capability: tosca.capabilities.nfv.VirtualLinkable
+ relationship: tosca.relationships.nfv.VirtualLinksTo
+ node: rnc.nodes.VL
+ - virtualBinding:
+ capability: tosca.capabilities.nfv.VirtualBindable
+ relationship: tosca.relationships.nfv.VirtualBindsTo
+ node: rnc.nodes.compute.CM
+
+ rnc.nodes.CP.DM:
+ derived_from: tosca.nodes.nfv.CP
+ requirements:
+ - virtualLink:
+ capability: tosca.capabilities.nfv.VirtualLinkable
+ relationship: tosca.relationships.nfv.VirtualLinksTo
+ node: rnc.nodes.VL
+ - virtualBinding:
+ capability: tosca.capabilities.nfv.VirtualBindable
+ relationship: tosca.relationships.nfv.VirtualBindsTo
+ node: rnc.nodes.compute.DM
+
+ rnc.nodes.CP.LB:
+ derived_from: tosca.nodes.nfv.CP
+ requirements:
+ - virtualLink:
+ capability: tosca.capabilities.nfv.VirtualLinkable
+ relationship: tosca.relationships.nfv.VirtualLinksTo
+ node: rnc.nodes.VL
+ - virtualBinding:
+ capability: tosca.capabilities.nfv.VirtualBindable
+ relationship: tosca.relationships.nfv.VirtualBindsTo
+ node: rnc.nodes.compute.LB
+
+# list of capability type definitions
+capability_types:
+ rnc.capabilities.Container:
+ derived_from: tosca.capabilities.Container
+ properties:
+ swap:
+ type: scalar-unit.size
+ description: swap info
+ required: false
+ default: 0
+ constraints:
+ - greater_or_equal: 0 MB
+ iops:
+ type: integer
+ description: IOPS for disk
+ required: false
+ default: 0
+ constraints:
+ - greater_than: 0
diff --git a/tosca2heat/tosca-parser/toscaparser/extensions/nfv/tests/data/vRNC/Definitions/vRNC.yaml b/tosca2heat/tosca-parser/toscaparser/extensions/nfv/tests/data/vRNC/Definitions/vRNC.yaml
new file mode 100644
index 0000000..2617b4d
--- /dev/null
+++ b/tosca2heat/tosca-parser/toscaparser/extensions/nfv/tests/data/vRNC/Definitions/vRNC.yaml
@@ -0,0 +1,455 @@
+## 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_definitions_version: tosca_simple_profile_for_nfv_1_0_0
+
+metadata:
+ template_name: tosca_simple_profile_for_nfv_vRNC
+ template_author: opnfv_parser_project_from_zte
+ template_version: tosca_simple_profile_for_nfv_1_0
+
+# Optional description of the definitions inside the file.
+description: >
+ TOSCA simple profile for RNC
+ 1. Compute Node MM, CM, DM, LB...
+ 1.1 MM: MaintainModule;
+ 1.2 CM: Control Module;
+ 1.3 DM: Data Module;
+ 1.4 LB: LineCard Module
+ 2. Network Node VL and CP
+
+imports:
+ - rnc_definition.yaml
+
+# list of YAML alias anchors (or macros)
+dsl_definitions:
+ compute_props_os_DEF: &compute_props_os_DEF
+ architecture: x86_64
+ type: Linux
+ distribution: Ubuntu
+ version: 14.10
+
+ compute_props_host_MM: &compute_props_host_MM
+ disk_size: 20 GB
+ num_cpus: 2
+ mem_size: 1024 MB
+
+ compute_props_host_CM: &compute_props_host_CM
+ disk_size: 0 GB
+ num_cpus: 2
+ mem_size: 1024 MB
+
+ compute_props_host_DM: &compute_props_host_DM
+ disk_size: 0 GB
+ num_cpus: 2
+ mem_size: 1024 MB
+
+ compute_props_host_LB: &compute_props_host_LB
+ disk_size: 0 GB
+ num_cpus: 2
+ mem_size: 1024 MB
+
+# topology template definition of the cloud application or service
+topology_template:
+ # a description of the topology template
+ description: >
+ simple RNC template
+
+ inputs:
+ mm_storage_size:
+ type: integer
+ default: 20 GB
+ description: mm additional block storage size
+ constraints:
+ - in_range: [ 1, 200 ]
+
+ substitution_mappings:
+ node_type: rnc.nodes.VNF
+ properties:
+ vnfmtype: UMTS
+ requirements:
+ virtualLink_VNFM: [ MM_Port_CTRL, virtualLink ]
+ virtualLink_EMS: [ MM_Port_EMS, virtualLink ]
+ virtualLink_TRAFFIC: [ LB_Port_EXTERMEDIA, virtualLink ]
+
+ # definition of the node templates of the topology
+ node_templates:
+ MM_Active:
+ type: rnc.nodes.compute.MM
+ properties:
+ activestatus: 1
+ id: MM_Active
+ capabilities:
+ os:
+ properties: *compute_props_os_DEF
+ host:
+ properties: *compute_props_host_MM
+ requirements:
+ - local_storage:
+ node: MM_BlockStorage
+ relationship: Storage_attachesto
+ - high_availability: MM_Passive
+ artifacts:
+ #the VM image of MM
+ vm_image: mm.image
+ interfaces:
+ Standard:
+ create:
+ implementation: mm_install.sh
+ configure:
+ implementation: mm_active_configure.sh
+
+ MM_Passive:
+ type: rnc.nodes.compute.MM
+ properties:
+ activestatus: 0
+ id: MM_Passive
+ capabilities:
+ os:
+ properties: *compute_props_os_DEF
+ host:
+ properties: *compute_props_host_MM
+ requirements:
+ - local_storage:
+ node: MM_BlockStorage
+ relationship: Storage_attachesto
+ - high_availability: MM_Active
+ artifacts:
+ #the VM image of MM
+ vm_image: mm.image
+ interfaces:
+ Standard:
+ create:
+ implementation: mm_install.sh
+ configure:
+ implementation: mm_passvie_configure.sh
+
+ CM_Active:
+ type: rnc.nodes.compute.CM
+ properties:
+ activestatus: 1
+ capabilities:
+ os:
+ properties: *compute_props_os_DEF
+ host:
+ properties: *compute_props_host_CM
+ scalable:
+ properties:
+ min_instances: 1
+ max_instances: 126
+ default_instances: 1
+ requirements:
+ - high_availability: CM_Passive
+ artifacts:
+ #the VM image of CM
+ vm_image: cm.image
+ interfaces:
+ Standard:
+ create:
+ implementation: cm_install.sh
+ configure:
+ implementation: cm_active_configure.sh
+
+ CM_Passive:
+ type: rnc.nodes.compute.CM
+ properties:
+ activestatus: 0
+ capabilities:
+ os:
+ properties: *compute_props_os_DEF
+ host:
+ properties: *compute_props_host_CM
+ scalable:
+ properties:
+ min_instances: 1
+ max_instances: 126
+ default_instances: 1
+ requirements:
+ - high_availability: CM_Active
+ artifacts:
+ #the VM image of CM
+ vm_image: mm.image
+ interfaces:
+ Standard:
+ create:
+ implementation: cm_install.sh
+ configure:
+ implementation: cm_passvie_configure.sh
+
+ DM:
+ type: rnc.nodes.compute.DM
+ capabilities:
+ os:
+ properties: *compute_props_os_DEF
+ host:
+ properties: *compute_props_host_DM
+ scalable:
+ properties:
+ min_instances: 1
+ max_instances: 120
+ default_instances: 1
+ artifacts:
+ vm_image: dm.image
+ interfaces:
+ Standard:
+ create:
+ implementation: dm_install.sh
+ configure:
+ implementation: dm_configure.sh
+
+ LB:
+ type: rnc.nodes.compute.LB
+ capabilities:
+ os:
+ properties: *compute_props_os_DEF
+ host:
+ properties: *compute_props_host_LB
+ scalable:
+ properties:
+ min_instances: 1
+ max_instances: 20
+ default_instances: 1
+ artifacts:
+ #the VM image of LB
+ vm_image: lb.image
+ interfaces:
+ Standard:
+ create:
+ implementation: lb_install.sh
+ configure:
+ implementation: lb_configure.sh
+
+ MM_BlockStorage:
+ type: rnc.nodes.BlockStorage
+ properties:
+ size: { get_input: mm_storage_size }
+ interfaces:
+ Configure:
+ post_configure_target:
+ implementation: default_script.sh
+
+ CTRL_Net:
+ type: rnc.nodes.VL
+ properties:
+ vendor: ZTE
+ cidr: "128.0.0.0/8"
+ network_name: Ctrl_Net
+ network_type: vlan
+ segmentation_id: 110
+ dhcp_enabled: false
+
+ INTERMEDIA_Net:
+ type: rnc.nodes.VL
+ properties:
+ vendor: ZTE
+ cidr: 10.0.0.0/8
+ start_ip: 10.1.0.1
+ end_ip: 10.1.2.254
+ network_name: InterMedia_Net
+ network_type: vlan
+ segmentation_id: 111
+ dhcp_enabled: false
+
+ EXTERMEDIA_Net:
+ type: rnc.nodes.VL
+ properties:
+ vendor: ZTE
+ cidr: 172.1.0.0/16
+ start_ip: 172.1.0.2
+ end_ip: 172.1.2.254
+ gateway_ip: 172.1.0.1
+ network_name: ExterMdedia_Net
+ network_type: vlan
+ segmentation_id: 100
+ dhcp_enabled: false
+
+ EMS_Net:
+ type: rnc.nodes.VL
+ properties:
+ vendor: ZTE
+ cidr: 129.0.0.0/24
+ start_ip: 129.0.0.2
+ end_ip: 129.0.0.64
+ gateway_ip: 129.0.0.1
+ network_name: Ems_Net
+ network_type: vlan
+ segmentation_id: 101
+ dhcp_enabled: false
+
+ MM_Port_EMS:
+ type: rnc.nodes.CP.MM
+ properties:
+ order: 0
+ is_default: true
+ requirements:
+ - virtualBinding: MM_Active
+ - virtualLink: EMS_Net
+
+ MM_Port_EMS:
+ type: rnc.nodes.CP.MM
+ properties:
+ order: 0
+ is_default: true
+ requirements:
+ - virtualBinding: MM_Active
+ - virtualLink: EMS_Net
+
+ MM_Port_CTRL:
+ type: rnc.nodes.CP.MM
+ properties:
+ order: 1
+ is_default: false
+ requirements:
+ - virtualBinding: MM_Active
+ - virtualLink: CTRL_Net
+
+ MM_Port_EXTERMEDIA:
+ type: rnc.nodes.CP.MM
+ properties:
+ order: 2
+ is_default: false
+ requirements:
+ - virtualBinding: MM_Active
+ - virtualLink: EXTERMEDIA_Net
+
+ CM_Port_CTRL:
+ type: rnc.nodes.CP.CM
+ properties:
+ order: 0
+ is_default: true
+ requirements:
+ - virtualBinding: CM_Active
+ - virtualLink: CTRL_Net
+
+ CM_Port_INTERMEDIA:
+ type: rnc.nodes.CP.CM
+ properties:
+ order: 1
+ is_default: false
+ requirements:
+ - virtualBinding: CM_Active
+ - virtualLink: INTERMEDIA_Net
+
+ DM_Port_CTRL:
+ type: rnc.nodes.CP.DM
+ properties:
+ order: 0
+ is_default: true
+ requirements:
+ - virtualBinding: DM
+ - virtualLink: CTRL_Net
+
+ DM_Port_INTERMEDIA:
+ type: rnc.nodes.CP.DM
+ properties:
+ order: 1
+ is_default: false
+ requirements:
+ - virtualBinding: DM
+ - virtualLink: INTERMEDIA_Net
+
+ LB_Port_CTRL:
+ type: rnc.nodes.CP.LB
+ properties:
+ order: 0
+ is_default: true
+ requirements:
+ - virtualBinding: LB
+ - virtualLink: CTRL_Net
+
+ LB_Port_INTERMEDIA:
+ type: rnc.nodes.CP.LB
+ properties:
+ order: 1
+ is_default: false
+ requirements:
+ - virtualBinding: LB
+ - virtualLink: INTERMEDIA_Net
+
+ LB_Port_EXTERMEDIA:
+ type: rnc.nodes.CP.LB
+ properties:
+ order: 2
+ is_default: false
+ requirements:
+ - virtualBinding: LB
+ - virtualLink: EXTERMEDIA_Net
+
+ # definition of the relationship templates of the topology
+ relationship_templates:
+ Storage_attachesto:
+ type: tosca.relationships.AttachesTo
+ properties:
+ location: /data_location
+
+ # definition of output parameters for the topology template
+ outputs:
+ private_ip_of_MM:
+ description: The private IP address of the MM.
+ value: { get_attribute: [ MM_Active, private_address ] }
+
+ private_ip_of_CM:
+ description: The private IP address of the CM.
+ value: { get_attribute: [ CM_Active, private_address ] }
+
+ private_ip_of_DM:
+ description: The private IP address of the DM.
+ value: { get_attribute: [ DM, private_address ] }
+
+ private_ip_of_LB:
+ description: The private IP address of the LB.
+ value: { get_attribute: [ LB, private_address ] }
+
+ # definition of logical groups of node templates within the topology
+ # To be continue about this section
+ groups:
+ AnitAffinityServerGroup:
+ type: tosca.groups.Root
+ description: >
+ Logical component grouping for anti affinity placement,
+ MM_Acitve, MM_Passive, CM_Acitve, CM_Passive, LB must host
+ on different host to reduce the impact to each other.
+ members: [ MM_Active, MM_Passive, CM_Active, CM_Passive, LB ]
+
+ AffinityServerGroup:
+ type: tosca.groups.Root
+ description: >
+ Logical component grouping for affinity placement,
+ CM and DM will be host on the same host to get high performence
+ members: [ CM_Active, DM ]
+
+ policies:
+ - AnitAffinityPolicy:
+ type: tosca.policies.Placement.Antilocate
+ description: Apply anti-locate placement policy to group
+ targets: [ AnitAffinityServerGroup ]
+
+ - AffinityPolicy:
+ type: tosca.policies.Placement.Colocate
+ description: Apply anti-locate placement policy to group
+ targets: [ AffinityServerGroup ]
+
+ # ServerGroupScaling_DM: # added future
+ # members: [ DM, ]# only one, will be error
+ # policies:
+ # - name: MyScaleUpPolicy
+ # - type: tosca.policy.scale.up | tosca.policy.scale.down
+ # - rule: fn.utilizaton [ DM ], greater_than: 80
+ # - trigger: script_dm
+
+ # ServerGroupScaling_LB: # added future
+ # members: [ LB, ] # only one, will be error
+ # policies:
+ # - name: MyScaleUpPolicy
+ # - type: tosca.policy.scale.up | tosca.policy.scale.down
+ # - rule: fn.utilizaton [ LB ], greater_than: 80
+ # - trigger: script_lb
diff --git a/tosca2heat/tosca-parser/toscaparser/extensions/nfv/tests/data/vRNC/README.txt b/tosca2heat/tosca-parser/toscaparser/extensions/nfv/tests/data/vRNC/README.txt
new file mode 100644
index 0000000..9ea77a4
--- /dev/null
+++ b/tosca2heat/tosca-parser/toscaparser/extensions/nfv/tests/data/vRNC/README.txt
@@ -0,0 +1,22 @@
+README:
+
+This CSAR contains all definitions that are required for deploying a simple
+vRNC(virtual Radio Network Controller) on a cloud.
+
+Entry information for processing through an orchestrator is contained in file
+TOSCA-Metadata/TOSCA.meta. This file provides high-level information such as
+CSAR version or creator of the CSAR. Furthermore, it provides pointers to the
+various TOSCA definitions files that contain the real details.
+The entry 'Entry-Definitions' points to the definitions file which holds the
+service template for the workload.
+'Entry-Definitions' is optional. An orchestrator can also process the contents
+like this:
+1) Read in and process each definitions file.
+2) For each definitions file:
+ 2.1) Read in all * type definitions (node types, capability types, etc.) and
+ store them in an internal map
+3) Verify and build dependencies (e.g. inheritance) between all type definitions
+ previously read in. Orchestrator built-in types (e.g. TOSCA base types) are
+ also considered in this step.
+4) Process the actual service template (the file with a node_templates section).
+ Validate using previously obtained type information. \ No newline at end of file
diff --git a/tosca2heat/tosca-parser/toscaparser/extensions/nfv/tests/data/vRNC/TOSCA-Metadata/TOSCA.meta b/tosca2heat/tosca-parser/toscaparser/extensions/nfv/tests/data/vRNC/TOSCA-Metadata/TOSCA.meta
new file mode 100644
index 0000000..45f9ab2
--- /dev/null
+++ b/tosca2heat/tosca-parser/toscaparser/extensions/nfv/tests/data/vRNC/TOSCA-Metadata/TOSCA.meta
@@ -0,0 +1,4 @@
+TOSCA-Meta-File-Version: 1.0
+CSAR-Version: 1.1
+Created-By: shang.xiaodog@zte.com.cn
+Entry-Definitions: Definitions/vRNC.yaml \ No newline at end of file
diff --git a/tosca2heat/tosca-parser/toscaparser/extensions/nfv/tests/test_tosca_vRNC.py b/tosca2heat/tosca-parser/toscaparser/extensions/nfv/tests/test_tosca_vRNC.py
new file mode 100644
index 0000000..46a5e29
--- /dev/null
+++ b/tosca2heat/tosca-parser/toscaparser/extensions/nfv/tests/test_tosca_vRNC.py
@@ -0,0 +1,54 @@
+# 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
+
+from toscaparser.tests.base import TestCase
+from toscaparser.tosca_template import ToscaTemplate
+
+
+class ToscaVRNCTemplateTest(TestCase):
+
+ '''NFV TOSCA vRNC template.'''
+ tosca_tpl = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ "data/vRNC/Definitions/vRNC.yaml")
+ tosca = ToscaTemplate(tosca_tpl)
+
+ def test_version(self):
+ self.assertEqual(self.tosca.version,
+ "tosca_simple_profile_for_nfv_1_0_0")
+
+ def test_input(self):
+ first_input_name = "mm_storage_size"
+ self.assertEqual(self.tosca.inputs[0].name, first_input_name)
+
+ def test_nodetemplates(self):
+ expected_node_list = sorted(
+ ["MM_Active", "MM_Passive", "MM_BlockStorage",
+ "CM_Active", "CM_Passive", "DM", "LB",
+ "EXTERMEDIA_Net", "INTERMEDIA_Net", "EMS_Net", "CTRL_Net",
+ "MM_Port_EMS", "MM_Port_CTRL", "MM_Port_EXTERMEDIA",
+ "CM_Port_CTRL", "CM_Port_INTERMEDIA",
+ "DM_Port_CTRL", "DM_Port_INTERMEDIA",
+ "LB_Port_INTERMEDIA", "LB_Port_EXTERMEDIA", "LB_Port_CTRL"])
+
+ node_list = sorted([node.name for node in self.tosca.nodetemplates])
+ self.assertEqual(node_list, expected_node_list)
+
+ def test_output(self):
+ expected_output_name = sorted(
+ ["private_ip_of_CM", "private_ip_of_DM",
+ "private_ip_of_LB", "private_ip_of_MM"])
+
+ output_list = sorted([output.name for output in self.tosca.outputs])
+ self.assertEqual(output_list, expected_output_name)
diff --git a/tosca2heat/tosca-parser/toscaparser/imports.py b/tosca2heat/tosca-parser/toscaparser/imports.py
index 5149382..62748bd 100644
--- a/tosca2heat/tosca-parser/toscaparser/imports.py
+++ b/tosca2heat/tosca-parser/toscaparser/imports.py
@@ -36,6 +36,7 @@ class ImportsLoader(object):
tpl=None):
self.importslist = importslist
self.custom_defs = {}
+ self.nested_topo_tpls = []
if not path and not tpl:
msg = _('Input tosca template is not provided.')
log.warning(msg)
@@ -55,6 +56,9 @@ class ImportsLoader(object):
def get_custom_defs(self):
return self.custom_defs
+ def get_nested_topo_tpls(self):
+ return self.nested_topo_tpls
+
def _validate_and_load_imports(self):
imports_names = set()
@@ -76,8 +80,8 @@ class ImportsLoader(object):
ValidationError(message=msg))
imports_names.add(import_name)
- custom_type = self._load_import_template(import_name,
- import_uri)
+ full_file_name, custom_type = self._load_import_template(
+ import_name, import_uri)
namespace_prefix = None
if isinstance(import_uri, dict):
namespace_prefix = import_uri.get(
@@ -86,13 +90,15 @@ class ImportsLoader(object):
TypeValidation(custom_type, import_def)
self._update_custom_def(custom_type, namespace_prefix)
else: # old style of imports
- custom_type = self._load_import_template(None,
- import_def)
+ full_file_name, custom_type = self._load_import_template(
+ None, import_def)
if custom_type:
TypeValidation(
custom_type, import_def)
self._update_custom_def(custom_type, None)
+ self._update_nested_topo_tpls(full_file_name, custom_type)
+
def _update_custom_def(self, custom_type, namespace_prefix):
outer_custom_types = {}
for type_def in self.type_definition_list:
@@ -112,6 +118,11 @@ class ImportsLoader(object):
else:
self.custom_defs.update(outer_custom_types)
+ def _update_nested_topo_tpls(self, full_file_name, custom_tpl):
+ if full_file_name and custom_tpl:
+ topo_tpl = {full_file_name: custom_tpl}
+ self.nested_topo_tpls.append(topo_tpl)
+
def _validate_import_keys(self, import_name, import_uri_def):
if self.FILE not in import_uri_def.keys():
log.warning(_('Missing keyname "file" in import "%(name)s".')
@@ -170,7 +181,7 @@ class ImportsLoader(object):
return
if toscaparser.utils.urlutils.UrlUtils.validate_url(file_name):
- return YAML_LOADER(file_name, False)
+ return file_name, YAML_LOADER(file_name, False)
elif not repository:
import_template = None
if self.path:
@@ -234,7 +245,7 @@ class ImportsLoader(object):
ImportError(_('Import "%s" is not valid.') %
import_uri_def))
return
- return YAML_LOADER(import_template, a_file)
+ return import_template, YAML_LOADER(import_template, a_file)
if short_import_notation:
log.error(_('Import "%(name)s" is not valid.') % import_uri_def)
@@ -261,7 +272,7 @@ class ImportsLoader(object):
return
if toscaparser.utils.urlutils.UrlUtils.validate_url(full_url):
- return YAML_LOADER(full_url, False)
+ return full_url, YAML_LOADER(full_url, False)
else:
msg = (_('repository url "%(n_uri)s" is not valid in import '
'definition "%(tpl)s".')
diff --git a/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/subsystem.yaml b/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/subsystem.yaml
index b27e698..99d645b 100644
--- a/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/subsystem.yaml
+++ b/tosca2heat/tosca-parser/toscaparser/tests/data/topology_template/subsystem.yaml
@@ -12,12 +12,15 @@ topology_template:
inputs:
mq_server_ip:
type: string
+ required: true
description: IP address of the message queuing server to receive messages from.
receiver_port:
type: string
+ required: true
description: Port to be used for receiving messages.
my_cpus:
type: integer
+ default: 2
description: Number of CPUs for the server.
constraints:
- valid_values: [ 1, 2, 4, 8 ]
diff --git a/tosca2heat/tosca-parser/toscaparser/tests/test_topology_template.py b/tosca2heat/tosca-parser/toscaparser/tests/test_topology_template.py
index 0f1a33e..cbd4e3b 100644
--- a/tosca2heat/tosca-parser/toscaparser/tests/test_topology_template.py
+++ b/tosca2heat/tosca-parser/toscaparser/tests/test_topology_template.py
@@ -34,6 +34,11 @@ class TopologyTemplateTest(TestCase):
self.topo = TopologyTemplate(self.topo_tpl,
self._get_all_custom_def())
+ self.tosca_system_tpl_path = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ "data/topology_template/system.yaml")
+ self.system_template = ToscaTemplate(self.tosca_system_tpl_path)
+
def _get_custom_def(self, type_definition):
custom_defs = {}
for definition in self.imports:
diff --git a/tosca2heat/tosca-parser/toscaparser/tests/test_toscadef.py b/tosca2heat/tosca-parser/toscaparser/tests/test_toscadef.py
index f0a87ac..7c29e67 100644
--- a/tosca2heat/tosca-parser/toscaparser/tests/test_toscadef.py
+++ b/tosca2heat/tosca-parser/toscaparser/tests/test_toscadef.py
@@ -188,8 +188,9 @@ class ToscaDefTest(TestCase):
self.assertIn(ifaces.LIFECYCLE_SHORTNAME, root_node.interfaces)
def test_artifacts(self):
+ self.assertEqual(artif_root_type.parent_type, None)
self.assertEqual('tosca.artifacts.Root',
- artif_file_type.parent_type)
+ artif_file_type.parent_type.type)
self.assertEqual({}, artif_file_type.parent_artifacts)
self.assertEqual(sorted(['tosca.artifacts.Root'],
key=lambda x: str(x)),
@@ -198,7 +199,7 @@ class ToscaDefTest(TestCase):
key=lambda x: str(x)))
self.assertEqual('tosca.artifacts.Implementation',
- artif_bash_type.parent_type)
+ artif_bash_type.parent_type.type)
self.assertEqual({'tosca.artifacts.Implementation':
{'derived_from': 'tosca.artifacts.Root',
'description':
@@ -212,7 +213,7 @@ class ToscaDefTest(TestCase):
key=lambda x: str(x)))
self.assertEqual('tosca.artifacts.Implementation',
- artif_python_type.parent_type)
+ artif_python_type.parent_type.type)
self.assertEqual({'tosca.artifacts.Implementation':
{'derived_from': 'tosca.artifacts.Root',
'description':
@@ -227,7 +228,7 @@ class ToscaDefTest(TestCase):
key=lambda x: str(x)))
self.assertEqual('tosca.artifacts.Deployment.Image',
- artif_container_docker_type.parent_type)
+ artif_container_docker_type.parent_type.type)
self.assertEqual({'tosca.artifacts.Deployment':
{'derived_from': 'tosca.artifacts.Root',
'description':
@@ -244,7 +245,7 @@ class ToscaDefTest(TestCase):
key=lambda x: str(x)))
self.assertEqual('tosca.artifacts.Deployment.Image',
- artif_vm_iso_type.parent_type)
+ artif_vm_iso_type.parent_type.type)
self.assertEqual({'tosca.artifacts.Deployment':
{'derived_from': 'tosca.artifacts.Root',
'description':
@@ -263,7 +264,7 @@ class ToscaDefTest(TestCase):
key=lambda x: str(x)))
self.assertEqual('tosca.artifacts.Deployment.Image',
- artif_vm_qcow2_type.parent_type)
+ artif_vm_qcow2_type.parent_type.type)
self.assertEqual({'tosca.artifacts.Deployment':
{'derived_from': 'tosca.artifacts.Root',
'description':
@@ -282,8 +283,9 @@ class ToscaDefTest(TestCase):
key=lambda x: str(x)))
def test_policies(self):
+ self.assertEqual(policy_root_type.parent_type, None)
self.assertEqual('tosca.policies.Root',
- policy_placement_type.parent_type)
+ policy_placement_type.parent_type.type)
self.assertEqual({}, policy_placement_type.parent_policies)
self.assertEqual(sorted(['tosca.policies.Root',
'The TOSCA Policy Type definition that is '
@@ -295,7 +297,7 @@ class ToscaDefTest(TestCase):
key=lambda x: str(x)))
self.assertEqual('tosca.policies.Root',
- policy_scaling_type.parent_type)
+ policy_scaling_type.parent_type.type)
self.assertEqual({}, policy_scaling_type.parent_policies)
self.assertEqual(sorted(['tosca.policies.Root',
'The TOSCA Policy Type definition that is '
@@ -307,7 +309,7 @@ class ToscaDefTest(TestCase):
key=lambda x: str(x)))
self.assertEqual('tosca.policies.Root',
- policy_update_type.parent_type)
+ policy_update_type.parent_type.type)
self.assertEqual({}, policy_update_type.parent_policies)
self.assertEqual(sorted(['tosca.policies.Root',
'The TOSCA Policy Type definition that is '
@@ -319,7 +321,7 @@ class ToscaDefTest(TestCase):
key=lambda x: str(x)))
self.assertEqual('tosca.policies.Root',
- policy_performance_type.parent_type)
+ policy_performance_type.parent_type.type)
self.assertEqual({}, policy_performance_type.parent_policies)
self.assertEqual(sorted(['tosca.policies.Root',
'The TOSCA Policy Type definition that is '
diff --git a/tosca2heat/tosca-parser/toscaparser/tests/test_toscatpl.py b/tosca2heat/tosca-parser/toscaparser/tests/test_toscatpl.py
index efc71fd..752e5de 100644
--- a/tosca2heat/tosca-parser/toscaparser/tests/test_toscatpl.py
+++ b/tosca2heat/tosca-parser/toscaparser/tests/test_toscatpl.py
@@ -224,6 +224,10 @@ class ToscaTemplateTest(TestCase):
for key in relation.keys():
rel_tpl = relation.get(key).get_relationship_template()
if rel_tpl:
+ self.assertEqual(
+ rel_tpl[0].type, "tosca.relationships.ConnectsTo")
+ self.assertTrue(rel_tpl[0].is_derived_from(
+ "tosca.relationships.Root"))
interfaces = rel_tpl[0].interfaces
for interface in interfaces:
self.assertEqual(config_interface,
@@ -741,5 +745,7 @@ class ToscaTemplateTest(TestCase):
"data/test_tosca_custom_rel_with_script.yaml")
tosca = ToscaTemplate(tosca_tpl)
rel = tosca.relationship_templates[0]
+ self.assertEqual(rel.type, "tosca.relationships.HostedOn")
+ self.assertTrue(rel.is_derived_from("tosca.relationships.Root"))
self.assertEqual(len(rel.interfaces), 1)
self.assertEqual(rel.interfaces[0].type, "Configure")
diff --git a/tosca2heat/tosca-parser/toscaparser/tosca_template.py b/tosca2heat/tosca-parser/toscaparser/tosca_template.py
index ba056da..1bad6e9 100644
--- a/tosca2heat/tosca-parser/toscaparser/tosca_template.py
+++ b/tosca2heat/tosca-parser/toscaparser/tosca_template.py
@@ -69,6 +69,7 @@ class ToscaTemplate(object):
self.input_path = None
self.path = None
self.tpl = None
+ self.nested_tosca_template = None
if path:
self.input_path = path
self.path = self._get_path(path)
@@ -177,9 +178,14 @@ class ToscaTemplate(object):
imports = self._tpl_imports()
if imports:
- custom_defs = toscaparser.imports.\
+ custom_service = toscaparser.imports.\
ImportsLoader(imports, self.path,
- type_defs, self.tpl).get_custom_defs()
+ type_defs, self.tpl)
+
+ nested_topo_tpls = custom_service.get_nested_topo_tpls()
+ self._handle_nested_topo_tpls(nested_topo_tpls)
+
+ custom_defs = custom_service.get_custom_defs()
if not custom_defs:
return
@@ -191,6 +197,14 @@ class ToscaTemplate(object):
custom_defs.update(inner_custom_types)
return custom_defs
+ def _handle_nested_topo_tpls(self, nested_topo_tpls):
+ for tpl in nested_topo_tpls:
+ if tpl.get(TOPOLOGY_TEMPLATE):
+ nested_tosca_template = ToscaTemplate(
+ path=self.path, parsed_params=self.parsed_params,
+ yaml_dict_tpl=nested_topo_tpls)
+ self.nested_tosca_template.apend(nested_tosca_template)
+
def _validate_field(self):
version = self._tpl_version()
if not version: