Add support for Simple NFV Profile
* This patchset implements an extensions capability to allow the parser to easily support additional TOSCA profiles * The first supported extension is the TOSCA NFV profile Change-Id: I00606c8f0075c205da4bc221c3274e0921b630a8 Partially implements: blueprint tosca-nfv-support
This commit is contained in:
parent
3359884aaf
commit
16a300e3e7
@ -105,6 +105,18 @@ class URLException(TOSCAException):
|
||||
msg_fmt = _('%(what)s')
|
||||
|
||||
|
||||
class ToscaExtImportError(TOSCAException):
|
||||
msg_fmt = _('Unable to import extension "%(ext_name)s". '
|
||||
'Check to see that it exists and has no '
|
||||
'language definition errors.')
|
||||
|
||||
|
||||
class ToscaExtAttributeError(TOSCAException):
|
||||
msg_fmt = _('Missing attribute in extension "%(ext_name)s". '
|
||||
'Check to see that it has required attributes '
|
||||
'"%(attrs)s" defined.')
|
||||
|
||||
|
||||
class ExceptionCollector(object):
|
||||
|
||||
exceptions = []
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
import logging
|
||||
import os
|
||||
from toscaparser.extensions.exttools import ExtTools
|
||||
import toscaparser.utils.yamlparser
|
||||
|
||||
log = logging.getLogger('tosca')
|
||||
@ -113,3 +114,12 @@ class EntityType(object):
|
||||
inherited.update(value)
|
||||
value.update(inherited)
|
||||
return value
|
||||
|
||||
|
||||
def update_definitions(version):
|
||||
exttools = ExtTools()
|
||||
extension_defs_file = exttools.get_defs_file(version)
|
||||
|
||||
loader = toscaparser.utils.yamlparser.load_yaml
|
||||
|
||||
EntityType.TOSCA_DEF.update(loader(extension_defs_file))
|
||||
|
0
toscaparser/extensions/__init__.py
Normal file
0
toscaparser/extensions/__init__.py
Normal file
88
toscaparser/extensions/exttools.py
Normal file
88
toscaparser/extensions/exttools.py
Normal file
@ -0,0 +1,88 @@
|
||||
#
|
||||
# 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 importlib
|
||||
import logging
|
||||
import os
|
||||
|
||||
from toscaparser.common.exception import ToscaExtAttributeError
|
||||
from toscaparser.common.exception import ToscaExtImportError
|
||||
|
||||
log = logging.getLogger("tosca.model")
|
||||
|
||||
REQUIRED_ATTRIBUTES = ['VERSION', 'DEFS_FILE']
|
||||
|
||||
|
||||
class ExtTools(object):
|
||||
def __init__(self):
|
||||
self.EXTENSION_INFO = self._load_extensions()
|
||||
|
||||
def _load_extensions(self):
|
||||
'''Dynamically load all the extensions .'''
|
||||
extensions = {}
|
||||
|
||||
# Use the absolute path of the class path
|
||||
abs_path = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
extdirs = [e for e in os.listdir(abs_path) if
|
||||
not e.startswith('tests') and
|
||||
not e.endswith('.pyc') and not e.endswith('.py')]
|
||||
|
||||
for e in extdirs:
|
||||
log.info(e)
|
||||
extpath = abs_path + '/' + e
|
||||
# Grab all the extension files in the given path
|
||||
ext_files = [f for f in os.listdir(extpath) if f.endswith('.py')
|
||||
and not f.startswith('__init__')]
|
||||
|
||||
# For each module, pick out the target translation class
|
||||
for f in ext_files:
|
||||
log.info(f)
|
||||
ext_name = 'toscaparser/extensions/' + e + '/' + f.strip('.py')
|
||||
ext_name = ext_name.replace('/', '.')
|
||||
try:
|
||||
extinfo = importlib.import_module(ext_name)
|
||||
version = getattr(extinfo, 'VERSION')
|
||||
defs_file = extpath + '/' + getattr(extinfo, 'DEFS_FILE')
|
||||
|
||||
# Sections is an optional attribute
|
||||
sections = getattr(extinfo, 'SECTIONS', ())
|
||||
|
||||
extensions[version] = {'sections': sections,
|
||||
'defs_file': defs_file}
|
||||
except ImportError:
|
||||
raise ToscaExtImportError(ext_name=ext_name)
|
||||
except AttributeError:
|
||||
attrs = ', '.join(REQUIRED_ATTRIBUTES)
|
||||
raise ToscaExtAttributeError(ext_name=ext_name,
|
||||
attrs=attrs)
|
||||
|
||||
return extensions
|
||||
|
||||
def get_versions(self):
|
||||
return self.EXTENSION_INFO.keys()
|
||||
|
||||
def get_sections(self):
|
||||
sections = {}
|
||||
for version in self.EXTENSION_INFO.keys():
|
||||
sections[version] = self.EXTENSION_INFO[version]['sections']
|
||||
|
||||
return sections
|
||||
|
||||
def get_defs_file(self, version):
|
||||
versiondata = self.EXTENSION_INFO.get(version)
|
||||
|
||||
if versiondata:
|
||||
return versiondata.get('defs_file')
|
||||
else:
|
||||
return None
|
242
toscaparser/extensions/nfv/TOSCA_nfv_definition_1_0.yaml
Normal file
242
toscaparser/extensions/nfv/TOSCA_nfv_definition_1_0.yaml
Normal file
@ -0,0 +1,242 @@
|
||||
# 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 NFV Profile in YAML version
|
||||
# 1.0.0. It describes the definition for TOSCA NFV types including Node Type,
|
||||
# Relationship Type, Capability Type and Interfaces.
|
||||
##########################################################################
|
||||
tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0
|
||||
|
||||
##########################################################################
|
||||
# Node Type.
|
||||
# A Node Type is a reusable entity that defines the type of one or more
|
||||
# Node Templates.
|
||||
##########################################################################
|
||||
|
||||
tosca.nodes.nfv.VNF:
|
||||
derived_from: tosca.nodes.Root # Or should this be its own top - level type?
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: ID of this VNF
|
||||
vendor:
|
||||
type: string
|
||||
description: name of the vendor who generate this VNF
|
||||
version:
|
||||
type: version
|
||||
description: version of the software for this VNF
|
||||
requirements:
|
||||
- virtualLink:
|
||||
capability: tosca.capabilities.nfv.VirtualLinkable
|
||||
|
||||
tosca.nodes.nfv.VDU:
|
||||
derived_from: tosca.nodes.Compute
|
||||
capabilities:
|
||||
high_availability:
|
||||
type: tosca.capabilities.nfv.HA
|
||||
Virtualbinding:
|
||||
type: tosca.capabilities.nfv.VirtualBindable
|
||||
monitoring_parameter:
|
||||
type: tosca.capabilities.nfv.Metric
|
||||
requirements:
|
||||
- high_availability:
|
||||
capability: tosca.capabilities.nfv.HA
|
||||
relationship: tosca.relationships.nfv.HA
|
||||
occurrences: [ 0, 1 ]
|
||||
|
||||
tosca.nodes.nfv.CP:
|
||||
derived_from: tosca.nodes.network.Port
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
required: false
|
||||
requirements:
|
||||
- virtualLink:
|
||||
capability: tosca.capabilities.VirtualLinkable
|
||||
- virtualBinding:
|
||||
capability: tosca.capabilities.nfv.VirtualBindable
|
||||
attributes:
|
||||
IP_address:
|
||||
type: string
|
||||
required: false
|
||||
|
||||
tosca.nodes.nfv.VL:
|
||||
derived_from: tosca.nodes.network.Network
|
||||
properties:
|
||||
vendor:
|
||||
type: string
|
||||
required: true
|
||||
description: name of the vendor who generate this VL
|
||||
capabilities:
|
||||
virtual_linkable:
|
||||
type: tosca.capabilities.nfv.VirtualLinkable
|
||||
|
||||
tosca.nodes.nfv.VL.ELine:
|
||||
derived_from: tosca.nodes.nfv.VL
|
||||
capabilities:
|
||||
virtual_linkable:
|
||||
occurrences: 2
|
||||
|
||||
tosca.nodes.nfv.VL.ELAN:
|
||||
derived_from: tosca.nodes.nfv.VL
|
||||
|
||||
tosca.nodes.nfv.VL.ETree:
|
||||
derived_from: tosca.nodes.nfv.VL
|
||||
|
||||
tosca.nodes.nfv.FP:
|
||||
derived_from: tosca.nodes.Root
|
||||
properties:
|
||||
policy:
|
||||
type: string
|
||||
required: false
|
||||
description: name of the vendor who generate this VL
|
||||
requirements:
|
||||
forwarder:
|
||||
-capability: tosca.capabilities.nfv.Forwarder
|
||||
|
||||
##########################################################################
|
||||
# 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.nfv.VirtualLinksTo:
|
||||
derived_from: tosca.relationships.ConnectsTo
|
||||
valid_target_types: [ tosca.capabilities.nfv.VirtualLinkable ]
|
||||
|
||||
tosca.relationships.nfv.VirtualBindsTo:
|
||||
derived_from: tosca.relationships.ConnectsTo
|
||||
valid_target_types: [ tosca.capabilities.nfv.VirtualBindable ]
|
||||
|
||||
tosca.relationships.nfv.HA:
|
||||
derived_from: tosca.relationships.Root
|
||||
valid_target_types: [ tosca.capabilities.nfv.HA ]
|
||||
|
||||
tosca.relationships.nfv.Monitor:
|
||||
derived_from: tosca.relationships.ConnectsTo
|
||||
valid_target_types: [ tosca.capabilities.nfv.Metric ]
|
||||
|
||||
tosca.relationships.nfv. ForwardsTo:
|
||||
derived_from: tosca.relationships.root
|
||||
valid_target_types: [ tosca.capabilities.nfv.Forwarder]
|
||||
|
||||
##########################################################################
|
||||
# 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.nfv.VirtualLinkable:
|
||||
derived_from: tosca.capabilities.Root
|
||||
|
||||
tosca.capabilities.nfv.VirtualBindable:
|
||||
derived_from: tosca.capabilities.Root
|
||||
|
||||
tosca.capabilities.nfv.HA:
|
||||
derived_from: tosca.capabilities.Root
|
||||
valid_source_types: [ tosca.nodes.nfv.VDU ]
|
||||
|
||||
tosca.capabilities.nfv.HA.ActiveActive:
|
||||
derived_from: tosca.capabilities.nfv.HA
|
||||
|
||||
tosca.capabilities.nfv.HA.ActivePassive:
|
||||
derived_from: tosca.capabilities.nfv.HA
|
||||
|
||||
tosca.capabilities.nfv.Metric:
|
||||
derived_from: tosca.capabilities.Root
|
||||
|
||||
tosca.capabilities.nfv.Forwarder:
|
||||
derived_from: tosca.capabilities.Root
|
||||
|
||||
##########################################################################
|
||||
# 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.
|
||||
##########################################################################
|
||||
|
||||
##########################################################################
|
||||
# Data Type.
|
||||
# A Datatype is a complex data type declaration which contains other
|
||||
# complex or simple data types.
|
||||
##########################################################################
|
||||
|
||||
##########################################################################
|
||||
# Artifact Type.
|
||||
# An Artifact Type is a reusable entity that defines the type of one or more
|
||||
# files which Node Types or Node Templates can have dependent relationships
|
||||
# and used during operations such as during installation or deployment.
|
||||
##########################################################################
|
||||
|
||||
##########################################################################
|
||||
# Policy Type.
|
||||
# TOSCA Policy Types represent logical grouping of TOSCA nodes that have
|
||||
# an implied relationship and need to be orchestrated or managed together
|
||||
# to achieve some result.
|
||||
##########################################################################
|
||||
|
||||
##########################################################################
|
||||
# Group Type
|
||||
#
|
||||
##########################################################################
|
||||
tosca.groups.nfv.VNFFG:
|
||||
derived_from: tosca.groups.Root
|
||||
|
||||
properties:
|
||||
vendor:
|
||||
type: string
|
||||
required: true
|
||||
description: name of the vendor who generate this VNFFG
|
||||
|
||||
version:
|
||||
type: string
|
||||
required: true
|
||||
description: version of this VNFFG
|
||||
|
||||
number_of_endpoints:
|
||||
type: integer
|
||||
required: true
|
||||
description: count of the external endpoints included in this VNFFG
|
||||
|
||||
dependent_virtual_link:
|
||||
type: list
|
||||
entry_schema:
|
||||
type: string
|
||||
required: true
|
||||
description: Reference to a VLD used in this Forwarding Graph
|
||||
|
||||
connection_point:
|
||||
type: list
|
||||
entry_schema:
|
||||
type: string
|
||||
required: true
|
||||
description: Reference to Connection Points forming the VNFFG
|
||||
|
||||
constituent_vnfs:
|
||||
type: list
|
||||
entry_schema:
|
||||
type: string
|
||||
required: true
|
||||
description: Reference to a list of VNFD used in this VNF Forwarding Graph
|
||||
|
||||
targets:
|
||||
type: list
|
||||
entry_schema:
|
||||
type: string
|
||||
required: false
|
||||
description: list of Network Forwarding Path within the VNFFG
|
||||
|
||||
requirements:
|
||||
forwarder:
|
||||
-capability: tosca.capabilities.nfv.Forwarder
|
||||
|
0
toscaparser/extensions/nfv/__init__.py
Normal file
0
toscaparser/extensions/nfv/__init__.py
Normal file
17
toscaparser/extensions/nfv/nfv.py
Normal file
17
toscaparser/extensions/nfv/nfv.py
Normal file
@ -0,0 +1,17 @@
|
||||
# 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.
|
||||
|
||||
# VERSION and DEFS_FILE are required for all extensions
|
||||
|
||||
VERSION = 'tosca_simple_profile_for_nfv_1_0_0'
|
||||
|
||||
DEFS_FILE = "TOSCA_nfv_definition_1_0.yaml"
|
0
toscaparser/extensions/nfv/tests/__init__.py
Normal file
0
toscaparser/extensions/nfv/tests/__init__.py
Normal file
@ -0,0 +1,28 @@
|
||||
tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0
|
||||
|
||||
description: Template for deploying a single server with predefined properties.
|
||||
|
||||
topology_template:
|
||||
node_templates:
|
||||
VNF1:
|
||||
type: tosca.nodes.nfv.VNF
|
||||
properties:
|
||||
id: vnf1
|
||||
vendor: acmetelco
|
||||
version: 1.0
|
||||
|
||||
VDU1:
|
||||
type: tosca.nodes.nfv.VDU
|
||||
|
||||
CP1:
|
||||
type: tosca.nodes.nfv.CP
|
||||
properties:
|
||||
type: vPort
|
||||
requirements:
|
||||
- virtualLink: PrivateNetwork
|
||||
- virtualBinding: VDU1
|
||||
|
||||
PrivateNetwork:
|
||||
type: tosca.nodes.nfv.VL
|
||||
properties:
|
||||
vendor: ACME Networks
|
29
toscaparser/extensions/nfv/tests/test_tosca_nfv_tpl.py
Normal file
29
toscaparser/extensions/nfv/tests/test_tosca_nfv_tpl.py
Normal file
@ -0,0 +1,29 @@
|
||||
# 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 ToscaNFVTemplateTest(TestCase):
|
||||
|
||||
'''TOSCA NFV template.'''
|
||||
tosca_tpl = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"data/tosca_helloworld_nfv.yaml")
|
||||
tosca = ToscaTemplate(tosca_tpl)
|
||||
|
||||
def test_version(self):
|
||||
self.assertEqual(self.tosca.version,
|
||||
"tosca_simple_profile_for_nfv_1_0_0")
|
@ -465,8 +465,9 @@ class ToscaTemplateTest(TestCase):
|
||||
"data/test_multiple_validation_errors.yaml")
|
||||
self.assertRaises(exception.ValidationError, ToscaTemplate, tosca_tpl,
|
||||
None)
|
||||
err1_msg = _('The template version "tosca_simple_yaml_1" is invalid. '
|
||||
'Valid versions are "tosca_simple_yaml_1_0".')
|
||||
valid_versions = ', '.join(ToscaTemplate.VALID_TEMPLATE_VERSIONS)
|
||||
err1_msg = (_('The template version "tosca_simple_yaml_1" is invalid. '
|
||||
'Valid versions are "%s".') % valid_versions)
|
||||
exception.ExceptionCollector.assertExceptionMessage(
|
||||
exception.InvalidTemplateVersion, err1_msg)
|
||||
|
||||
|
@ -19,6 +19,8 @@ from toscaparser.common.exception import InvalidTemplateVersion
|
||||
from toscaparser.common.exception import MissingRequiredFieldError
|
||||
from toscaparser.common.exception import UnknownFieldError
|
||||
from toscaparser.common.exception import ValidationError
|
||||
from toscaparser.elements.entity_type import update_definitions
|
||||
from toscaparser.extensions.exttools import ExtTools
|
||||
import toscaparser.imports
|
||||
from toscaparser.prereq.csar import CSAR
|
||||
from toscaparser.topology_template import TopologyTemplate
|
||||
@ -38,7 +40,8 @@ SECTIONS = (DEFINITION_VERSION, DEFAULT_NAMESPACE, TEMPLATE_NAME,
|
||||
'template_version', 'description', 'imports', 'dsl_definitions',
|
||||
'node_types', 'relationship_types', 'relationship_templates',
|
||||
'capability_types', 'artifact_types', 'datatype_definitions')
|
||||
# Special key names
|
||||
|
||||
# Sections that are specific to individual template definitions
|
||||
SPECIAL_SECTIONS = (METADATA) = ('metadata')
|
||||
|
||||
log = logging.getLogger("tosca.model")
|
||||
@ -47,9 +50,16 @@ YAML_LOADER = toscaparser.utils.yamlparser.load_yaml
|
||||
|
||||
|
||||
class ToscaTemplate(object):
|
||||
exttools = ExtTools()
|
||||
|
||||
VALID_TEMPLATE_VERSIONS = ['tosca_simple_yaml_1_0']
|
||||
|
||||
VALID_TEMPLATE_VERSIONS.extend(exttools.get_versions())
|
||||
|
||||
ADDITIONAL_SECTIONS = {'tosca_simple_yaml_1_0': SPECIAL_SECTIONS}
|
||||
|
||||
ADDITIONAL_SECTIONS.update(exttools.get_sections())
|
||||
|
||||
'''Load the template data.'''
|
||||
def __init__(self, path, parsed_params=None, a_file=True):
|
||||
ExceptionCollector.start()
|
||||
@ -171,7 +181,8 @@ class ToscaTemplate(object):
|
||||
self.version = version
|
||||
|
||||
for name in self.tpl:
|
||||
if name not in SECTIONS and name not in SPECIAL_SECTIONS:
|
||||
if (name not in SECTIONS and
|
||||
name not in self.ADDITIONAL_SECTIONS.get(version, ())):
|
||||
ExceptionCollector.appendException(
|
||||
UnknownFieldError(what='Template', field=name))
|
||||
|
||||
@ -181,6 +192,9 @@ class ToscaTemplate(object):
|
||||
InvalidTemplateVersion(
|
||||
what=version,
|
||||
valid_versions=', '. join(self.VALID_TEMPLATE_VERSIONS)))
|
||||
else:
|
||||
if version != 'tosca_simple_yaml_1_0':
|
||||
update_definitions(version)
|
||||
|
||||
def _get_path(self, path):
|
||||
if path.lower().endswith('.yaml'):
|
||||
|
Loading…
Reference in New Issue
Block a user