initial unittest for osm_nbi.instance_topics 99/7899/7
authortierno <alfonso.tiernosepulveda@telefonica.com>
Mon, 2 Sep 2019 16:03:25 +0000 (16:03 +0000)
committertierno <alfonso.tiernosepulveda@telefonica.com>
Thu, 17 Oct 2019 13:57:10 +0000 (13:57 +0000)
Change-Id: Ib38b3e6625014c8641e7cadce69624f46b41d1ac
Signed-off-by: tierno <alfonso.tiernosepulveda@telefonica.com>
.gitignore-common
Dockerfile.local
Makefile
devops-stages/stage-test.sh
osm_nbi/instance_topics.py
osm_nbi/tests/test_db_descriptors.py [new file with mode: 0644]
osm_nbi/tests/test_instance_topics.py [new file with mode: 0644]
requirements.txt
test-requirements.txt
tox.ini

index 157e9ef..30f83df 100644 (file)
@@ -46,6 +46,8 @@ build
 dist
 *.egg-info
 .eggs
+.temp-tox
 
 #vscode
-.vscode
\ No newline at end of file
+.vscode
+
index e72aefa..8635e4b 100644 (file)
@@ -36,11 +36,13 @@ RUN pip3 install pyang && mkdir -p /app && cd /app \
     && git -C /app clone https://github.com/robshakir/pyangbind \
     && pip3 install -e /app/pyangbind \
     && git -C /app clone  https://osm.etsi.org/gerrit/osm/IM \
-    && cd /app/IM/models/yang \
     && mkdir /app/IM/osm_im \
-    && pyang --plugindir /app/pyangbind/pyangbind/plugin -f pybind -o /app/IM/osm_im/vnfd.py vnfd.yang \
-    && pyang --plugindir /app/pyangbind/pyangbind/plugin -f pybind -o /app/IM/osm_im/nsd.py nsd.yang \
-    && pyang --plugindir /app/pyangbind/pyangbind/plugin -f pybind -o /app/IM/osm_im/nst.py nst.yang \
+    && pyang --plugindir /app/pyangbind/pyangbind/plugin -f pybind -p /app/IM/models/yang \
+       -o /app/IM/osm_im/vnfd.py /app/IM/models/yang/vnfd.yang \
+    && pyang --plugindir /app/pyangbind/pyangbind/plugin -f pybind -p /app/IM/models/yang \
+       -o /app/IM/osm_im/nsd.py /app/IM/models/yang/nsd.yang \
+    && pyang --plugindir /app/pyangbind/pyangbind/plugin -f pybind -p /app/IM/models/yang \
+       -o /app/IM/osm_im/nst.py /app/IM/models/yang/nst.yang \
     && pip3 install -e /app/IM
 
 EXPOSE 9999
index fba5941..528cca1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@
 all: clean package
 
 clean:
-       rm -rf dist deb_dist osm_nbi-*.tar.gz osm_nbi.egg-info .eggs
+       rm -rf dist deb_dist osm_nbi-*.tar.gz osm_nbi.egg-info .eggs .temp-tox
 
 package:
        python3 setup.py --command-packages=stdeb.command sdist_dsc
index b47e138..5f94ba3 100755 (executable)
@@ -14,3 +14,5 @@
 # limitations under the License.
 
 tox -e flake8
+tox -e unittest
+
index 8024996..4cb1e9c 100644 (file)
@@ -23,6 +23,8 @@ from osm_nbi.base_topic import BaseTopic, EngineException, get_iterable
 # from descriptor_topics import DescriptorTopic
 from yaml import safe_dump
 from osm_common.dbbase import DbException
+from osm_common.msgbase import MsgException
+from osm_common.fsbase import FsException
 from re import match  # For checking that additional parameter names are valid Jinja2 identifiers
 
 __author__ = "Alfonso Tierno <alfonso.tiernosepulveda@telefonica.com>"
@@ -178,7 +180,9 @@ class NsrTopic(BaseTopic):
         :param indata: params to be used for the nsr
         :param kwargs: used to override the indata descriptor
         :param headers: http request headers
-        :return: the _id of nsr descriptor created at database
+        :return: the _id of nsr descriptor created at database. Or an exception of type
+            EngineException, ValidationError, DbException, FsException, MsgException.
+            Note: Exceptions are not captured on purpose. They should be captured at called
         """
 
         try:
@@ -380,11 +384,8 @@ class NsrTopic(BaseTopic):
             self.fs.mkdir(nsr_id)
 
             return nsr_id, None
-        except ValidationError as e:   # TODO remove try Except, it is captured at nbi.py
-            raise EngineException(e, HTTPStatus.UNPROCESSABLE_ENTITY)
-        except Exception as e:
-            self.logger.exception("Exception {} at NsrTopic.new()".format(e), exc_info=True)
-            raise EngineException("Error {}: {}".format(step, e))
+        except (ValidationError, EngineException, DbException, MsgException, FsException) as e:
+            raise type(e)("{} while '{}".format(e, step), http_code=e.http_code)
 
     def edit(self, session, _id, indata=None, kwargs=None, content=None):
         raise EngineException("Method edit called directly", HTTPStatus.INTERNAL_SERVER_ERROR)
@@ -489,7 +490,7 @@ class NsLcmOpTopic(BaseTopic):
             for in_ivld in get_iterable(in_vnfd.get("internal-vld")):
                 for ivld in get_iterable(vnfd.get("internal-vld")):
                     if in_ivld["name"] == ivld["name"] or in_ivld["name"] == ivld["id"]:
-                        for in_icp in get_iterable(in_ivld["internal-connection-point"]):
+                        for in_icp in get_iterable(in_ivld.get("internal-connection-point")):
                             for icp in ivld["internal-connection-point"]:
                                 if in_icp["id-ref"] == icp["id-ref"]:
                                     break
@@ -826,8 +827,9 @@ class NsLcmOpTopic(BaseTopic):
                 self._update_vnfrs(session, rollback, nsr, indata)
 
             nslcmop_desc = self._create_nslcmop(nsInstanceId, operation, indata)
+            _id = nslcmop_desc["_id"]
             self.format_on_new(nslcmop_desc, session["project_id"], make_public=session["public"])
-            _id = self.db.create("nslcmops", nslcmop_desc)
+            self.db.create("nslcmops", nslcmop_desc)
             rollback.append({"topic": "nslcmops", "_id": _id})
             if not slice_object:
                 self.msg.write("ns", operation, nslcmop_desc)
diff --git a/osm_nbi/tests/test_db_descriptors.py b/osm_nbi/tests/test_db_descriptors.py
new file mode 100644 (file)
index 0000000..d445d09
--- /dev/null
@@ -0,0 +1,591 @@
+#
+# 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.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: esousa@whitestack.com or alfonso.tiernosepulveda@telefonica.com
+##
+
+"""Contains database content needed for tests"""
+
+
+db_vim_accounts_text = """
+---
+-   _admin:
+        created: 1566818150.3024442
+        current_operation: 0
+        deployed:
+            RO: dc51ce6c-c7f2-11e9-b9c0-02420aff0004
+            RO-account: dc5c67fa-c7f2-11e9-b9c0-02420aff0004
+        detailed-status: Done
+        modified: 1566818150.3024442
+        operationalState: ENABLED
+        operations:
+        -   detailed-status: Done
+            lcmOperationType: create
+            operationParams: null
+            operationState: COMPLETED
+            startTime: 1566818150.3025382
+            statusEnteredTime: 1566818150.3025382
+            worker: 86434c2948e2
+        projects_read:
+        - 25b5aebf-3da1-49ed-99de-1d2b4a86d6e4
+        projects_write:
+        - 25b5aebf-3da1-49ed-99de-1d2b4a86d6e4
+    _id: ea958ba5-4e58-4405-bf42-6e3be15d4c3a
+    description: Openstack site 2, based on Mirantis, also called DSS9000-1, with
+        tenant tid
+    name: ost2-mrt-tid
+    schema_version: '1.1'
+    vim_password: 5g0yGX86qIhprX86YTMcpg==
+    vim_tenant_name: osm
+    vim_type: openstack
+    vim_url: http://10.95.87.162:5000/v2.0
+    vim_user: osm
+"""
+
+db_vnfds_text = """
+---
+-   _admin:
+        created: 1566823352.7154346
+        modified: 1566823353.9295402
+        onboardingState: ONBOARDED
+        operationalState: ENABLED
+        projects_read:
+        - 25b5aebf-3da1-49ed-99de-1d2b4a86d6e4
+        projects_write:
+        - 25b5aebf-3da1-49ed-99de-1d2b4a86d6e4
+        storage:
+            descriptor: hackfest_3charmed_vnfd/hackfest_3charmed_vnfd.yaml
+            folder: 7637bcf8-cf14-42dc-ad70-c66fcf1e6e77
+            fs: local
+            path: /app/storage/
+            pkg-dir: hackfest_3charmed_vnfd
+            zipfile: package.tar.gz
+        type: vnfd
+        usageState: NOT_IN_USE
+        userDefinedData: {}
+    _id: 7637bcf8-cf14-42dc-ad70-c66fcf1e6e77
+    connection-point:
+    -   id: vnf-mgmt
+        name: vnf-mgmt
+        short-name: vnf-mgmt
+        type: VPORT
+    -   id: vnf-data
+        name: vnf-data
+        short-name: vnf-data
+        type: VPORT
+    description: A VNF consisting of 2 VDUs connected to an internal VL, and one VDU
+        with cloud-init
+    id: hackfest3charmed-vnf
+    internal-vld:
+    -   id: internal
+        internal-connection-point:
+        -   id-ref: mgmtVM-internal
+        -   id-ref: dataVM-internal
+        name: internal
+        short-name: internal
+        type: ELAN
+    logo: osm.png
+    mgmt-interface:
+        cp: vnf-mgmt
+    monitoring-param:
+    -   aggregation-type: AVERAGE
+        id: monitor1
+        name: monitor1
+        vdu-monitoring-param:
+            vdu-monitoring-param-ref: dataVM_cpu_util
+            vdu-ref: dataVM
+    name: hackfest3charmed-vnf
+    scaling-group-descriptor:
+    -   max-instance-count: 10
+        name: scale_dataVM
+        scaling-config-action:
+        -   trigger: post-scale-out
+            vnf-config-primitive-name-ref: touch
+        -   trigger: pre-scale-in
+            vnf-config-primitive-name-ref: touch
+        scaling-policy:
+        -   cooldown-time: 60
+            name: auto_cpu_util_above_threshold
+            scaling-criteria:
+            -   name: cpu_util_above_threshold
+                scale-in-relational-operation: LE
+                scale-in-threshold: '15.0000000000'
+                scale-out-relational-operation: GE
+                scale-out-threshold: '60.0000000000'
+                vnf-monitoring-param-ref: monitor1
+            scaling-type: automatic
+            threshold-time: 0
+        vdu:
+        -   count: 1
+            vdu-id-ref: dataVM
+    short-name: hackfest3charmed-vnf
+    vdu:
+    -   count: '1'
+        cloud-init-file: cloud-config.txt
+        id: mgmtVM
+        image: hackfest3-mgmt
+        interface:
+        -   external-connection-point-ref: vnf-mgmt
+            name: mgmtVM-eth0
+            position: 1
+            type: EXTERNAL
+            virtual-interface:
+                type: VIRTIO
+        -   internal-connection-point-ref: mgmtVM-internal
+            name: mgmtVM-eth1
+            position: 2
+            type: INTERNAL
+            virtual-interface:
+                type: VIRTIO
+        internal-connection-point:
+        -   id: mgmtVM-internal
+            name: mgmtVM-internal
+            short-name: mgmtVM-internal
+            type: VPORT
+        name: mgmtVM
+        vm-flavor:
+            memory-mb: '1024'
+            storage-gb: '10'
+            vcpu-count: 1
+    -   count: '1'
+        id: dataVM
+        image: hackfest3-mgmt
+        interface:
+        -   internal-connection-point-ref: dataVM-internal
+            name: dataVM-eth0
+            position: 1
+            type: INTERNAL
+            virtual-interface:
+                type: VIRTIO
+        -   external-connection-point-ref: vnf-data
+            name: dataVM-xe0
+            position: 2
+            type: EXTERNAL
+            virtual-interface:
+                type: VIRTIO
+        internal-connection-point:
+        -   id: dataVM-internal
+            name: dataVM-internal
+            short-name: dataVM-internal
+            type: VPORT
+        monitoring-param:
+        -   id: dataVM_cpu_util
+            nfvi-metric: cpu_utilization
+        name: dataVM
+        vm-flavor:
+            memory-mb: '1024'
+            storage-gb: '10'
+            vcpu-count: 1
+    version: '1.0'
+    vnf-configuration:
+        config-primitive:
+        -   name: touch
+            parameter:
+            -   data-type: STRING
+                default-value: <touch_filename2>
+                name: filename
+        initial-config-primitive:
+        -   name: config
+            parameter:
+            -   name: ssh-hostname
+                value: <rw_mgmt_ip>
+            -   name: ssh-username
+                value: ubuntu
+            -   name: ssh-password
+                value: osm4u
+            seq: '1'
+        -   name: touch
+            parameter:
+            -   name: filename
+                value: <touch_filename>
+            seq: '2'
+        juju:
+            charm: simple
+"""
+
+db_nsds_text = """
+---
+-   _admin:
+        created: 1566823353.971486
+        modified: 1566823353.971486
+        onboardingState: ONBOARDED
+        operationalState: ENABLED
+        projects_read:
+        - 25b5aebf-3da1-49ed-99de-1d2b4a86d6e4
+        projects_write:
+        - 25b5aebf-3da1-49ed-99de-1d2b4a86d6e4
+        storage:
+            descriptor: hackfest_3charmed_nsd/hackfest_3charmed_nsd.yaml
+            folder: 8c2f8b95-bb1b-47ee-8001-36dc090678da
+            fs: local
+            path: /app/storage/
+            pkg-dir: hackfest_3charmed_nsd
+            zipfile: package.tar.gz
+        usageState: NOT_IN_USE
+        userDefinedData: {}
+    _id: 8c2f8b95-bb1b-47ee-8001-36dc090678da
+    constituent-vnfd:
+    -   member-vnf-index: '1'
+        vnfd-id-ref: hackfest3charmed-vnf
+    -   member-vnf-index: '2'
+        vnfd-id-ref: hackfest3charmed-vnf
+    description: NS with 2 VNFs hackfest3charmed-vnf connected by datanet and mgmtnet
+        VLs
+    id: hackfest3charmed-ns
+    logo: osm.png
+    name: hackfest3charmed-ns
+    short-name: hackfest3charmed-ns
+    version: '1.0'
+    vld:
+    -   id: mgmt
+        mgmt-network: true
+        name: mgmt
+        short-name: mgmt
+        type: ELAN
+        vim-network-name: mgmt
+        vnfd-connection-point-ref:
+        -   member-vnf-index-ref: '1'
+            vnfd-connection-point-ref: vnf-mgmt
+            vnfd-id-ref: hackfest3charmed-vnf
+        -   member-vnf-index-ref: '2'
+            vnfd-connection-point-ref: vnf-mgmt
+            vnfd-id-ref: hackfest3charmed-vnf
+    -   id: datanet
+        name: datanet
+        short-name: datanet
+        type: ELAN
+        vnfd-connection-point-ref:
+        -   member-vnf-index-ref: '1'
+            vnfd-connection-point-ref: vnf-data
+            vnfd-id-ref: hackfest3charmed-vnf
+        -   member-vnf-index-ref: '2'
+            vnfd-connection-point-ref: vnf-data
+            vnfd-id-ref: hackfest3charmed-vnf
+"""
+
+db_nsrs_text = """
+---
+-   _admin:
+        created: 1566823354.3716335
+        modified: 1566823354.3716335
+        nsState: NOT_INSTANTIATED
+        nslcmop: null
+        projects_read:
+        - 25b5aebf-3da1-49ed-99de-1d2b4a86d6e4
+        projects_write:
+        - 25b5aebf-3da1-49ed-99de-1d2b4a86d6e4
+    _id: f48163a6-c807-47bc-9682-f72caef5af85
+    additionalParamsForNs: null
+    admin-status: ENABLED
+    config-status: init
+    constituent-vnfr-ref:
+    - 88d90b0c-faff-4b9f-bccd-017f33985984
+    - 1ca3bb1a-b29b-49fe-bed6-5f3076d77434
+    create-time: 1566823354.36234
+    datacenter: ea958ba5-4e58-4405-bf42-6e3be15d4c3a
+    description: default description
+    detailed-status: 'ERROR executing proxy charm initial primitives for member_vnf_index=1
+        vdu_id=None: charm error executing primitive verify-ssh-credentials for member_vnf_index=1
+        vdu_id=None: ''timeout after 600 seconds'''
+    id: f48163a6-c807-47bc-9682-f72caef5af85
+    instantiate_params:
+        nsDescription: default description
+        nsName: ALF
+        nsdId: 8c2f8b95-bb1b-47ee-8001-36dc090678da
+        vimAccountId: ea958ba5-4e58-4405-bf42-6e3be15d4c3a
+    name: ALF
+    name-ref: ALF
+    ns-instance-config-ref: f48163a6-c807-47bc-9682-f72caef5af85
+    nsd:
+        _admin:
+            created: 1566823353.971486
+            modified: 1566823353.971486
+            onboardingState: ONBOARDED
+            operationalState: ENABLED
+            projects_read:
+            - 25b5aebf-3da1-49ed-99de-1d2b4a86d6e4
+            projects_write:
+            - 25b5aebf-3da1-49ed-99de-1d2b4a86d6e4
+            storage:
+                descriptor: hackfest_3charmed_nsd/hackfest_3charmed_nsd.yaml
+                folder: 8c2f8b95-bb1b-47ee-8001-36dc090678da
+                fs: local
+                path: /app/storage/
+                pkg-dir: hackfest_3charmed_nsd
+                zipfile: package.tar.gz
+            usageState: NOT_IN_USE
+            userDefinedData: {}
+        _id: 8c2f8b95-bb1b-47ee-8001-36dc090678da
+        constituent-vnfd:
+        -   member-vnf-index: '1'
+            vnfd-id-ref: hackfest3charmed-vnf
+        -   member-vnf-index: '2'
+            vnfd-id-ref: hackfest3charmed-vnf
+        description: NS with 2 VNFs hackfest3charmed-vnf connected by datanet and
+            mgmtnet VLs
+        id: hackfest3charmed-ns
+        logo: osm.png
+        name: hackfest3charmed-ns
+        short-name: hackfest3charmed-ns
+        version: '1.0'
+        vld:
+        -   id: mgmt
+            mgmt-network: true
+            name: mgmt
+            short-name: mgmt
+            type: ELAN
+            vim-network-name: mgmt
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: vnf-mgmt
+                vnfd-id-ref: hackfest3charmed-vnf
+            -   member-vnf-index-ref: '2'
+                vnfd-connection-point-ref: vnf-mgmt
+                vnfd-id-ref: hackfest3charmed-vnf
+        -   id: datanet
+            name: datanet
+            short-name: datanet
+            type: ELAN
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: vnf-data
+                vnfd-id-ref: hackfest3charmed-vnf
+            -   member-vnf-index-ref: '2'
+                vnfd-connection-point-ref: vnf-data
+                vnfd-id-ref: hackfest3charmed-vnf
+    nsd-id: 8c2f8b95-bb1b-47ee-8001-36dc090678da
+    nsd-name-ref: hackfest3charmed-ns
+    nsd-ref: hackfest3charmed-ns
+    operational-events: []
+    operational-status: failed
+    orchestration-progress: {}
+    resource-orchestrator: osmopenmano
+    short-name: ALF
+    ssh-authorized-key: null
+    vld:
+    -   id: mgmt
+        name: null
+        status: ACTIVE
+        status-detailed: null
+        vim-id: f99ae780-0e2f-4985-af41-574eae6919c0
+        vim-network-name: mgmt
+    -   id: datanet
+        name: ALF-datanet
+        status: ACTIVE
+        status-detailed: null
+        vim-id: c31364ba-f573-4ab6-bf1a-fed30ede39a8
+    vnfd-id:
+    - 7637bcf8-cf14-42dc-ad70-c66fcf1e6e77
+"""
+
+db_nslcmops_text = """
+---
+-   _admin:
+        created: 1566823354.4148262
+        modified: 1566823354.4148262
+        projects_read:
+        - 25b5aebf-3da1-49ed-99de-1d2b4a86d6e4
+        projects_write:
+        - 25b5aebf-3da1-49ed-99de-1d2b4a86d6e4
+        worker: 86434c2948e2
+    _id: a639fac7-e0bb-4225-8ecb-c1f8efcc125e
+    detailed-status: 'FAILED executing proxy charm initial primitives for member_vnf_index=1
+        vdu_id=None: charm error executing primitive verify-ssh-credentials for member_vnf_index=1
+        vdu_id=None: ''timeout after 600 seconds'''
+    id: a639fac7-e0bb-4225-8ecb-c1f8efcc125e
+    isAutomaticInvocation: false
+    isCancelPending: false
+    lcmOperationType: instantiate
+    links:
+        nsInstance: /osm/nslcm/v1/ns_instances/f48163a6-c807-47bc-9682-f72caef5af85
+        self: /osm/nslcm/v1/ns_lcm_op_occs/a639fac7-e0bb-4225-8ecb-c1f8efcc125e
+    nsInstanceId: f48163a6-c807-47bc-9682-f72caef5af85
+    operationParams:
+        additionalParamsForVnf:
+        -   additionalParams:
+                touch_filename: /home/ubuntu/first-touch-1
+                touch_filename2: /home/ubuntu/second-touch-1
+            member-vnf-index: '1'
+        -   additionalParams:
+                touch_filename: /home/ubuntu/first-touch-2
+                touch_filename2: /home/ubuntu/second-touch-2
+            member-vnf-index: '2'
+        lcmOperationType: instantiate
+        nsDescription: default description
+        nsInstanceId: f48163a6-c807-47bc-9682-f72caef5af85
+        nsName: ALF
+        nsdId: 8c2f8b95-bb1b-47ee-8001-36dc090678da
+        vimAccountId: ea958ba5-4e58-4405-bf42-6e3be15d4c3a
+    operationState: FAILED
+    startTime: 1566823354.414689
+    statusEnteredTime: 1566824534.5112448
+"""
+
+db_vnfrs_text = """
+---
+-   _admin:
+        created: 1566823354.3668208
+        modified: 1566823354.3668208
+        nsState: NOT_INSTANTIATED
+        projects_read:
+        - 25b5aebf-3da1-49ed-99de-1d2b4a86d6e4
+        projects_write:
+        - 25b5aebf-3da1-49ed-99de-1d2b4a86d6e4
+    _id: 88d90b0c-faff-4b9f-bccd-017f33985984
+    additionalParamsForVnf:
+        touch_filename: /home/ubuntu/first-touch-1
+        touch_filename2: /home/ubuntu/second-touch-1
+    connection-point:
+    -   connection-point-id: vnf-mgmt
+        id: vnf-mgmt
+        name: vnf-mgmt
+    -   connection-point-id: vnf-data
+        id: vnf-data
+        name: vnf-data
+    created-time: 1566823354.36234
+    id: 88d90b0c-faff-4b9f-bccd-017f33985984
+    ip-address: 10.205.1.46
+    member-vnf-index-ref: '1'
+    nsr-id-ref: f48163a6-c807-47bc-9682-f72caef5af85
+    vdur:
+    -   _id: f0e7d7ce-2443-4dcb-ad0b-5ab9f3b13d37
+        count-index: 0
+        interfaces:
+        -   ip-address: 10.205.1.46
+            mac-address: fa:16:3e:b4:3e:b1
+            mgmt-vnf: true
+            name: mgmtVM-eth0
+            ns-vld-id: mgmt
+        -   ip-address: 192.168.54.2
+            mac-address: fa:16:3e:6e:7e:78
+            name: mgmtVM-eth1
+            vnf-vld-id: internal
+        internal-connection-point:
+        -   connection-point-id: mgmtVM-internal
+            id: mgmtVM-internal
+            name: mgmtVM-internal
+        ip-address: 10.205.1.46
+        name: ALF-1-mgmtVM-1
+        status: ACTIVE
+        status-detailed: null
+        vdu-id-ref: mgmtVM
+        vim-id: c2538499-4c30-41c0-acd5-80cb92f48061
+    -   _id: ab453219-2d9a-45c2-864d-2c0788385028
+        count-index: 0
+        interfaces:
+        -   ip-address: 192.168.54.3
+            mac-address: fa:16:3e:d9:7a:5d
+            name: dataVM-eth0
+            vnf-vld-id: internal
+        -   ip-address: 192.168.24.3
+            mac-address: fa:16:3e:d1:6c:0d
+            name: dataVM-xe0
+            ns-vld-id: datanet
+        internal-connection-point:
+        -   connection-point-id: dataVM-internal
+            id: dataVM-internal
+            name: dataVM-internal
+        ip-address: null
+        name: ALF-1-dataVM-1
+        status: ACTIVE
+        status-detailed: null
+        vdu-id-ref: dataVM
+        vim-id: 87973c3f-365d-4227-95c2-7a8abc74349c
+    vim-account-id: ea958ba5-4e58-4405-bf42-6e3be15d4c3a
+    vld:
+    -   id: internal
+        name: ALF-internal
+        status: ACTIVE
+        status-detailed: null
+        vim-id: ff181e6d-2597-4244-b40b-bb0174bdfeb6
+    vnfd-id: 7637bcf8-cf14-42dc-ad70-c66fcf1e6e77
+    vnfd-ref: hackfest3charmed-vnf
+-   _admin:
+        created: 1566823354.3703845
+        modified: 1566823354.3703845
+        nsState: NOT_INSTANTIATED
+        projects_read:
+        - 25b5aebf-3da1-49ed-99de-1d2b4a86d6e4
+        projects_write:
+        - 25b5aebf-3da1-49ed-99de-1d2b4a86d6e4
+    _id: 1ca3bb1a-b29b-49fe-bed6-5f3076d77434
+    additionalParamsForVnf:
+        touch_filename: /home/ubuntu/first-touch-2
+        touch_filename2: /home/ubuntu/second-touch-2
+    connection-point:
+    -   connection-point-id: vnf-mgmt
+        id: vnf-mgmt
+        name: vnf-mgmt
+    -   connection-point-id: vnf-data
+        id: vnf-data
+        name: vnf-data
+    created-time: 1566823354.36234
+    id: 1ca3bb1a-b29b-49fe-bed6-5f3076d77434
+    ip-address: 10.205.1.47
+    member-vnf-index-ref: '2'
+    nsr-id-ref: f48163a6-c807-47bc-9682-f72caef5af85
+    vdur:
+    -   _id: 190b4a2c-4f85-4cfe-9406-4cef7ffb1e67
+        count-index: 0
+        interfaces:
+        -   ip-address: 10.205.1.47
+            mac-address: fa:16:3e:cb:9f:c7
+            mgmt-vnf: true
+            name: mgmtVM-eth0
+            ns-vld-id: mgmt
+        -   ip-address: 192.168.231.1
+            mac-address: fa:16:3e:1a:89:24
+            name: mgmtVM-eth1
+            vnf-vld-id: internal
+        internal-connection-point:
+        -   connection-point-id: mgmtVM-internal
+            id: mgmtVM-internal
+            name: mgmtVM-internal
+        ip-address: 10.205.1.47
+        name: ALF-2-mgmtVM-1
+        status: ACTIVE
+        status-detailed: null
+        vdu-id-ref: mgmtVM
+        vim-id: 248077b2-e3b8-4a37-8b72-575abb8ed912
+    -   _id: 889b874d-e1c3-4e75-aa45-53a9b0ddabd9
+        count-index: 0
+        interfaces:
+        -   ip-address: 192.168.231.3
+            mac-address: fa:16:3e:7e:ba:8c
+            name: dataVM-eth0
+            vnf-vld-id: internal
+        -   ip-address: 192.168.24.4
+            mac-address: fa:16:3e:d2:e1:f5
+            name: dataVM-xe0
+            ns-vld-id: datanet
+        internal-connection-point:
+        -   connection-point-id: dataVM-internal
+            id: dataVM-internal
+            name: dataVM-internal
+        ip-address: null
+        name: ALF-2-dataVM-1
+        status: ACTIVE
+        status-detailed: null
+        vdu-id-ref: dataVM
+        vim-id: a4ce4372-e0ad-4ae3-8f9f-1c969f32e77b
+    vim-account-id: ea958ba5-4e58-4405-bf42-6e3be15d4c3a
+    vld:
+    -   id: internal
+        name: ALF-internal
+        status: ACTIVE
+        status-detailed: null
+        vim-id: ff181e6d-2597-4244-b40b-bb0174bdfeb6
+    vnfd-id: 7637bcf8-cf14-42dc-ad70-c66fcf1e6e77
+    vnfd-ref: hackfest3charmed-vnf
+"""
diff --git a/osm_nbi/tests/test_instance_topics.py b/osm_nbi/tests/test_instance_topics.py
new file mode 100644 (file)
index 0000000..5c91114
--- /dev/null
@@ -0,0 +1,235 @@
+#
+# 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.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: esousa@whitestack.com or alfonso.tiernosepulveda@telefonica.com
+##
+
+import unittest
+from unittest.mock import Mock, mock_open   # patch, MagicMock
+from osm_common.dbbase import DbException
+from osm_nbi.engine import EngineException
+from osm_common.dbmemory import DbMemory
+from osm_common.fsbase import FsBase
+from osm_common.msgbase import MsgBase
+from http import HTTPStatus
+from osm_nbi.instance_topics import NsLcmOpTopic, NsrTopic
+from osm_nbi.tests.test_db_descriptors import db_vim_accounts_text, db_nsds_text, db_vnfds_text, db_nsrs_text,\
+    db_vnfrs_text
+from copy import deepcopy
+import yaml
+
+
+class TestNsLcmOpTopic(unittest.TestCase):
+
+    def setUp(self):
+        self.db = DbMemory()
+        self.fs = Mock(FsBase())
+        self.fs.get_params.return_value = {"./fake/folder"}
+        self.fs.file_open = mock_open()
+        self.msg = Mock(MsgBase())
+        # create class
+        self.nslcmop_topic = NsLcmOpTopic(self.db, self.fs, self.msg, None)
+        self.nslcmop_topic.check_quota = Mock(return_value=None)  # skip quota
+
+        self.db.create_list("vim_accounts", yaml.load(db_vim_accounts_text, Loader=yaml.Loader))
+        self.db.create_list("nsds", yaml.load(db_nsds_text, Loader=yaml.Loader))
+        self.db.create_list("vnfds", yaml.load(db_vnfds_text, Loader=yaml.Loader))
+        self.db.create_list("vnfrs", yaml.load(db_vnfrs_text, Loader=yaml.Loader))
+        self.db.create_list("nsrs", yaml.load(db_nsrs_text, Loader=yaml.Loader))
+        self.db.create = Mock(return_value="created_id")
+        self.db.set_one = Mock(return_value={"updated": 1})
+        self.nsd = self.db.get_list("nsds")[0]
+        self.nsd_id = self.nsd["_id"]
+        self.nsr = self.db.get_list("nsrs")[0]
+        self.nsr_id = self.nsr["_id"]
+        self.nsr_project = self.nsr["_admin"]["projects_read"][0]
+
+        self.vim = self.db.get_list("vim_accounts")[0]
+        self.vim_id = self.vim["_id"]
+
+    def test_create_instantiate(self):
+        session = {"force": False, "admin": False, "public": False, "project_id": [self.nsr_project], "method": "write"}
+        indata = {
+            "nsdId": self.nsd_id,
+            "nsInstanceId": self.nsr_id,
+            "nsName": "name",
+            "vimAccountId": self.vim_id,
+            "additionalParamsForVnf": [{"member-vnf-index": "1", "additionalParams": {"touch_filename": "file"}},
+                                       {"member-vnf-index": "2", "additionalParams": {"touch_filename": "file"}}],
+            "vnf": [{"member-vnf-index": "1",
+                     "vdu": [{"id": "dataVM", "interface": [{"name": "dataVM-eth0",
+                                                             "ip-address": "10.11.12.13",
+                                                             "floating-ip-required": True}]
+                              }],
+                     "internal-vld": [{"name": "internal", "vim-network-id": "vim-net-id"}]
+                     }],
+            "lcmOperationType": "instantiate",
+
+        }
+        rollback = []
+        headers = {}
+
+        nslcmop_id, _ = self.nslcmop_topic.new(rollback, session, indata=indata, kwargs=None, headers=headers)
+
+        # check nslcmop is created at database
+        self.assertEqual(self.db.create.call_count, 1, "database create not called, or called more than once")
+        _call = self.db.create.call_args_list[0]
+        self.assertEqual(_call[0][0], "nslcmops", "must be create a nslcmops entry at database")
+
+        created_nslcmop = _call[0][1]
+        self.assertEqual(nslcmop_id, created_nslcmop["_id"], "mismatch between return id and database '_id'")
+        self.assertEqual(self.nsr_id, created_nslcmop["nsInstanceId"], "bad reference id from nslcmop to nsr")
+        self.assertTrue(created_nslcmop["_admin"].get("projects_read"),
+                        "Database record must contain '_amdin.projects_read'")
+        self.assertIn("created", created_nslcmop["_admin"], "Database record must contain '_admin.created'")
+        self.assertTrue(created_nslcmop["lcmOperationType"] == "instantiate",
+                        "Database record must contain 'lcmOperationType=instantiate'")
+
+        self.assertEqual(len(rollback), len(self.db.set_one.call_args_list) + 1,
+                         "rollback mismatch with created/set items at database")
+
+        # test parameters with error
+        bad_id = "88d90b0c-faff-4b9f-bccd-aaaaaaaaaaaa"
+        test_set = (
+            ("nsr not found", {"nsInstanceId": bad_id}, DbException, HTTPStatus.NOT_FOUND, ("not found", bad_id)),
+            # TODO add "nsd"
+            # ({"vimAccountId": bad_id}, DbException, HTTPStatus.NOT_FOUND, ("not found", bad_id)),  # TODO add "vim"
+            ("bad member-vnf-index", {"vnf.0.member-vnf-index": "k"}, EngineException, HTTPStatus.BAD_REQUEST,
+             ("k",)),
+        )
+        for message, kwargs_, expect_exc, expect_code, expect_text_list in test_set:
+            with self.assertRaises(expect_exc, msg=message) as e:
+                self.nslcmop_topic.new(rollback, session, indata=deepcopy(indata), kwargs=kwargs_, headers=headers)
+            if expect_code:
+                self.assertTrue(e.exception.http_code == expect_code)
+            if expect_text_list:
+                for expect_text in expect_text_list:
+                    self.assertIn(expect_text, str(e.exception).lower(),
+                                  "Expected '{}' at exception text".format(expect_text))
+
+    def test_check_ns_operation_action(self):
+        nsrs = self.db.get_list("nsrs")[0]
+        session = {}
+
+        indata = {
+            "member_vnf_index": "1",
+            "vdu_id": None,
+            "primitive": "touch",
+            "primitive_params": {"filename": "file"}
+        }
+
+        self.nslcmop_topic._check_ns_operation(session, nsrs, "action", indata)
+        for k in indata:
+            indata_copy = indata.copy()
+            if k == "primitive_params":
+                continue
+            indata_copy[k] = "non_existing"
+            with self.assertRaises(EngineException) as exc_manager:
+                self.nslcmop_topic._check_ns_operation(session, nsrs, "action", indata_copy)
+            exc = exc_manager.exception
+            self.assertEqual(exc.http_code, HTTPStatus.BAD_REQUEST, "Engine exception bad http_code with {}".
+                             format(indata_copy))
+
+
+class TestNsrTopic(unittest.TestCase):
+
+    def setUp(self):
+        self.db = DbMemory()
+        self.fs = Mock(FsBase())
+        self.fs.get_params.return_value = {"./fake/folder"}
+        self.fs.file_open = mock_open()
+        self.msg = Mock(MsgBase())
+        # create class
+        self.nsr_topic = NsrTopic(self.db, self.fs, self.msg, None)
+        self.nsr_topic.check_quota = Mock(return_value=None)  # skip quota
+
+        self.db.create_list("vim_accounts", yaml.load(db_vim_accounts_text, Loader=yaml.Loader))
+        self.db.create_list("nsds", yaml.load(db_nsds_text, Loader=yaml.Loader))
+        self.db.create_list("vnfds", yaml.load(db_vnfds_text, Loader=yaml.Loader))
+        self.db.create = Mock(return_value="created_id")
+        self.nsd = self.db.get_list("nsds")[0]
+        self.nsd_id = self.nsd["_id"]
+        self.nsd_project = self.nsd["_admin"]["projects_read"][0]
+
+        self.vim = self.db.get_list("vim_accounts")[0]
+        self.vim_id = self.vim["_id"]
+
+    def test_create(self):
+        session = {"force": False, "admin": False, "public": False, "project_id": [self.nsd_project], "method": "write"}
+        indata = {
+            "nsdId": self.nsd_id,
+            "nsName": "name",
+            "vimAccountId": self.vim_id,
+            "additionalParamsForVnf": [{"member-vnf-index": "1", "additionalParams": {"touch_filename": "file"}},
+                                       {"member-vnf-index": "2", "additionalParams": {"touch_filename": "file"}}]
+        }
+        rollback = []
+        headers = {}
+
+        self.nsr_topic.new(rollback, session, indata=indata, kwargs=None, headers=headers)
+
+        # check vnfrs and nsrs created in whatever order
+        created_vnfrs = []
+        created_nsrs = []
+        nsr_id = None
+        for _call in self.db.create.call_args_list:
+            assert len(_call[0]) >= 2, "called db.create with few parameters"
+            created_item = _call[0][1]
+            if _call[0][0] == "vnfrs":
+                created_vnfrs.append(created_item)
+                self.assertIn("member-vnf-index-ref", created_item,
+                              "Created item must contain member-vnf-index-ref section")
+                if nsr_id:
+                    self.assertEqual(nsr_id, created_item["nsr-id-ref"], "bad reference id from vnfr to nsr")
+                else:
+                    nsr_id = created_item["nsr-id-ref"]
+
+            elif _call[0][0] == "nsrs":
+                created_nsrs.append(created_item)
+                if nsr_id:
+                    self.assertEqual(nsr_id, created_item["_id"], "bad reference id from vnfr to nsr")
+                else:
+                    nsr_id = created_item["_id"]
+            else:
+                assert True, "created an unknown record {} at database".format(_call[0][0])
+
+            self.assertTrue(created_item["_admin"].get("projects_read"),
+                            "Database record must contain '_amdin.projects_read'")
+            self.assertIn("created", created_item["_admin"], "Database record must contain '_admin.created'")
+            self.assertTrue(created_item["_admin"]["nsState"] == "NOT_INSTANTIATED",
+                            "Database record must contain '_admin.nstate=NOT INSTANTIATE'")
+
+        self.assertEqual(len(created_vnfrs), len(self.nsd["constituent-vnfd"]),
+                         "created a mismatch number of vnfr at database")
+        self.assertEqual(len(created_nsrs), 1, "Only one nsrs must be created at database")
+        self.assertEqual(len(rollback), len(created_vnfrs) + 1, "rollback mismatch with created items at database")
+
+        # test parameters with error
+        bad_id = "88d90b0c-faff-4b9f-bccd-aaaaaaaaaaaa"
+        test_set = (
+            # TODO add "nsd"
+            ("nsd not found", {"nsdId": bad_id}, DbException, HTTPStatus.NOT_FOUND, ("not found", bad_id)),
+            # ({"vimAccountId": bad_id}, DbException, HTTPStatus.NOT_FOUND, ("not found", bad_id)),  # TODO add "vim"
+            ("additional params not supply", {"additionalParamsForVnf.0.member-vnf-index": "k"}, EngineException,
+             HTTPStatus.BAD_REQUEST, None),
+        )
+        for message, kwargs_, expect_exc, expect_code, expect_text_list in test_set:
+            with self.assertRaises(expect_exc, msg=message) as e:
+                self.nsr_topic.new(rollback, session, indata=deepcopy(indata), kwargs=kwargs_, headers=headers)
+            if expect_code:
+                self.assertTrue(e.exception.http_code == expect_code)
+            if expect_text_list:
+                for expect_text in expect_text_list:
+                    self.assertIn(expect_text, str(e.exception).lower(),
+                                  "Expected '{}' at exception text".format(expect_text))
index 64c7079..426e430 100644 (file)
@@ -17,4 +17,5 @@ python-keystoneclient
 requests
 git+https://osm.etsi.org/gerrit/osm/common.git#egg=osm-common
 git+https://osm.etsi.org/gerrit/osm/IM.git#egg=osm-im
+aiohttp==0.20.2
 
index e52d6ac..8f9f3b4 100644 (file)
@@ -11,9 +11,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-flake8<3.0
-mock
-requests
-parallel-ssh
-urllib3
+# flake8<3.0
+# mock
+# pyangbind
+pyang
 
diff --git a/tox.ini b/tox.ini
index 5654da5..ef4af53 100644 (file)
--- a/tox.ini
+++ b/tox.ini
 # limitations under the License.
 
 [tox]
-envlist = py3
+envlist = flake8, unittest
 toxworkdir={toxinidir}/.tox
 
 [testenv]
+usedevelop = True
 basepython = python3
-install_command = python3 -m pip install -r requirements.txt -U {opts} {packages}
+install_command = python3 -m pip install -r requirements.txt   -U {opts} {packages}
 deps = -r{toxinidir}/test-requirements.txt
-commands=python3 -m unittest discover -v
 
 [testenv:flake8]
 basepython = python3
 deps = flake8
 commands = flake8 osm_nbi/ setup.py --max-line-length 120 \
-    --exclude .svn,CVS,.gz,.git,__pycache__,.tox,local,temp,osm_im --ignore W291,W293,E226,E402,W504
+    --exclude .svn,CVS,.gz,.git,__pycache__,.tox,local,temp,osm_im,.temp-tox --ignore W291,W293,E226,E402,W504
 
 [testenv:build]
 basepython = python3
@@ -35,3 +35,7 @@ deps = stdeb
        setuptools-version-command
 commands = python3 setup.py --command-packages=stdeb.command bdist_deb
 
+[testenv:unittest]
+basepython = python3
+commands = python3 -m unittest discover {toxinidir}/osm_nbi/tests -v
+