Implement NSD Support - Add CRUD operations for NSD
Co-Authored-By: Dharmendra Kushwaha<dharmendra.kushwaha@nectechnologies.in> Partially-implements: blueprint nsd-support Change-Id: Iff51926ce9f3b96f83a51ef06b4b464e4696d777
This commit is contained in:
parent
53c1c0464b
commit
5f46c2b030
@ -41,3 +41,4 @@ tosca-parser>=0.7.0 # Apache-2.0
|
|||||||
heat-translator>=0.4.0 # Apache-2.0
|
heat-translator>=0.4.0 # Apache-2.0
|
||||||
cryptography!=1.3.0,>=1.0 # BSD/Apache-2.0
|
cryptography!=1.3.0,>=1.0 # BSD/Apache-2.0
|
||||||
paramiko>=2.0 # LGPLv2.1+
|
paramiko>=2.0 # LGPLv2.1+
|
||||||
|
python-mistralclient>=2.0.0 # Apache-2.0
|
||||||
|
@ -0,0 +1,73 @@
|
|||||||
|
# Copyright 2016 OpenStack Foundation
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""create of Network service tables
|
||||||
|
|
||||||
|
Revision ID: 0ad3bbce1c18
|
||||||
|
Revises: 0ae5b1ce3024
|
||||||
|
Create Date: 2016-12-17 19:41:01.906138
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '0ad3bbce1c18'
|
||||||
|
down_revision = '8f7145914cb0'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
from tacker.db import types
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade(active_plugins=None, options=None):
|
||||||
|
op.create_table('nsd',
|
||||||
|
sa.Column('tenant_id', sa.String(length=64), nullable=False),
|
||||||
|
sa.Column('id', types.Uuid(length=36), nullable=False),
|
||||||
|
sa.Column('created_at', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('updated_at', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('deleted_at', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('name', sa.String(length=255), nullable=False),
|
||||||
|
sa.Column('description', sa.Text(), nullable=True),
|
||||||
|
sa.Column('vnfds', types.Json, nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint('id'),
|
||||||
|
mysql_engine='InnoDB'
|
||||||
|
)
|
||||||
|
op.create_table('ns',
|
||||||
|
sa.Column('tenant_id', sa.String(length=64), nullable=False),
|
||||||
|
sa.Column('id', types.Uuid(length=36), nullable=False),
|
||||||
|
sa.Column('created_at', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('updated_at', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('deleted_at', sa.DateTime(), nullable=True),
|
||||||
|
sa.Column('nsd_id', types.Uuid(length=36), nullable=True),
|
||||||
|
sa.Column('vim_id', sa.String(length=64), nullable=False),
|
||||||
|
sa.Column('name', sa.String(length=255), nullable=False),
|
||||||
|
sa.Column('description', sa.Text(), nullable=True),
|
||||||
|
sa.Column('vnf_ids', sa.TEXT(length=65535), nullable=True),
|
||||||
|
sa.Column('mgmt_urls', sa.TEXT(length=65535), nullable=True),
|
||||||
|
sa.Column('status', sa.String(length=64), nullable=False),
|
||||||
|
sa.Column('error_reason', sa.Text(), nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(['nsd_id'], ['nsd.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id'),
|
||||||
|
mysql_engine='InnoDB'
|
||||||
|
)
|
||||||
|
op.create_table('nsd_attribute',
|
||||||
|
sa.Column('id', types.Uuid(length=36), nullable=False),
|
||||||
|
sa.Column('nsd_id', types.Uuid(length=36), nullable=False),
|
||||||
|
sa.Column('key', sa.String(length=255), nullable=False),
|
||||||
|
sa.Column('value', sa.TEXT(length=65535), nullable=True),
|
||||||
|
sa.ForeignKeyConstraint(['nsd_id'], ['nsd.id'], ),
|
||||||
|
sa.PrimaryKeyConstraint('id'),
|
||||||
|
mysql_engine='InnoDB'
|
||||||
|
)
|
@ -1 +1 @@
|
|||||||
8f7145914cb0
|
0ad3bbce1c18
|
||||||
|
@ -23,6 +23,7 @@ Based on this comparison database can be healed with healing migration.
|
|||||||
|
|
||||||
from tacker.db import model_base
|
from tacker.db import model_base
|
||||||
from tacker.db.nfvo import nfvo_db # noqa
|
from tacker.db.nfvo import nfvo_db # noqa
|
||||||
|
from tacker.db.nfvo import ns_db # noqa
|
||||||
from tacker.db.nfvo import vnffg_db # noqa
|
from tacker.db.nfvo import vnffg_db # noqa
|
||||||
from tacker.db.vnfm import vnfm_db # noqa
|
from tacker.db.vnfm import vnfm_db # noqa
|
||||||
|
|
||||||
|
192
tacker/db/nfvo/ns_db.py
Normal file
192
tacker/db/nfvo/ns_db.py
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
# 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 uuid
|
||||||
|
|
||||||
|
from oslo_log import log as logging
|
||||||
|
from oslo_utils import timeutils
|
||||||
|
|
||||||
|
import sqlalchemy as sa
|
||||||
|
from sqlalchemy import orm
|
||||||
|
|
||||||
|
from tacker.db.common_services import common_services_db
|
||||||
|
from tacker.db import db_base
|
||||||
|
from tacker.db import model_base
|
||||||
|
from tacker.db import models_v1
|
||||||
|
from tacker.db import types
|
||||||
|
from tacker.extensions.nfvo_plugins import network_service
|
||||||
|
from tacker.plugins.common import constants
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
_ACTIVE_UPDATE = (constants.ACTIVE, constants.PENDING_UPDATE)
|
||||||
|
_ACTIVE_UPDATE_ERROR_DEAD = (
|
||||||
|
constants.PENDING_CREATE, constants.ACTIVE, constants.PENDING_UPDATE,
|
||||||
|
constants.ERROR, constants.DEAD)
|
||||||
|
CREATE_STATES = (constants.PENDING_CREATE, constants.DEAD)
|
||||||
|
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
# db tables
|
||||||
|
|
||||||
|
class NSD(model_base.BASE, models_v1.HasId, models_v1.HasTenant,
|
||||||
|
models_v1.Audit):
|
||||||
|
"""Represents NSD to create NS."""
|
||||||
|
|
||||||
|
__tablename__ = 'nsd'
|
||||||
|
# Descriptive name
|
||||||
|
name = sa.Column(sa.String(255), nullable=False)
|
||||||
|
description = sa.Column(sa.Text)
|
||||||
|
vnfds = sa.Column(types.Json, nullable=True)
|
||||||
|
|
||||||
|
# (key, value) pair to spin up
|
||||||
|
attributes = orm.relationship('NSDAttribute',
|
||||||
|
backref='nsd')
|
||||||
|
|
||||||
|
|
||||||
|
class NSDAttribute(model_base.BASE, models_v1.HasId):
|
||||||
|
"""Represents attributes necessary for creation of ns in (key, value) pair
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
__tablename__ = 'nsd_attribute'
|
||||||
|
nsd_id = sa.Column(types.Uuid, sa.ForeignKey('nsd.id'),
|
||||||
|
nullable=False)
|
||||||
|
key = sa.Column(sa.String(255), nullable=False)
|
||||||
|
value = sa.Column(sa.TEXT(65535), nullable=True)
|
||||||
|
|
||||||
|
|
||||||
|
class NS(model_base.BASE, models_v1.HasId, models_v1.HasTenant,
|
||||||
|
models_v1.Audit):
|
||||||
|
"""Represents network services that deploys services.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
__tablename__ = 'ns'
|
||||||
|
nsd_id = sa.Column(types.Uuid, sa.ForeignKey('nsd.id'))
|
||||||
|
nsd = orm.relationship('NSD')
|
||||||
|
|
||||||
|
name = sa.Column(sa.String(255), nullable=False)
|
||||||
|
description = sa.Column(sa.Text, nullable=True)
|
||||||
|
|
||||||
|
# Dict of VNF details that network service launches
|
||||||
|
vnf_ids = sa.Column(sa.TEXT(65535), nullable=True)
|
||||||
|
|
||||||
|
# Dict of mgmt urls that network servic launches
|
||||||
|
mgmt_urls = sa.Column(sa.TEXT(65535), nullable=True)
|
||||||
|
|
||||||
|
status = sa.Column(sa.String(64), nullable=False)
|
||||||
|
vim_id = sa.Column(types.Uuid, sa.ForeignKey('vims.id'), nullable=False)
|
||||||
|
error_reason = sa.Column(sa.Text, nullable=True)
|
||||||
|
|
||||||
|
|
||||||
|
class NSPluginDb(network_service.NSPluginBase, db_base.CommonDbMixin):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(NSPluginDb, self).__init__()
|
||||||
|
self._cos_db_plg = common_services_db.CommonServicesPluginDb()
|
||||||
|
|
||||||
|
def _make_attributes_dict(self, attributes_db):
|
||||||
|
return dict((attr.key, attr.value) for attr in attributes_db)
|
||||||
|
|
||||||
|
def _make_nsd_dict(self, nsd, fields=None):
|
||||||
|
res = {
|
||||||
|
'attributes': self._make_attributes_dict(nsd['attributes']),
|
||||||
|
}
|
||||||
|
key_list = ('id', 'tenant_id', 'name', 'description',
|
||||||
|
'created_at', 'updated_at', 'vnfds')
|
||||||
|
res.update((key, nsd[key]) for key in key_list)
|
||||||
|
return self._fields(res, fields)
|
||||||
|
|
||||||
|
def create_nsd(self, context, nsd):
|
||||||
|
vnfds = nsd['vnfds']
|
||||||
|
nsd = nsd['nsd']
|
||||||
|
LOG.debug(_('nsd %s'), nsd)
|
||||||
|
tenant_id = self._get_tenant_id_for_create(context, nsd)
|
||||||
|
|
||||||
|
with context.session.begin(subtransactions=True):
|
||||||
|
nsd_id = str(uuid.uuid4())
|
||||||
|
nsd_db = NSD(
|
||||||
|
id=nsd_id,
|
||||||
|
tenant_id=tenant_id,
|
||||||
|
name=nsd.get('name'),
|
||||||
|
vnfds=vnfds,
|
||||||
|
description=nsd.get('description'))
|
||||||
|
context.session.add(nsd_db)
|
||||||
|
for (key, value) in nsd.get('attributes', {}).items():
|
||||||
|
attribute_db = NSDAttribute(
|
||||||
|
id=str(uuid.uuid4()),
|
||||||
|
nsd_id=nsd_id,
|
||||||
|
key=key,
|
||||||
|
value=value)
|
||||||
|
context.session.add(attribute_db)
|
||||||
|
|
||||||
|
LOG.debug(_('nsd_db %(nsd_db)s %(attributes)s '),
|
||||||
|
{'nsd_db': nsd_db,
|
||||||
|
'attributes': nsd_db.attributes})
|
||||||
|
nsd_dict = self._make_nsd_dict(nsd_db)
|
||||||
|
LOG.debug(_('nsd_dict %s'), nsd_dict)
|
||||||
|
self._cos_db_plg.create_event(
|
||||||
|
context, res_id=nsd_dict['id'],
|
||||||
|
res_type=constants.RES_TYPE_NSD,
|
||||||
|
res_state=constants.RES_EVT_ONBOARDED,
|
||||||
|
evt_type=constants.RES_EVT_CREATE,
|
||||||
|
tstamp=nsd_dict[constants.RES_EVT_CREATED_FLD])
|
||||||
|
return nsd_dict
|
||||||
|
|
||||||
|
def delete_nsd(self,
|
||||||
|
context,
|
||||||
|
nsd_id,
|
||||||
|
soft_delete=True):
|
||||||
|
with context.session.begin(subtransactions=True):
|
||||||
|
nss_db = context.session.query(NS).filter_by(
|
||||||
|
nsd_id=nsd_id).first()
|
||||||
|
if nss_db is not None and nss_db.deleted_at is None:
|
||||||
|
raise network_service.NSDInUse(
|
||||||
|
nsd_id=nsd_id)
|
||||||
|
|
||||||
|
nsd_db = self._get_resource(context, NSD,
|
||||||
|
nsd_id)
|
||||||
|
if soft_delete:
|
||||||
|
nsd_db.update({'deleted_at': timeutils.utcnow()})
|
||||||
|
self._cos_db_plg.create_event(
|
||||||
|
context, res_id=nsd_db['id'],
|
||||||
|
res_type=constants.RES_TYPE_NSD,
|
||||||
|
res_state=constants.RES_EVT_NA_STATE,
|
||||||
|
evt_type=constants.RES_EVT_DELETE,
|
||||||
|
tstamp=nsd_db[constants.RES_EVT_DELETED_FLD])
|
||||||
|
else:
|
||||||
|
context.session.query(NSDAttribute).filter_by(
|
||||||
|
nsd_id=nsd_id).delete()
|
||||||
|
context.session.delete(nsd_db)
|
||||||
|
|
||||||
|
def get_nsd(self, context, nsd_id, fields=None):
|
||||||
|
nsd_db = self._get_resource(context, NSD, nsd_id)
|
||||||
|
return self._make_nsd_dict(nsd_db)
|
||||||
|
|
||||||
|
def get_nsds(self, context, filters, fields=None):
|
||||||
|
return self._get_collection(context, NSD,
|
||||||
|
self._make_nsd_dict,
|
||||||
|
filters=filters, fields=fields)
|
||||||
|
|
||||||
|
# reference implementation. needs to be overrided by subclass
|
||||||
|
def create_ns(self, context, ns):
|
||||||
|
return {'nsd': {}}
|
||||||
|
|
||||||
|
# reference implementation. needs to be overrided by subclass
|
||||||
|
def delete_ns(self, context, ns_id, soft_delete=True):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_ns(self, context, ns_id, fields=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_nss(self, context, filters=None, fields=None):
|
||||||
|
pass
|
@ -18,6 +18,7 @@ import uuid
|
|||||||
|
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_utils import timeutils
|
from oslo_utils import timeutils
|
||||||
|
from oslo_utils import uuidutils
|
||||||
|
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
from sqlalchemy import orm
|
from sqlalchemy import orm
|
||||||
@ -156,7 +157,9 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin):
|
|||||||
|
|
||||||
def _get_resource(self, context, model, id):
|
def _get_resource(self, context, model, id):
|
||||||
try:
|
try:
|
||||||
return self._get_by_id(context, model, id)
|
if uuidutils.is_uuid_like(id):
|
||||||
|
return self._get_by_id(context, model, id)
|
||||||
|
return self._get_by_name(context, model, id)
|
||||||
except orm_exc.NoResultFound:
|
except orm_exc.NoResultFound:
|
||||||
if issubclass(model, VNFD):
|
if issubclass(model, VNFD):
|
||||||
raise vnfm.VNFDNotFound(vnfd_id=id)
|
raise vnfm.VNFDNotFound(vnfd_id=id)
|
||||||
@ -254,7 +257,7 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin):
|
|||||||
self._cos_db_plg.create_event(
|
self._cos_db_plg.create_event(
|
||||||
context, res_id=vnfd_dict['id'],
|
context, res_id=vnfd_dict['id'],
|
||||||
res_type=constants.RES_TYPE_VNFD,
|
res_type=constants.RES_TYPE_VNFD,
|
||||||
res_state=constants.RES_EVT_VNFD_ONBOARDED,
|
res_state=constants.RES_EVT_ONBOARDED,
|
||||||
evt_type=constants.RES_EVT_CREATE,
|
evt_type=constants.RES_EVT_CREATE,
|
||||||
tstamp=vnfd_dict[constants.RES_EVT_CREATED_FLD])
|
tstamp=vnfd_dict[constants.RES_EVT_CREATED_FLD])
|
||||||
return vnfd_dict
|
return vnfd_dict
|
||||||
@ -270,7 +273,7 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin):
|
|||||||
self._cos_db_plg.create_event(
|
self._cos_db_plg.create_event(
|
||||||
context, res_id=vnfd_dict['id'],
|
context, res_id=vnfd_dict['id'],
|
||||||
res_type=constants.RES_TYPE_VNFD,
|
res_type=constants.RES_TYPE_VNFD,
|
||||||
res_state=constants.RES_EVT_VNFD_NA_STATE,
|
res_state=constants.RES_EVT_NA_STATE,
|
||||||
evt_type=constants.RES_EVT_UPDATE,
|
evt_type=constants.RES_EVT_UPDATE,
|
||||||
tstamp=vnfd_dict[constants.RES_EVT_UPDATED_FLD])
|
tstamp=vnfd_dict[constants.RES_EVT_UPDATED_FLD])
|
||||||
return vnfd_dict
|
return vnfd_dict
|
||||||
@ -295,7 +298,7 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin):
|
|||||||
self._cos_db_plg.create_event(
|
self._cos_db_plg.create_event(
|
||||||
context, res_id=vnfd_db['id'],
|
context, res_id=vnfd_db['id'],
|
||||||
res_type=constants.RES_TYPE_VNFD,
|
res_type=constants.RES_TYPE_VNFD,
|
||||||
res_state=constants.RES_EVT_VNFD_NA_STATE,
|
res_state=constants.RES_EVT_NA_STATE,
|
||||||
evt_type=constants.RES_EVT_DELETE,
|
evt_type=constants.RES_EVT_DELETE,
|
||||||
tstamp=vnfd_db[constants.RES_EVT_DELETED_FLD])
|
tstamp=vnfd_db[constants.RES_EVT_DELETED_FLD])
|
||||||
else:
|
else:
|
||||||
|
@ -209,6 +209,9 @@ class ClassifierNotFoundException(exceptions.NotFound):
|
|||||||
message = _('Classifier %(classifier_id)s could not be found')
|
message = _('Classifier %(classifier_id)s could not be found')
|
||||||
|
|
||||||
|
|
||||||
|
class NSDInUse(exceptions.InUse):
|
||||||
|
message = _('NSD %(nsd_id)s is still in use')
|
||||||
|
|
||||||
RESOURCE_ATTRIBUTE_MAP = {
|
RESOURCE_ATTRIBUTE_MAP = {
|
||||||
|
|
||||||
'vims': {
|
'vims': {
|
||||||
@ -549,7 +552,152 @@ RESOURCE_ATTRIBUTE_MAP = {
|
|||||||
'allow_put': False,
|
'allow_put': False,
|
||||||
'is_visible': True,
|
'is_visible': True,
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
|
|
||||||
|
'nsds': {
|
||||||
|
'id': {
|
||||||
|
'allow_post': False,
|
||||||
|
'allow_put': False,
|
||||||
|
'validate': {'type:uuid': None},
|
||||||
|
'is_visible': True,
|
||||||
|
'primary_key': True,
|
||||||
|
},
|
||||||
|
'tenant_id': {
|
||||||
|
'allow_post': True,
|
||||||
|
'allow_put': False,
|
||||||
|
'validate': {'type:string': None},
|
||||||
|
'required_by_policy': True,
|
||||||
|
'is_visible': True,
|
||||||
|
},
|
||||||
|
'name': {
|
||||||
|
'allow_post': True,
|
||||||
|
'allow_put': True,
|
||||||
|
'validate': {'type:string': None},
|
||||||
|
'is_visible': True,
|
||||||
|
},
|
||||||
|
'description': {
|
||||||
|
'allow_post': True,
|
||||||
|
'allow_put': True,
|
||||||
|
'validate': {'type:string': None},
|
||||||
|
'is_visible': True,
|
||||||
|
'default': '',
|
||||||
|
},
|
||||||
|
'created_at': {
|
||||||
|
'allow_post': False,
|
||||||
|
'allow_put': False,
|
||||||
|
'is_visible': True,
|
||||||
|
},
|
||||||
|
'updated_at': {
|
||||||
|
'allow_post': False,
|
||||||
|
'allow_put': False,
|
||||||
|
'is_visible': True,
|
||||||
|
},
|
||||||
|
'attributes': {
|
||||||
|
'allow_post': True,
|
||||||
|
'allow_put': False,
|
||||||
|
'convert_to': attr.convert_none_to_empty_dict,
|
||||||
|
'validate': {'type:dict_or_nodata': None},
|
||||||
|
'is_visible': True,
|
||||||
|
'default': None,
|
||||||
|
},
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
'nss': {
|
||||||
|
'id': {
|
||||||
|
'allow_post': False,
|
||||||
|
'allow_put': False,
|
||||||
|
'validate': {'type:uuid': None},
|
||||||
|
'is_visible': True,
|
||||||
|
'primary_key': True,
|
||||||
|
},
|
||||||
|
'tenant_id': {
|
||||||
|
'allow_post': True,
|
||||||
|
'allow_put': False,
|
||||||
|
'validate': {'type:string': None},
|
||||||
|
'required_by_policy': True,
|
||||||
|
'is_visible': True,
|
||||||
|
},
|
||||||
|
'name': {
|
||||||
|
'allow_post': True,
|
||||||
|
'allow_put': True,
|
||||||
|
'validate': {'type:string': None},
|
||||||
|
'is_visible': True,
|
||||||
|
},
|
||||||
|
'description': {
|
||||||
|
'allow_post': True,
|
||||||
|
'allow_put': True,
|
||||||
|
'validate': {'type:string': None},
|
||||||
|
'is_visible': True,
|
||||||
|
'default': '',
|
||||||
|
},
|
||||||
|
'created_at': {
|
||||||
|
'allow_post': False,
|
||||||
|
'allow_put': False,
|
||||||
|
'is_visible': True,
|
||||||
|
},
|
||||||
|
'updated_at': {
|
||||||
|
'allow_post': False,
|
||||||
|
'allow_put': False,
|
||||||
|
'is_visible': True,
|
||||||
|
},
|
||||||
|
'vnf_ids': {
|
||||||
|
'allow_post': True,
|
||||||
|
'allow_put': False,
|
||||||
|
'validate': {'type:string': None},
|
||||||
|
'is_visible': True,
|
||||||
|
'default': '',
|
||||||
|
},
|
||||||
|
'nsd_id': {
|
||||||
|
'allow_post': True,
|
||||||
|
'allow_put': False,
|
||||||
|
'validate': {'type:uuid': None},
|
||||||
|
'is_visible': True,
|
||||||
|
},
|
||||||
|
'vim_id': {
|
||||||
|
'allow_post': True,
|
||||||
|
'allow_put': False,
|
||||||
|
'validate': {'type:string': None},
|
||||||
|
'is_visible': True,
|
||||||
|
'default': '',
|
||||||
|
},
|
||||||
|
'status': {
|
||||||
|
'allow_post': False,
|
||||||
|
'allow_put': False,
|
||||||
|
'is_visible': True,
|
||||||
|
},
|
||||||
|
'error_reason': {
|
||||||
|
'allow_post': False,
|
||||||
|
'allow_put': False,
|
||||||
|
'is_visible': True,
|
||||||
|
},
|
||||||
|
'created_at': {
|
||||||
|
'allow_post': False,
|
||||||
|
'allow_put': False,
|
||||||
|
'is_visible': True,
|
||||||
|
},
|
||||||
|
'updated_at': {
|
||||||
|
'allow_post': False,
|
||||||
|
'allow_put': False,
|
||||||
|
'is_visible': True,
|
||||||
|
},
|
||||||
|
'attributes': {
|
||||||
|
'allow_post': True,
|
||||||
|
'allow_put': False,
|
||||||
|
'convert_to': attr.convert_none_to_empty_dict,
|
||||||
|
'validate': {'type:dict_or_nodata': None},
|
||||||
|
'is_visible': True,
|
||||||
|
'default': None,
|
||||||
|
},
|
||||||
|
'mgmt_urls': {
|
||||||
|
'allow_post': False,
|
||||||
|
'allow_put': False,
|
||||||
|
'convert_to': attr.convert_none_to_empty_dict,
|
||||||
|
'validate': {'type:dict_or_nodata': None},
|
||||||
|
'is_visible': True,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
52
tacker/extensions/nfvo_plugins/network_service.py
Normal file
52
tacker/extensions/nfvo_plugins/network_service.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import abc
|
||||||
|
import six
|
||||||
|
|
||||||
|
from tacker.services import service_base
|
||||||
|
|
||||||
|
|
||||||
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
|
class NSPluginBase(service_base.NFVPluginBase):
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def create_nsd(self, context, nsd):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def delete_nsd(self, context, nsd_id):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_nsd(self, context, nsd_id, fields=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_nsds(self, context, filters=None, fields=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def create_ns(self, context, ns):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_nss(self, context, filters=None, fields=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def get_ns(self, context, ns_id, fields=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def delete_ns(self, context, ns_id):
|
||||||
|
pass
|
@ -149,6 +149,21 @@ class MetadataNotMatched(exceptions.InvalidInput):
|
|||||||
message = _("Metadata for alarm policy is not matched")
|
message = _("Metadata for alarm policy is not matched")
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidSubstitutionMapping(exceptions.InvalidInput):
|
||||||
|
message = _("Input for substitution mapping requirements are not"
|
||||||
|
" valid for %(requirement)s. They must be in the form"
|
||||||
|
" of list with two entries")
|
||||||
|
|
||||||
|
|
||||||
|
class SMRequirementMissing(exceptions.InvalidInput):
|
||||||
|
message = _("All the requirements for substitution_mappings are not"
|
||||||
|
" provided. Missing requirement for %(requirement)s")
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidParamsForSM(exceptions.InvalidInput):
|
||||||
|
message = _("Please provide parameters for substitution mappings")
|
||||||
|
|
||||||
|
|
||||||
def _validate_service_type_list(data, valid_values=None):
|
def _validate_service_type_list(data, valid_values=None):
|
||||||
if not isinstance(data, list):
|
if not isinstance(data, list):
|
||||||
msg = _("invalid data format for service list: '%s'") % data
|
msg = _("invalid data format for service list: '%s'") % data
|
||||||
|
@ -18,12 +18,15 @@ import os
|
|||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import uuid
|
import uuid
|
||||||
|
import yaml
|
||||||
|
|
||||||
from cryptography import fernet
|
from cryptography import fernet
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_utils import excutils
|
from oslo_utils import excutils
|
||||||
from oslo_utils import strutils
|
from oslo_utils import strutils
|
||||||
|
from tempfile import mkstemp
|
||||||
|
from toscaparser.tosca_template import ToscaTemplate
|
||||||
|
|
||||||
from tacker._i18n import _
|
from tacker._i18n import _
|
||||||
from tacker.common import driver_manager
|
from tacker.common import driver_manager
|
||||||
@ -32,6 +35,7 @@ from tacker.common import log
|
|||||||
from tacker.common import utils
|
from tacker.common import utils
|
||||||
from tacker import context as t_context
|
from tacker import context as t_context
|
||||||
from tacker.db.nfvo import nfvo_db
|
from tacker.db.nfvo import nfvo_db
|
||||||
|
from tacker.db.nfvo import ns_db
|
||||||
from tacker.db.nfvo import vnffg_db
|
from tacker.db.nfvo import vnffg_db
|
||||||
from tacker.extensions import nfvo
|
from tacker.extensions import nfvo
|
||||||
from tacker import manager
|
from tacker import manager
|
||||||
@ -48,7 +52,8 @@ def config_opts():
|
|||||||
return [('nfvo_vim', NfvoPlugin.OPTS)]
|
return [('nfvo_vim', NfvoPlugin.OPTS)]
|
||||||
|
|
||||||
|
|
||||||
class NfvoPlugin(nfvo_db.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin):
|
class NfvoPlugin(nfvo_db.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin,
|
||||||
|
ns_db.NSPluginDb):
|
||||||
"""NFVO reference plugin for NFVO extension
|
"""NFVO reference plugin for NFVO extension
|
||||||
|
|
||||||
Implements the NFVO extension and defines public facing APIs for VIM
|
Implements the NFVO extension and defines public facing APIs for VIM
|
||||||
@ -404,3 +409,74 @@ class NfvoPlugin(nfvo_db.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin):
|
|||||||
vim_auth=vim_obj['auth_cred'],
|
vim_auth=vim_obj['auth_cred'],
|
||||||
resource_type=resource,
|
resource_type=resource,
|
||||||
resource_name=name)
|
resource_name=name)
|
||||||
|
|
||||||
|
@log.log
|
||||||
|
def create_nsd(self, context, nsd):
|
||||||
|
nsd_data = nsd['nsd']
|
||||||
|
template = nsd_data['attributes'].get('nsd')
|
||||||
|
if isinstance(template, dict):
|
||||||
|
nsd_data['attributes']['nsd'] = yaml.safe_dump(
|
||||||
|
template)
|
||||||
|
LOG.debug(_('nsd %s'), nsd_data)
|
||||||
|
|
||||||
|
name = nsd_data['name']
|
||||||
|
if self._get_by_name(context, ns_db.NSD, name):
|
||||||
|
raise exceptions.DuplicateResourceName(resource='NSD', name=name)
|
||||||
|
|
||||||
|
self._parse_template_input(context, nsd)
|
||||||
|
return super(NfvoPlugin, self).create_nsd(
|
||||||
|
context, nsd)
|
||||||
|
|
||||||
|
def _parse_template_input(self, context, nsd):
|
||||||
|
nsd_dict = nsd['nsd']
|
||||||
|
nsd_yaml = nsd_dict['attributes'].get('nsd')
|
||||||
|
inner_nsd_dict = yaml.load(nsd_yaml)
|
||||||
|
nsd['vnfds'] = dict()
|
||||||
|
LOG.debug(_('nsd_dict: %s'), inner_nsd_dict)
|
||||||
|
|
||||||
|
vnfm_plugin = manager.TackerManager.get_service_plugins()['VNFM']
|
||||||
|
vnfd_imports = inner_nsd_dict['imports']
|
||||||
|
inner_nsd_dict['imports'] = []
|
||||||
|
new_files = []
|
||||||
|
for vnfd_name in vnfd_imports:
|
||||||
|
vnfd = vnfm_plugin.get_vnfd(context, vnfd_name)
|
||||||
|
# Copy VNF types and VNF names
|
||||||
|
sm_dict = yaml.load(vnfd['attributes']['vnfd'])[
|
||||||
|
'topology_template'][
|
||||||
|
'substitution_mappings']
|
||||||
|
nsd['vnfds'][sm_dict['node_type']] = vnfd['name']
|
||||||
|
# Ugly Hack to validate the child templates
|
||||||
|
# TODO(tbh): add support in tosca-parser to pass child
|
||||||
|
# templates as dict
|
||||||
|
fd, temp_path = mkstemp()
|
||||||
|
with open(temp_path, 'w') as fp:
|
||||||
|
fp.write(vnfd['attributes']['vnfd'])
|
||||||
|
os.close(fd)
|
||||||
|
new_files.append(temp_path)
|
||||||
|
inner_nsd_dict['imports'].append(temp_path)
|
||||||
|
# Prepend the tacker_defs.yaml import file with the full
|
||||||
|
# path to the file
|
||||||
|
toscautils.updateimports(inner_nsd_dict)
|
||||||
|
|
||||||
|
try:
|
||||||
|
ToscaTemplate(a_file=False,
|
||||||
|
yaml_dict_tpl=inner_nsd_dict)
|
||||||
|
except Exception as e:
|
||||||
|
LOG.exception(_("tosca-parser error: %s"), str(e))
|
||||||
|
raise nfvo.ToscaParserFailed(error_msg_details=str(e))
|
||||||
|
finally:
|
||||||
|
for file_path in new_files:
|
||||||
|
os.remove(file_path)
|
||||||
|
inner_nsd_dict['imports'] = vnfd_imports
|
||||||
|
|
||||||
|
if ('description' not in nsd_dict or
|
||||||
|
nsd_dict['description'] == ''):
|
||||||
|
nsd_dict['description'] = inner_nsd_dict.get(
|
||||||
|
'description', '')
|
||||||
|
if (('name' not in nsd_dict or
|
||||||
|
not len(nsd_dict['name'])) and
|
||||||
|
'metadata' in inner_nsd_dict):
|
||||||
|
nsd_dict['name'] = inner_nsd_dict['metadata'].get(
|
||||||
|
'template_name', '')
|
||||||
|
|
||||||
|
LOG.debug(_('nsd %s'), nsd)
|
||||||
|
@ -56,6 +56,7 @@ POLICY_ALARMING = 'tosca.policies.tacker.Alarming'
|
|||||||
DEFAULT_ALARM_ACTIONS = ['respawn', 'log', 'log_and_kill', 'notify']
|
DEFAULT_ALARM_ACTIONS = ['respawn', 'log', 'log_and_kill', 'notify']
|
||||||
|
|
||||||
RES_TYPE_VNFD = "vnfd"
|
RES_TYPE_VNFD = "vnfd"
|
||||||
|
RES_TYPE_NSD = "nsd"
|
||||||
RES_TYPE_VNF = "vnf"
|
RES_TYPE_VNF = "vnf"
|
||||||
RES_TYPE_VIM = "vim"
|
RES_TYPE_VIM = "vim"
|
||||||
|
|
||||||
@ -64,8 +65,8 @@ RES_EVT_DELETE = "DELETE"
|
|||||||
RES_EVT_UPDATE = "UPDATE"
|
RES_EVT_UPDATE = "UPDATE"
|
||||||
RES_EVT_MONITOR = "MONITOR"
|
RES_EVT_MONITOR = "MONITOR"
|
||||||
RES_EVT_SCALE = "SCALE"
|
RES_EVT_SCALE = "SCALE"
|
||||||
RES_EVT_VNFD_NA_STATE = "Not Applicable"
|
RES_EVT_NA_STATE = "Not Applicable"
|
||||||
RES_EVT_VNFD_ONBOARDED = "OnBoarded"
|
RES_EVT_ONBOARDED = "OnBoarded"
|
||||||
|
|
||||||
RES_EVT_CREATED_FLD = "created_at"
|
RES_EVT_CREATED_FLD = "created_at"
|
||||||
RES_EVT_DELETED_FLD = "deleted_at"
|
RES_EVT_DELETED_FLD = "deleted_at"
|
||||||
|
@ -37,14 +37,14 @@ class VnfdTestCreate(base.BaseTackerTest):
|
|||||||
vnfd_id = vnfd_instance['vnfd']['id']
|
vnfd_id = vnfd_instance['vnfd']['id']
|
||||||
self.verify_vnfd_events(
|
self.verify_vnfd_events(
|
||||||
vnfd_id, evt_constants.RES_EVT_CREATE,
|
vnfd_id, evt_constants.RES_EVT_CREATE,
|
||||||
evt_constants.RES_EVT_VNFD_ONBOARDED)
|
evt_constants.RES_EVT_ONBOARDED)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.client.delete_vnfd(vnfd_id)
|
self.client.delete_vnfd(vnfd_id)
|
||||||
except Exception:
|
except Exception:
|
||||||
assert False, "vnfd Delete failed"
|
assert False, "vnfd Delete failed"
|
||||||
self.verify_vnfd_events(vnfd_id, evt_constants.RES_EVT_DELETE,
|
self.verify_vnfd_events(vnfd_id, evt_constants.RES_EVT_DELETE,
|
||||||
evt_constants.RES_EVT_VNFD_NA_STATE)
|
evt_constants.RES_EVT_NA_STATE)
|
||||||
|
|
||||||
def test_tosca_vnfd(self):
|
def test_tosca_vnfd(self):
|
||||||
self._test_create_list_delete_tosca_vnfd('sample-tosca-vnfd.yaml',
|
self._test_create_list_delete_tosca_vnfd('sample-tosca-vnfd.yaml',
|
||||||
|
@ -33,7 +33,7 @@ class VnfmTestParam(base.BaseTackerTest):
|
|||||||
self.assertIsNotNone(vnfd_id)
|
self.assertIsNotNone(vnfd_id)
|
||||||
self.verify_vnfd_events(
|
self.verify_vnfd_events(
|
||||||
vnfd_id, evt_constants.RES_EVT_CREATE,
|
vnfd_id, evt_constants.RES_EVT_CREATE,
|
||||||
evt_constants.RES_EVT_VNFD_ONBOARDED)
|
evt_constants.RES_EVT_ONBOARDED)
|
||||||
return vnfd_instance
|
return vnfd_instance
|
||||||
|
|
||||||
def _test_vnfd_delete(self, vnfd_instance):
|
def _test_vnfd_delete(self, vnfd_instance):
|
||||||
@ -45,7 +45,7 @@ class VnfmTestParam(base.BaseTackerTest):
|
|||||||
except Exception:
|
except Exception:
|
||||||
assert False, "vnfd Delete failed"
|
assert False, "vnfd Delete failed"
|
||||||
self.verify_vnfd_events(vnfd_id, evt_constants.RES_EVT_DELETE,
|
self.verify_vnfd_events(vnfd_id, evt_constants.RES_EVT_DELETE,
|
||||||
evt_constants.RES_EVT_VNFD_NA_STATE)
|
evt_constants.RES_EVT_NA_STATE)
|
||||||
try:
|
try:
|
||||||
vnfd_d = self.client.show_vnfd(vnfd_id)
|
vnfd_d = self.client.show_vnfd(vnfd_id)
|
||||||
except Exception:
|
except Exception:
|
||||||
|
@ -41,6 +41,7 @@ vnfd_alarm_respawn_tosca_template = _get_template(
|
|||||||
'test_tosca_vnfd_alarm_respawn.yaml')
|
'test_tosca_vnfd_alarm_respawn.yaml')
|
||||||
vnfd_alarm_scale_tosca_template = _get_template(
|
vnfd_alarm_scale_tosca_template = _get_template(
|
||||||
'test_tosca_vnfd_alarm_scale.yaml')
|
'test_tosca_vnfd_alarm_scale.yaml')
|
||||||
|
nsd_tosca_template = yaml.load(_get_template('tosca_nsd_template.yaml'))
|
||||||
|
|
||||||
|
|
||||||
def get_dummy_vnfd_obj():
|
def get_dummy_vnfd_obj():
|
||||||
@ -177,3 +178,11 @@ def get_dummy_vnffg_obj_vnf_mapping():
|
|||||||
'VNF3': '7168062e-9fa1-4203-8cb7-f5c99ff3ee1b'
|
'VNF3': '7168062e-9fa1-4203-8cb7-f5c99ff3ee1b'
|
||||||
},
|
},
|
||||||
'symmetrical': False}}
|
'symmetrical': False}}
|
||||||
|
|
||||||
|
|
||||||
|
def get_dummy_nsd_obj():
|
||||||
|
return {'nsd': {'description': 'dummy nsd description',
|
||||||
|
'name': 'dummy_NSD',
|
||||||
|
'tenant_id': u'8819a1542a5948b68f94d4be0fd50496',
|
||||||
|
'template': {},
|
||||||
|
'attributes': {u'nsd': nsd_tosca_template}}}
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0
|
||||||
|
imports:
|
||||||
|
- VNF1
|
||||||
|
- VNF2
|
||||||
|
|
||||||
|
topology_template:
|
||||||
|
inputs:
|
||||||
|
vl1_name:
|
||||||
|
type: string
|
||||||
|
description: name of VL1 virtuallink
|
||||||
|
default: net_mgmt
|
||||||
|
vl2_name:
|
||||||
|
type: string
|
||||||
|
description: name of VL2 virtuallink
|
||||||
|
default: net0
|
||||||
|
|
||||||
|
node_templates:
|
||||||
|
VNF1:
|
||||||
|
type: tosca.nodes.nfv.VNF1
|
||||||
|
requirements:
|
||||||
|
- virtualLink1: VL1
|
||||||
|
- virtualLink2: VL2
|
||||||
|
|
||||||
|
VNF2:
|
||||||
|
type: tosca.nodes.nfv.VNF2
|
||||||
|
|
||||||
|
VL1:
|
||||||
|
type: tosca.nodes.nfv.VL
|
||||||
|
properties:
|
||||||
|
network_name: {get_input: vl1_name}
|
||||||
|
vendor: tacker
|
||||||
|
|
||||||
|
VL2:
|
||||||
|
type: tosca.nodes.nfv.VL
|
||||||
|
properties:
|
||||||
|
network_name: {get_input: vl2_name}
|
||||||
|
vendor: tacker
|
||||||
|
|
@ -69,7 +69,7 @@ class FakeVNFMPlugin(mock.Mock):
|
|||||||
elif {'name': ['VNF3']} in args:
|
elif {'name': ['VNF3']} in args:
|
||||||
return [{'id': self.vnf3_vnfd_id}]
|
return [{'id': self.vnf3_vnfd_id}]
|
||||||
else:
|
else:
|
||||||
return None
|
return []
|
||||||
|
|
||||||
def get_vnfs(self, *args, **kwargs):
|
def get_vnfs(self, *args, **kwargs):
|
||||||
if {'vnfd_id': [self.vnf1_vnfd_id]} in args:
|
if {'vnfd_id': [self.vnf1_vnfd_id]} in args:
|
||||||
@ -432,3 +432,13 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
|||||||
self._driver_manager.invoke.assert_called_with(mock.ANY, mock.ANY,
|
self._driver_manager.invoke.assert_called_with(mock.ANY, mock.ANY,
|
||||||
fc_id=mock.ANY,
|
fc_id=mock.ANY,
|
||||||
auth_attr=mock.ANY)
|
auth_attr=mock.ANY)
|
||||||
|
|
||||||
|
# def test_create_nsd(self):
|
||||||
|
# nsd_obj = utils.get_dummy_nsd_obj()
|
||||||
|
# with patch.object(TackerManager, 'get_service_plugins') as \
|
||||||
|
# mock_plugins:
|
||||||
|
# mock_plugins.return_value = {'VNFM': FakeVNFMPlugin()}
|
||||||
|
# mock.patch('tacker.common.driver_manager.DriverManager',
|
||||||
|
# side_effect=FakeDriverManager()).start()
|
||||||
|
# result = self.nfvo_plugin.create_nsd(self.context, nsd_obj)
|
||||||
|
# self.assertIsNotNone(result)
|
||||||
|
@ -226,7 +226,7 @@ class TestVNFMPlugin(db_base.SqlTestCase):
|
|||||||
mock_update_imports.assert_called_once_with(yaml_dict)
|
mock_update_imports.assert_called_once_with(yaml_dict)
|
||||||
self._cos_db_plugin.create_event.assert_called_once_with(
|
self._cos_db_plugin.create_event.assert_called_once_with(
|
||||||
self.context, evt_type=constants.RES_EVT_CREATE, res_id=mock.ANY,
|
self.context, evt_type=constants.RES_EVT_CREATE, res_id=mock.ANY,
|
||||||
res_state=constants.RES_EVT_VNFD_ONBOARDED,
|
res_state=constants.RES_EVT_ONBOARDED,
|
||||||
res_type=constants.RES_TYPE_VNFD, tstamp=mock.ANY)
|
res_type=constants.RES_TYPE_VNFD, tstamp=mock.ANY)
|
||||||
|
|
||||||
def test_create_vnfd_no_service_types(self):
|
def test_create_vnfd_no_service_types(self):
|
||||||
|
@ -289,6 +289,9 @@ class TOSCAToHOT(object):
|
|||||||
raise vnfm.ParamYAMLNotWellFormed(error_msg_details=str(e))
|
raise vnfm.ParamYAMLNotWellFormed(error_msg_details=str(e))
|
||||||
|
|
||||||
toscautils.updateimports(vnfd_dict)
|
toscautils.updateimports(vnfd_dict)
|
||||||
|
if 'substitution_mappings' in str(vnfd_dict):
|
||||||
|
toscautils.check_for_substitution_mappings(vnfd_dict,
|
||||||
|
parsed_params)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
tosca = tosca_template.ToscaTemplate(parsed_params=parsed_params,
|
tosca = tosca_template.ToscaTemplate(parsed_params=parsed_params,
|
||||||
|
@ -99,6 +99,38 @@ def updateimports(template):
|
|||||||
LOG.debug(_("%s"), path)
|
LOG.debug(_("%s"), path)
|
||||||
|
|
||||||
|
|
||||||
|
@log.log
|
||||||
|
def check_for_substitution_mappings(template, params):
|
||||||
|
sm_dict = params.get('substitution_mappings')
|
||||||
|
if not sm_dict:
|
||||||
|
raise vnfm.InvalidParamsForSM()
|
||||||
|
del params['substitution_mappings']
|
||||||
|
requirements = sm_dict.get('requirements')
|
||||||
|
if not requirements:
|
||||||
|
pass
|
||||||
|
node_tpl = template['topology_template']['node_templates']
|
||||||
|
req_dict_tpl = template['topology_template']['substitution_mappings'][
|
||||||
|
'requirements']
|
||||||
|
for req_name, req_val in iteritems(req_dict_tpl):
|
||||||
|
if req_name not in requirements:
|
||||||
|
raise vnfm.SMRequirementMissing(requirement=req_name)
|
||||||
|
if not isinstance(req_val, list):
|
||||||
|
raise vnfm.InvalidSubstitutionMapping(requirement=req_name)
|
||||||
|
try:
|
||||||
|
node_name = req_val[0]
|
||||||
|
node_req = req_val[1]
|
||||||
|
|
||||||
|
node_tpl[node_name]['requirements'].append({
|
||||||
|
node_req: {
|
||||||
|
'node': requirements[req_name]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
node_tpl[requirements[req_name]] = \
|
||||||
|
sm_dict[requirements[req_name]]
|
||||||
|
except Exception:
|
||||||
|
raise vnfm.InvalidSubstitutionMapping(requirement=req_name)
|
||||||
|
|
||||||
|
|
||||||
@log.log
|
@log.log
|
||||||
def get_vdu_monitoring(template):
|
def get_vdu_monitoring(template):
|
||||||
monitoring_dict = {}
|
monitoring_dict = {}
|
||||||
|
Loading…
Reference in New Issue
Block a user