From: garciadeblas Date: Mon, 16 Dec 2019 16:24:03 +0000 (+0100) Subject: Merge branch 'master' into sol006 X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FIM.git;a=commitdiff_plain;h=9a55a153e26524e3cd051d3e97a03aff3f4dc8b6;hp=c900490e2342643eff668a8e93fcba0cfcdcbfb6 Merge branch 'master' into sol006 Change-Id: Iaa1a32bb76c06720e941b6d801da72b1b1ad9af4 Signed-off-by: garciadeblas --- diff --git a/.gitignore b/.gitignore index 3e381c6..893f025 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,16 @@ +# 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. + *.pyc .cache @@ -9,7 +22,6 @@ debian/osm-imdocs.install .eggs *egg-info *.gz -osm_im osm_im_trees dists pool @@ -18,6 +30,11 @@ dist osm-im-*.post* osm-imdocs-*.post* osm-imdocs_*.post* +osm_im/nsd.py +osm_im/vnfd.py +osm_im/nst.py +osm_im/nsi.py +osm_im/osm.yaml #Pyang and other tools' folders pyangbind diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..b804618 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +recursive-include models *.yang \ No newline at end of file diff --git a/Makefile b/Makefile index 7c41b11..e4e8fef 100644 --- a/Makefile +++ b/Makefile @@ -45,14 +45,10 @@ trees: $(YANG_DESC_TREES) $(YANG_DESC_JSTREES) $(YANG_RECORD_TREES) $(YANG_RECOR openapi_schemas: $(OPENAPI_SCHEMAS) -$(OUT_DIR): - $(Q)mkdir -p $(OUT_DIR) - $(Q)touch $(OUT_DIR)/__init__.py - $(TREES_DIR): $(Q)mkdir -p $(TREES_DIR) -%.py: $(OUT_DIR) yang-ietf +%.py: yang-ietf $(Q)echo generating $@ from $*.yang $(Q)pyang $(PYANG_OPTIONS) --path $(MODEL_DIR) --plugindir $(PYBINDPLUGIN) -f pybind -o $(OUT_DIR)/$@ $(MODEL_DIR)/$*.yang @@ -78,7 +74,7 @@ $(TREES_DIR): $(Q)sed -r -i 's|||g' $(TREES_DIR)/$@ $(Q)mv $(TREES_DIR)/$@ $(TREES_DIR)/$*.html -osm.yaml: $(OUT_DIR) yang-ietf yang2swagger +osm.yaml: yang-ietf yang2swagger $(Q)echo generating $@ $(Q)$(JAVA) -jar ${HOME}/.m2/repository/com/mrv/yangtools/swagger-generator-cli/1.1.11/swagger-generator-cli-1.1.11-executable.jar -yang-dir $(MODEL_DIR) -output $(OUT_DIR)/$@ @@ -108,4 +104,4 @@ deps: $(Q)cp -n ~/.m2/settings.xml{,.orig} ; wget -q -O - https://raw.githubusercontent.com/opendaylight/odlparent/master/settings.xml > ~/.m2/settings.xml clean: - $(Q)rm -rf dist osm_im.egg-info deb deb_dist *.gz yang2swagger $(OUT_DIR) $(TREES_DIR) + $(Q)rm -rf dist osm_im.egg-info deb deb_dist *.gz osm-imdocs* yang2swagger $(TREES_DIR) diff --git a/models/yang/mano-types.yang b/models/yang/mano-types.yang index a734822..a696550 100644 --- a/models/yang/mano-types.yang +++ b/models/yang/mano-types.yang @@ -176,7 +176,7 @@ module mano-types description "Name of the configuration primitive."; type string; - mandatory "true"; + mandatory true; } leaf user-defined-script { @@ -221,22 +221,36 @@ module mano-types } - grouping vca-relationships { - container vca-relationships { - list relation { - description "List of relations between VCA componets."; + grouping vca-relations { + list relation { + description "List of relations between elements in this descriptor."; + key "name"; + + leaf name { + description + "Name of the relation."; - key "requires provides"; + type string; + } + + list entities { + description + "List of two elements to be related. + Elements to be related are identified by a pair (id, endpoint). + The relation will relate (id1, endpoint1) to (id2, endpoint2)."; + key "id"; - leaf requires { + leaf id { description - "Name of the required relation."; + "A string, reference to the element id in the descriptor. + It could be a vnfd-id or a vdu-id in a VNFD, + or a nsd-id or member-vnf-index in a NSD."; type string; } - leaf provides { + leaf endpoint { description - "Name of the provided relation."; + "Endpoint name defining the relation."; type string; } } @@ -291,7 +305,6 @@ module mano-types type boolean; default true; } - uses manotypes:vca-relationships; } } } diff --git a/models/yang/nsd-base.yang b/models/yang/nsd-base.yang index 2eeabc5..70dd3eb 100644 --- a/models/yang/nsd-base.yang +++ b/models/yang/nsd-base.yang @@ -559,6 +559,7 @@ module nsd-base "Information about NS configuration."; uses manotypes:vca-configuration; + uses manotypes:vca-relations; } uses manotypes:input-parameter-xpath; diff --git a/models/yang/nsr.yang b/models/yang/nsr.yang index bce46e0..49a44e3 100644 --- a/models/yang/nsr.yang +++ b/models/yang/nsr.yang @@ -189,7 +189,7 @@ module nsr description "Name of the primitive."; type string; - mandatory "true"; + mandatory true; } leaf user-defined-script { diff --git a/models/yang/vnfd-base.yang b/models/yang/vnfd-base.yang index eb81021..38bede6 100644 --- a/models/yang/vnfd-base.yang +++ b/models/yang/vnfd-base.yang @@ -176,6 +176,7 @@ module vnfd-base container vnf-configuration { uses manotypes:vca-configuration; + uses manotypes:vca-relations; uses manotypes:vca-config-access; } @@ -567,12 +568,12 @@ module vnfd-base leaf mac-address { description - "MAC address of the interface. - Some VNFs require a specific MAC address to be configured - in the interface. While this is not recommended at all in - NFV environments, this parameter exists to allow those - scenarios. - This parameter will be likely deprecated in the future."; + "MAC address of the interface. + Some VNFs require a specific MAC address to be configured + in the interface. While this is not recommended at all in + NFV environments, this parameter exists to allow those + scenarios. + This parameter will be likely deprecated in the future."; type string; } @@ -580,19 +581,19 @@ module vnfd-base case internal { leaf internal-connection-point-ref { description - "Leaf Ref to the particular internal connection point"; + "Leaf Ref to the particular internal connection point"; type leafref { - path "../../internal-connection-point/id"; - } + path "../../internal-connection-point/id"; + } } } case external { leaf external-connection-point-ref { description - "Leaf Ref to the particular external connection point"; + "Leaf Ref to the particular external connection point"; type leafref { - path "../../../connection-point/name"; - } + path "../../../connection-point/name"; + } } } } @@ -613,6 +614,118 @@ module vnfd-base } } + list kdu { + description "List of K8s Deployment Units"; + key "name"; + + leaf name { + description "Unique name for the KDU"; + type string; + } + + leaf description { + description "Description of the KDU."; + type string; + } + + container kdu-configuration { + uses manotypes:vca-configuration; + uses manotypes:vca-config-access; + + leaf-list blacklist-config-primitive { + description + "List of blacklisted config primitives from the list of + default kdu config primitives"; + + type enumeration { + enum upgrade; + enum rollback; + } + + } + + } + + choice kdu-model { + description + "Indicates the KDU model, either as a helm-chart or as a juju-bundle."; + + case helm-chart { + leaf helm-chart { + description + "Helm chart that models the KDU, in any of the following ways: + - / + - + - + - + "; + type string; + } + } + + case juju-bundle { + leaf juju-bundle { + description + "Juju bundle that models the KDU, in any of the following ways: + - / + - + - + - + "; + type string; + } + } + } + + } + + container k8s-cluster { + leaf-list version { + description + "List of supported K8s versions. + The cluster where the KDUs will be deployed will have to match + one of these versions."; + + type string; + } + + leaf-list cni { + description + "List of supported CNI plugins. + The cluster where the KDUs will be deployed will have to use + one of these CNI plugins."; + + type enumeration { + enum calico; + enum flannel; + enum multus; + } + } + + list nets { + description + "List of required networks in the K8s cluster. + The cluster where the KDUs will be deployed will have to use + one of these CNI plugins."; + + key "id"; + + leaf id { + description "Internal identifier for the K8s cluster network in this VNF"; + type string; + } + + leaf external-connection-point-ref { + description + "Leaf Ref to the particular external connection point"; + type leafref { + path "../../../connection-point/name"; + } + } + + } + } + list vdu-dependency { description "List of VDU dependencies."; diff --git a/osm_im/__init__.py b/osm_im/__init__.py new file mode 100644 index 0000000..7284a2b --- /dev/null +++ b/osm_im/__init__.py @@ -0,0 +1,13 @@ +## +# 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. +## diff --git a/osm_im/validation.py b/osm_im/validation.py new file mode 100644 index 0000000..7334fbb --- /dev/null +++ b/osm_im/validation.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import yaml +import json +# import logging +from osm_im.vnfd import vnfd as vnfd_im +from osm_im.nsd import nsd as nsd_im +from osm_im.nst import nst as nst_im +from pyangbind.lib.serialise import pybindJSONDecoder +import pyangbind.lib.pybindJSON as pybindJSON + +class ValidationException(Exception): + pass + +class Validation: + + def pyangbind_validation(self, item, data, force=False): + ''' + item: vnfd, nst, nsd + data: dict object loaded from the descriptor file + force: True to skip unknown fields in the descriptor + ''' + if item == "vnfd": + myobj = vnfd_im() + elif item == "nsd": + myobj = nsd_im() + elif item == "nst": + myobj = nst_im() + else: + raise ValidationException("Not possible to validate '{}' item".format(item)) + + try: + pybindJSONDecoder.load_ietf_json(data, None, None, obj=myobj, + path_helper=True, skip_unknown=force) + out = pybindJSON.dumps(myobj, mode="ietf") + desc_out = yaml.safe_load(out) + return desc_out + except Exception as e: + raise ValidationException("Error in pyangbind validation: {}".format(str(e))) + + def yaml_validation(self, descriptor): + try: + data = yaml.safe_load(descriptor) + except Exception as e: + raise ValidationException("Error in YAML validation. Not a proper YAML file: {}".format(e)) + if 'vnfd:vnfd-catalog' in data or 'vnfd-catalog' in data: + item = "vnfd" + elif 'nsd:nsd-catalog' in data or 'nsd-catalog' in data: + item = "nsd" + elif 'nst' in data: + item = "nst" + else: + raise ValidationException("Error in YAML validation. Not possible to determine the type of descriptor in the first line. Expected values: vnfd:vnfd-catalog, vnfd-catalog, nsd:nsd-catalog, nsd-catalog, nst") + + return item, data + + def descriptor_validation(self, descriptor): + item, data = self.yaml_validation(descriptor) + self.pyangbind_validation(item, data) + diff --git a/setup.py b/setup.py index cda4c73..f59e790 100644 --- a/setup.py +++ b/setup.py @@ -1,14 +1,72 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import subprocess +import sys +import os from setuptools import setup, find_packages +from setuptools.command.install import install + + +class Install_osm_im(install): + """Generation of .py files from yang models""" + model_dir = "models/yang" + im_dir = "osm_im" + + def pipinstall(self, package): + """pip install for executable dependencies""" + subprocess.call([sys.executable, "-m", "pip", "install", package]) + + def run(self): + self.pipinstall('pyang') + self.pipinstall('pyangbind') + import pyangbind + print("Using dir {}/{} for python artifacts".format(os.getcwd(), self.im_dir)) + path = "{}/{}".format(os.getcwd(), self.im_dir) + for files_item in ['vnfd', 'nsd', 'nst']: + protoc_command = ["pyang", + "-Werror", + "--plugindir", + "{}/plugin".format(os.path.dirname(pyangbind.__file__)), + "--path", + self.model_dir, + "-f", "pybind", + "-o", + "{}/{}.py".format(self.im_dir, files_item), + "{}/{}.yang".format(self.model_dir, files_item)] + print("Generating {}.py from {}.yang".format(files_item, files_item)) + if subprocess.call(protoc_command) != 0: + sys.exit(-1) + # To ensure generated files are copied to the python installation folder + self.copy_tree(self.im_dir, "{}{}".format(self.install_lib, self.im_dir)) + install.run(self) + setup( name='osm_im', description='OSM Information Model', - long_description = open('README.rst').read(), + long_description=open('README.rst').read(), version_command=('git describe --tags --long --dirty --match v*', 'pep440-git-full'), author='Mike Marchetti', author_email='mmarchetti@sandvine.com', packages=find_packages(), include_package_data=True, setup_requires=['setuptools-version-command'], + install_requires=['pyang', 'pyangbind'], test_suite='nose.collector', + url='https://osm.etsi.org/gitweb/?p=osm/IM.git;a=summary', + license='Apache 2.0', + cmdclass={'install': Install_osm_im}, ) diff --git a/stdeb.cfg b/stdeb.cfg index 7b85a12..ec4c256 100644 --- a/stdeb.cfg +++ b/stdeb.cfg @@ -1,5 +1,20 @@ +# -*- coding: utf-8 -*- +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + [DEFAULT] Suite: xenial +Build-Depends: dh-python Maintainer: Gerardo Garcia Depends: osm-imdocs Depends3: osm-imdocs