Merge branch 'master' into sol006 05/8405/1
authorgarciadeblas <gerardo.garciadeblas@telefonica.com>
Mon, 16 Dec 2019 16:24:03 +0000 (17:24 +0100)
committergarciadeblas <gerardo.garciadeblas@telefonica.com>
Mon, 16 Dec 2019 16:25:04 +0000 (17:25 +0100)
Change-Id: Iaa1a32bb76c06720e941b6d801da72b1b1ad9af4
Signed-off-by: garciadeblas <gerardo.garciadeblas@telefonica.com>
.gitignore
MANIFEST.in [new file with mode: 0644]
Makefile
models/yang/mano-types.yang
models/yang/nsd-base.yang
models/yang/nsr.yang
models/yang/vnfd-base.yang
osm_im/__init__.py [new file with mode: 0644]
osm_im/validation.py [new file with mode: 0644]
setup.py
stdeb.cfg

index 3e381c6..893f025 100644 (file)
@@ -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 (file)
index 0000000..b804618
--- /dev/null
@@ -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
index 7c41b11..e4e8fef 100644 (file)
--- 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|<a href=\"http://www.tail-f.com">|<a href="http://osm.etsi.org">|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)
index a734822..a696550 100644 (file)
@@ -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;
         }
       }
     }
index 2eeabc5..70dd3eb 100644 (file)
@@ -559,6 +559,7 @@ module nsd-base
         "Information about NS configuration.";
 
       uses manotypes:vca-configuration;
+      uses manotypes:vca-relations;
     }
 
     uses manotypes:input-parameter-xpath;
index bce46e0..49a44e3 100644 (file)
@@ -189,7 +189,7 @@ module nsr
       description
           "Name of the primitive.";
       type string;
-      mandatory "true";
+      mandatory true;
     }
 
     leaf user-defined-script {
index eb81021..38bede6 100644 (file)
@@ -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:
+                 - <helm-repo>/<helm-chart>
+                 - <helm-chart folder under k8s_models folder in the package>
+                 - <helm-chart tgz file (w/ or w/o extension) under k8s_models folder in the package>
+                 - <URL_where_to_fetch_chart>
+                ";
+              type string;
+            }
+          }
+
+          case juju-bundle {
+            leaf juju-bundle {
+              description
+                "Juju bundle that models the KDU, in any of the following ways:
+                 - <juju-repo>/<juju-bundle>
+                 - <juju-bundle folder under k8s_models folder in the package>
+                 - <juju-bundle tgz file (w/ or w/o extension) under k8s_models folder in the package>
+                 - <URL_where_to_fetch_juju_bundle>
+                ";
+              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 (file)
index 0000000..7284a2b
--- /dev/null
@@ -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 (file)
index 0000000..7334fbb
--- /dev/null
@@ -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)
+
index cda4c73..f59e790 100644 (file)
--- 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},
 )
index 7b85a12..ec4c256 100644 (file)
--- 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 <gerardo.garciadeblas@telefonica.com>
 Depends: osm-imdocs
 Depends3: osm-imdocs