Adding PaaS Service Creation UTs 22/12622/2
authorPatricia Reinoso <patricia.reinoso@canonical.com>
Wed, 26 Oct 2022 09:03:28 +0000 (09:03 +0000)
committeraticig <gulsum.atici@canonical.com>
Thu, 27 Oct 2022 11:54:51 +0000 (13:54 +0200)
Change-Id: I526e4bd68d54b831def9b8c6c8ab3340909d5470
Signed-off-by: Patricia Reinoso <patricia.reinoso@canonical.com>
osm_lcm/tests/test_lcm.py
osm_lcm/tests/test_lcm_utils.py
osm_lcm/tests/test_paas_conn.py [new file with mode: 0644]
osm_lcm/tests/test_paas_service.py [new file with mode: 0644]

index d1a99ff..50b8d7a 100644 (file)
@@ -160,3 +160,100 @@ class TestPaasKafkaRead(TestLcmBase):
         self.my_lcm.kafka_read_callback("paas", "invalid", self.params)
         self.my_lcm.lcm_tasks.register.assert_not_called()
         ensure_future.assert_not_called()
+
+
+@patch("osm_lcm.lcm.asyncio.ensure_future")
+class TestNsKafkaRead(TestLcmBase):
+    def setUp(self):
+        super().setUp()
+        self.task = {}
+        self.paas_params = {
+            "_id": "nslcmop_id",
+            "nsInstanceId": "nsr_id",
+            "operationParams": {"paasAccountId": "paas_id"},
+        }
+
+        self.vim_params = {
+            "_id": "nslcmop_id",
+            "nsInstanceId": "nsr_id",
+            "operationParams": {},
+        }
+
+        self.my_lcm.ns = Mock()
+        self.my_lcm.lcm_tasks = Mock()
+        self.my_lcm.juju_paas = Mock()
+        self.my_lcm.paas_service = {"juju": self.my_lcm.juju_paas}
+
+    def test_kafka_read_ns_instantiate_vim_account(self, mock_ensure_future):
+        mock_ensure_future.return_value = self.task
+        self.my_lcm.kafka_read_callback("ns", "instantiate", self.vim_params)
+        mock_ensure_future.assert_called_once_with(self.my_lcm.ns.instantiate())
+        self.my_lcm.lcm_tasks.register.assert_called_with(
+            "ns", "nsr_id", "nslcmop_id", "ns_instantiate", self.task
+        )
+
+    @patch("osm_lcm.lcm.get_paas_id_by_nsr_id")
+    def test_kafka_read_ns_terminate_vim_account(self, get_paas_id, mock_ensure_future):
+        mock_ensure_future.return_value = self.task
+        get_paas_id.return_value = None
+        self.my_lcm.kafka_read_callback("ns", "terminate", self.vim_params)
+        self.my_lcm.lcm_tasks.cancel.assert_called_with("ns", "nsr_id")
+        mock_ensure_future.assert_called_once_with(self.my_lcm.ns.terminate())
+        self.my_lcm.lcm_tasks.register.assert_called_with(
+            "ns", "nsr_id", "nslcmop_id", "ns_terminate", self.task
+        )
+
+    @patch("osm_lcm.lcm.get_paas_id_by_nsr_id")
+    def test_kafka_read_ns_action_vim_account(self, get_paas_id, mock_ensure_future):
+        mock_ensure_future.return_value = self.task
+        get_paas_id.return_value = None
+        self.my_lcm.kafka_read_callback("ns", "action", self.vim_params)
+        mock_ensure_future.assert_called_once_with(self.my_lcm.ns.action())
+        self.my_lcm.lcm_tasks.register.assert_called_with(
+            "ns", "nsr_id", "nslcmop_id", "ns_action", self.task
+        )
+
+    @patch("osm_lcm.lcm.get_paas_type_by_paas_id")
+    def test_kafka_read_ns_instantiate_paas_account(
+        self, get_paas_type, mock_ensure_future
+    ):
+        mock_ensure_future.return_value = self.task
+        get_paas_type.return_value = "juju"
+        self.my_lcm.kafka_read_callback("ns", "instantiate", self.paas_params)
+        mock_ensure_future.assert_called_once_with(self.my_lcm.juju_paas.instantiate())
+        self.my_lcm.lcm_tasks.register.assert_called_with(
+            "ns", "nsr_id", "nslcmop_id", "ns_instantiate", self.task
+        )
+        get_paas_type.assert_called_with("paas_id", self.my_lcm.db)
+
+    @patch("osm_lcm.lcm.get_paas_type_by_paas_id")
+    @patch("osm_lcm.lcm.get_paas_id_by_nsr_id")
+    def test_kafka_read_ns_terminate_paas_account(
+        self, get_paas_id, get_paas_type, mock_ensure_future
+    ):
+        mock_ensure_future.return_value = self.task
+        get_paas_id.return_value = "paas_id"
+        get_paas_type.return_value = "juju"
+        self.my_lcm.kafka_read_callback("ns", "terminate", self.paas_params)
+        mock_ensure_future.assert_called_once_with(self.my_lcm.juju_paas.terminate())
+        self.my_lcm.lcm_tasks.register.assert_called_with(
+            "ns", "nsr_id", "nslcmop_id", "ns_terminate", self.task
+        )
+        get_paas_id.assert_called_with("nsr_id", self.my_lcm.db)
+        get_paas_type.assert_called_with("paas_id", self.my_lcm.db)
+
+    @patch("osm_lcm.lcm.get_paas_type_by_paas_id")
+    @patch("osm_lcm.lcm.get_paas_id_by_nsr_id")
+    def test_kafka_read_ns_action_paas_account(
+        self, get_paas_id, get_paas_type, mock_ensure_future
+    ):
+        mock_ensure_future.return_value = self.task
+        get_paas_id.return_value = "paas_id"
+        get_paas_type.return_value = "juju"
+        self.my_lcm.kafka_read_callback("ns", "action", self.paas_params)
+        mock_ensure_future.assert_called_once_with(self.my_lcm.juju_paas.action())
+        self.my_lcm.lcm_tasks.register.assert_called_with(
+            "ns", "nsr_id", "nslcmop_id", "ns_action", self.task
+        )
+        get_paas_id.assert_called_with("nsr_id", self.my_lcm.db)
+        get_paas_type.assert_called_with("paas_id", self.my_lcm.db)
index 6067b2d..5155dcf 100644 (file)
@@ -23,7 +23,12 @@ from osm_common.msgkafka import MsgKafka
 from osm_common import fslocal
 from osm_lcm.data_utils.database.database import Database
 from osm_lcm.data_utils.filesystem.filesystem import Filesystem
-from osm_lcm.lcm_utils import LcmBase, LcmException
+from osm_lcm.lcm_utils import (
+    LcmBase,
+    LcmException,
+    get_paas_id_by_nsr_id,
+    get_paas_type_by_paas_id,
+)
 from osm_lcm.tests import test_db_descriptors as descriptors
 import yaml
 from zipfile import BadZipfile
@@ -245,3 +250,24 @@ class TestLcmBase(TestCase):
                 self.assertEqual(mock_charm_path.call_count, 1)
                 self.assertEqual(mock_metadata_file.call_count, 1)
                 self.assertEqual(mock_charm_name.call_count, 1)
+
+
+class TestPaasUtils(TestCase):
+    def setUp(self):
+        self.db = Mock()
+
+    def test_get_paas_id_by_nsr_id(self):
+        nsr_id = "nsr_id"
+        nsr_filter = {"_id": nsr_id}
+        self.db.get_one.return_value = {"paasdatacenter": "paas_id"}
+        result = get_paas_id_by_nsr_id(nsr_id, self.db)
+        self.db.get_one.expect_called_with("nsrs", nsr_filter)
+        assert result == "paas_id"
+
+    def test_get_paas_type_by_paas_id(self):
+        paas_id = "paas_id"
+        paas_filter = {"_id": paas_id}
+        self.db.get_one.return_value = {"paas_type": "juju"}
+        result = get_paas_type_by_paas_id(paas_id, self.db)
+        self.db.get_one.expect_called_with("paas", paas_filter)
+        assert result == "juju"
diff --git a/osm_lcm/tests/test_paas_conn.py b/osm_lcm/tests/test_paas_conn.py
new file mode 100644 (file)
index 0000000..3d463aa
--- /dev/null
@@ -0,0 +1,61 @@
+# Copyright 2022 Canonical Ltd.
+#
+# 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 asyncio
+from unittest import TestCase
+from unittest.mock import Mock
+from osm_lcm.paas_conn import (
+    paas_connector_factory,
+    JujuPaasConnector,
+    PaasConnException,
+)
+
+
+class TestPaasConnectorFactory(TestCase):
+    def test_paas_connector_factory_default_param_is_juju(self):
+        connector = paas_connector_factory(
+            "uuid", "name", Mock(), Mock(), Mock(), Mock(), Mock()
+        )
+        assert isinstance(connector, JujuPaasConnector)
+
+    def test_paas_connector_factory(self):
+        connector = paas_connector_factory(
+            "uuid", "name", Mock(), Mock(), Mock(), Mock(), Mock(), "juju"
+        )
+        assert isinstance(connector, JujuPaasConnector)
+
+    def test_paas_connector_factory_not_existing_type(self):
+        with self.assertRaises(PaasConnException):
+            paas_connector_factory(
+                "uuid", "name", Mock(), Mock(), Mock(), Mock(), Mock(), "other"
+            )
+
+
+class TestJujuPaasConnector(TestCase):
+    def setUp(self):
+        self.juju_paas_connector = JujuPaasConnector("uuid", "name")
+
+    def test_connect(self):
+        with self.assertRaises(NotImplementedError):
+            asyncio.run(self.juju_paas_connector.connect("endpoint", "user", "secret"))
+
+    def test_instantiate(self):
+        asyncio.run(self.juju_paas_connector.instantiate("nsr_id", "nslcmop_id"))
+
+    def test_terminate(self):
+        asyncio.run(self.juju_paas_connector.terminate("nsr_id", "nslcmop_id"))
+
+    def test_action(self):
+        with self.assertRaises(NotImplementedError):
+            asyncio.run(self.juju_paas_connector.action("nsr_id", "nslcmop_id"))
diff --git a/osm_lcm/tests/test_paas_service.py b/osm_lcm/tests/test_paas_service.py
new file mode 100644 (file)
index 0000000..668c364
--- /dev/null
@@ -0,0 +1,648 @@
+# Copyright 2022 Canonical Ltd.
+#
+# 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 asynctest
+import asyncio
+from copy import deepcopy
+from unittest import TestCase
+from unittest.mock import Mock, patch, call
+from osm_lcm.lcm_utils import TaskRegistry
+from osm_common import msgbase
+from osm_common.dbbase import DbException
+from osm_lcm.paas_service import (
+    paas_service_factory,
+    JujuPaasService,
+    PaasServiceException,
+)
+from osm_lcm.paas_conn import JujuPaasConnector
+
+
+class CopyingMock(Mock):
+    def __call__(self, *args, **kwargs):
+        args = deepcopy(args)
+        kwargs = deepcopy(kwargs)
+        return super(CopyingMock, self).__call__(*args, **kwargs)
+
+
+@patch("osm_lcm.lcm_utils.Database")
+@patch("osm_lcm.lcm_utils.Filesystem")
+class TestPaasServiceFactory(TestCase):
+    def test_paas_service_factory_default_param_is_juju(self, mock_fs, mock_db):
+        service = paas_service_factory(
+            Mock(), Mock(), Mock(), Mock(), Mock(), Mock(), Mock()
+        )
+        assert isinstance(service, JujuPaasService)
+
+    def test_paas_service_factory(self, mock_fs, mock_db):
+
+        service = paas_service_factory(
+            Mock(), Mock(), Mock(), Mock(), Mock(), Mock(), Mock(), "juju"
+        )
+        assert isinstance(service, JujuPaasService)
+
+    def test_paas_service_factory_not_existing_type(self, mock_fs, mock_db):
+        with self.assertRaises(PaasServiceException):
+            paas_service_factory(
+                Mock(), Mock(), Mock(), Mock(), Mock(), Mock(), Mock(), "other"
+            )
+
+
+class TestJujuPaasService(TestCase):
+    @patch("osm_lcm.lcm_utils.Database")
+    @patch("osm_lcm.lcm_utils.Filesystem")
+    def setUp(self, mock_fs, mock_db):
+        self.msg = Mock(msgbase.MsgBase())
+        self.set_lcm_tasks_mock_behavior()
+        loop = asyncio.new_event_loop()
+        asyncio.set_event_loop(loop)
+        self.loop = asyncio.get_event_loop()
+        self.logger = Mock()
+        self.juju_paas_service = JujuPaasService(
+            self.msg, self.lcm_tasks, Mock(), Mock(), self.loop, self.logger, Mock()
+        )
+        self.juju_paas_service.db = Mock()
+        self.task = Mock()
+        self.task.cancelled.return_value = False
+        self.task.exception.return_value = None
+        self.juju_paas_service.logger = asynctest.Mock(self.juju_paas_service.logger)
+        self.nsr_id = "nsr_id"
+        self.nslcmop_id = "nslcmop_id"
+        self.time_value = 12
+
+        self.before_instantiate_ns_upd = {
+            "detailed-status": "creating",
+            "operational-status": "init",
+            "_admin.nslcmop": self.nslcmop_id,
+            "_admin.current-operation": self.nslcmop_id,
+            "_admin.operation-type": "INSTANTIATING",
+            "currentOperation": "INSTANTIATING",
+            "currentOperationID": self.nslcmop_id,
+            "errorDescription": None,
+            "errorDetail": None,
+            "nsState": "BUILDING",
+            "_admin.modified": self.time_value,
+        }
+
+        self.before_instantiate_op_upd = {
+            "queuePosition": 0,
+            "stage": "Building",
+            "_admin.modified": self.time_value,
+        }
+
+        self.before_terminate_ns_upd = {
+            "detailed-status": "terminating",
+            "operational-status": "terminate",
+            "_admin.nslcmop": self.nslcmop_id,
+            "_admin.current-operation": self.nslcmop_id,
+            "_admin.operation-type": "TERMINATING",
+            "currentOperation": "TERMINATING",
+            "currentOperationID": self.nslcmop_id,
+            "errorDescription": None,
+            "errorDetail": None,
+            "nsState": "TERMINATING",
+            "_admin.modified": self.time_value,
+        }
+
+        self.before_terminate_op_upd = {
+            "queuePosition": 0,
+            "stage": "terminating",
+            "_admin.modified": self.time_value,
+        }
+
+    def set_lcm_tasks_mock_behavior(self):
+        self.lcm_tasks = asynctest.Mock(TaskRegistry())
+        self.lcm_tasks.lock_HA.return_value = True
+        self.lcm_tasks.waitfor_related_HA.return_value = None
+
+    def call_instantiate(self):
+        self.loop.run_until_complete(
+            self.juju_paas_service.instantiate(self.nsr_id, self.nslcmop_id)
+        )
+
+    def call_terminate(self):
+        self.loop.run_until_complete(
+            self.juju_paas_service.terminate(self.nsr_id, self.nslcmop_id)
+        )
+
+    def check_db_update(self, expected_calls):
+        self.juju_paas_service.db.set_one.assert_has_calls(expected_calls)
+
+    def config_instantiate_test(self, paas_mock_time, lcm_mock_time):
+        nsr = {"_id": self.nsr_id}
+        self.juju_paas_service.db.get_one.return_value = nsr
+        self.juju_paas_service.paas_connector = Mock()
+        self.juju_paas_service.db.set_one = CopyingMock()
+        paas_mock_time.return_value = 0
+        lcm_mock_time.return_value = self.time_value
+
+    def config_terminate_test(self, paas_mock_time, lcm_mock_time):
+        nsr = {"_id": self.nsr_id}
+        nslcmop = {"_id": self.nslcmop_id}
+        self.juju_paas_service.paas_connector = Mock()
+        self.juju_paas_service.db.get_one.side_effect = [nsr, nslcmop]
+        self.juju_paas_service.db.set_one = CopyingMock()
+        paas_mock_time.return_value = 0
+        lcm_mock_time.return_value = self.time_value
+
+    def instantiate_expected_calls(self, ensure_future_mock, kafka_msg):
+        self.juju_paas_service.db.get_one.assert_called_with(
+            "nsrs", {"_id": self.nsr_id}
+        )
+        self.lcm_tasks.waitfor_related_HA.assert_called_with(
+            "ns", "nslcmops", self.nslcmop_id
+        )
+        ensure_future_mock.assert_called_once_with(
+            self.juju_paas_service.paas_connector.instantiate()
+        )
+
+        self.juju_paas_service.msg.aiowrite.assert_called_with(
+            "ns", "instantiated", kafka_msg, loop=self.juju_paas_service.loop
+        )
+        self.juju_paas_service.lcm_tasks.remove.assert_called_with(
+            "ns", self.nsr_id, self.nslcmop_id, "ns_instantiate"
+        )
+
+    def terminate_expected_calls(self, ensure_future_mock, kafka_msg):
+        self.juju_paas_service.db.get_one.assert_has_calls(
+            [
+                call("nsrs", {"_id": self.nsr_id}),
+                call("nslcmops", {"_id": self.nslcmop_id}),
+            ]
+        )
+        self.lcm_tasks.waitfor_related_HA.assert_called_with(
+            "ns", "nslcmops", self.nslcmop_id
+        )
+        ensure_future_mock.assert_called_once_with(
+            self.juju_paas_service.paas_connector.terminate()
+        )
+        self.juju_paas_service.msg.aiowrite.assert_called_with(
+            "ns", "terminated", kafka_msg, loop=self.juju_paas_service.loop
+        )
+        self.juju_paas_service.lcm_tasks.remove.assert_called_with(
+            "ns", self.nsr_id, self.nslcmop_id, "ns_terminate"
+        )
+
+    def test_paas_connector_is_juju(self):
+        assert isinstance(self.juju_paas_service.paas_connector, JujuPaasConnector)
+
+    @patch("osm_lcm.paas_service.asyncio.ensure_future")
+    def test_paas_service_instantiate_lock_ha_returns_false(self, ensure_future_mock):
+        self.lcm_tasks.lock_HA.return_value = False
+        self.call_instantiate()
+        self.lcm_tasks.waitfor_related_HA.assert_not_called()
+        self.juju_paas_service.db.set_one.assert_not_called()
+        self.juju_paas_service.db.get_one.assert_not_called()
+        ensure_future_mock.assert_not_called()
+        self.juju_paas_service.lcm_tasks.register.assert_not_called()
+        self.juju_paas_service.msg.aiowrite.assert_not_called()
+        self.juju_paas_service.lcm_tasks.remove.assert_not_called()
+
+    @patch("osm_lcm.paas_service.asyncio.ensure_future")
+    def test_paas_service_terminate_lock_ha_returns_false(self, ensure_future_mock):
+        self.lcm_tasks.lock_HA.return_value = False
+        self.call_terminate()
+        self.lcm_tasks.waitfor_related_HA.assert_not_called()
+        self.juju_paas_service.db.set_one.assert_not_called()
+        self.juju_paas_service.db.get_one.assert_not_called()
+        ensure_future_mock.assert_not_called()
+        self.juju_paas_service.lcm_tasks.register.assert_not_called()
+        self.juju_paas_service.msg.aiowrite.assert_not_called()
+        self.juju_paas_service.lcm_tasks.remove.assert_not_called()
+
+    @patch("osm_lcm.paas_service.asyncio.ensure_future")
+    def test_instantiate_nsrs_does_not_exist_on_db(self, ensure_future_mock):
+
+        self.juju_paas_service.db.get_one.side_effect = DbException("failed")
+        with self.assertRaises(DbException):
+            self.call_instantiate()
+        self.lcm_tasks.waitfor_related_HA.assert_not_called()
+        self.juju_paas_service.db.set_one.assert_not_called()
+        ensure_future_mock.assert_not_called()
+        self.juju_paas_service.lcm_tasks.register.assert_not_called()
+        self.juju_paas_service.msg.aiowrite.assert_not_called()
+        self.juju_paas_service.lcm_tasks.remove.assert_not_called()
+
+    @patch("osm_lcm.lcm_utils.time")
+    @patch("osm_lcm.paas_service.time")
+    @patch("osm_lcm.paas_service.asyncio.ensure_future")
+    @patch("osm_lcm.paas_service.asyncio.wait")
+    def test_instantiate(
+        self, mock_await, ensure_future_mock, paas_mock_time, lcm_mock_time
+    ):
+        self.config_instantiate_test(paas_mock_time, lcm_mock_time)
+        ensure_future_mock.return_value = self.task
+        mock_await.return_value = [self.task], []
+
+        ns_instanciated_upd = {
+            "_admin.nsState": "INSTANTIATED",
+            "_admin.modified": self.time_value,
+        }
+
+        pending_tasks_before_loop_upd = {
+            "queuePosition": 0,
+            "stage": "Waiting for instantiate pending tasks.: 0/1",
+            "_admin.modified": self.time_value,
+        }
+
+        pending_tasks_during_loop_upd = {
+            "queuePosition": 0,
+            "stage": "Waiting for instantiate pending tasks.: 1/1",
+            "_admin.modified": self.time_value,
+        }
+
+        kafka_msg = {
+            "nsr_id": self.nsr_id,
+            "nslcmop_id": self.nslcmop_id,
+            "operationState": "COMPLETED",
+        }
+
+        after_instantiate_ns_upd = {
+            "operational-status": "running",
+            "detailed-status": "Done",
+            "_admin.nslcmop": None,
+            "_admin.current-operation": None,
+            "_admin.operation-type": None,
+            "currentOperation": "IDLE",
+            "currentOperationID": None,
+            "errorDescription": None,
+            "errorDetail": None,
+            "nsState": "READY",
+            "_admin.modified": self.time_value,
+        }
+
+        after_instantiate_op_upd = {
+            "detailed-status": "Done",
+            "queuePosition": 0,
+            "stage": "COMPLETED",
+            "operationState": "COMPLETED",
+            "statusEnteredTime": 0,
+            "_admin.modified": self.time_value,
+        }
+
+        self.call_instantiate()
+        self.juju_paas_service.logger.error.assert_not_called()
+        self.juju_paas_service.logger.exception().assert_not_called()
+
+        db_update_expected_calls = [
+            call("nsrs", {"_id": self.nsr_id}, self.before_instantiate_ns_upd),
+            call("nslcmops", {"_id": self.nslcmop_id}, self.before_instantiate_op_upd),
+            call("nsrs", {"_id": self.nsr_id}, ns_instanciated_upd),
+            call("nslcmops", {"_id": self.nslcmop_id}, pending_tasks_before_loop_upd),
+            call("nslcmops", {"_id": self.nslcmop_id}, pending_tasks_during_loop_upd),
+            call("nsrs", {"_id": self.nsr_id}, after_instantiate_ns_upd),
+            call("nslcmops", {"_id": self.nslcmop_id}, after_instantiate_op_upd),
+        ]
+
+        self.check_db_update(db_update_expected_calls)
+
+        self.juju_paas_service.lcm_tasks.register.assert_called_with(
+            "ns",
+            self.nsr_id,
+            self.nslcmop_id,
+            "instantiate_juju_paas_service",
+            self.task,
+        )
+        self.instantiate_expected_calls(ensure_future_mock, kafka_msg)
+
+    @patch("osm_lcm.lcm_utils.time")
+    @patch("osm_lcm.paas_service.time")
+    @patch("osm_lcm.paas_service.asyncio.ensure_future")
+    @patch("osm_lcm.paas_service.asyncio.wait")
+    def test_instantiate_with_exception(
+        self, mock_await, ensure_future_mock, paas_mock_time, lcm_mock_time
+    ):
+        self.config_instantiate_test(paas_mock_time, lcm_mock_time)
+        ensure_future_mock.side_effect = asyncio.CancelledError
+        mock_await.return_value = [self.task], []
+
+        kafka_msg = {
+            "nsr_id": self.nsr_id,
+            "nslcmop_id": self.nslcmop_id,
+            "operationState": "FAILED",
+        }
+
+        after_instantiate_ns_upd = {
+            "operational-status": "running",
+            "detailed-status": "Operation: instantiate.nslcmop_id Detail: Operation was cancelled",
+            "_admin.nslcmop": None,
+            "_admin.current-operation": None,
+            "_admin.operation-type": None,
+            "currentOperation": "IDLE",
+            "currentOperationID": None,
+            "errorDescription": "Operation: instantiate.nslcmop_id",
+            "errorDetail": "Operation was cancelled",
+            "nsState": "BROKEN",
+            "_admin.modified": self.time_value,
+        }
+
+        after_instantiate_op_upd = {
+            "detailed-status": "Operation was cancelled",
+            "queuePosition": 0,
+            "stage": "FAILED",
+            "errorMessage": "Detail: Operation was cancelled",
+            "operationState": "FAILED",
+            "statusEnteredTime": 0,
+            "_admin.modified": self.time_value,
+        }
+
+        self.call_instantiate()
+        db_update_expected_calls = [
+            call("nsrs", {"_id": "nsr_id"}, self.before_instantiate_ns_upd),
+            call("nslcmops", {"_id": "nslcmop_id"}, self.before_instantiate_op_upd),
+            call("nsrs", {"_id": "nsr_id"}, after_instantiate_ns_upd),
+            call("nslcmops", {"_id": "nslcmop_id"}, after_instantiate_op_upd),
+        ]
+
+        self.check_db_update(db_update_expected_calls)
+        self.juju_paas_service.lcm_tasks.register.assert_not_called()
+        self.instantiate_expected_calls(ensure_future_mock, kafka_msg)
+
+    @patch("osm_lcm.lcm_utils.time")
+    @patch("osm_lcm.paas_service.time")
+    @patch("osm_lcm.paas_service.asyncio.ensure_future")
+    @patch("osm_lcm.paas_service.asyncio.wait")
+    def test_instantiate_timeout(
+        self, mock_await, ensure_future_mock, paas_mock_time, lcm_mock_time
+    ):
+        self.config_instantiate_test(paas_mock_time, lcm_mock_time)
+        ensure_future_mock.return_value = self.task
+        mock_await.return_value = [], [self.task]  # Set timeout
+
+        ns_instanciated_upd = {
+            "_admin.nsState": "INSTANTIATED",
+            "_admin.modified": self.time_value,
+        }
+
+        pending_tasks_before_loop_upd = {
+            "queuePosition": 0,
+            "stage": "Waiting for instantiate pending tasks.: 0/1",
+            "_admin.modified": self.time_value,
+        }
+
+        kafka_msg = {
+            "nsr_id": self.nsr_id,
+            "nslcmop_id": self.nslcmop_id,
+            "operationState": "FAILED",
+        }
+
+        after_instantiate_ns_upd = {
+            "operational-status": "running",
+            "detailed-status": "Operation: instantiate.nslcmop_id Detail: Instantiate juju PaaS Service: Timeout",
+            "_admin.nslcmop": None,
+            "_admin.current-operation": None,
+            "_admin.operation-type": None,
+            "currentOperation": "IDLE",
+            "currentOperationID": None,
+            "errorDescription": "Operation: instantiate.nslcmop_id",
+            "errorDetail": "Instantiate juju PaaS Service: Timeout",
+            "nsState": "BROKEN",
+            "_admin.modified": self.time_value,
+        }
+
+        after_instantiate_op_upd = {
+            "detailed-status": "Instantiate juju PaaS Service: Timeout",
+            "queuePosition": 0,
+            "stage": "FAILED",
+            "errorMessage": "Detail: Instantiate juju PaaS Service: Timeout",
+            "operationState": "FAILED",
+            "statusEnteredTime": 0,
+            "_admin.modified": self.time_value,
+        }
+
+        self.call_instantiate()
+        db_update_expected_calls = [
+            call("nsrs", {"_id": "nsr_id"}, self.before_instantiate_ns_upd),
+            call("nslcmops", {"_id": "nslcmop_id"}, self.before_instantiate_op_upd),
+            call("nsrs", {"_id": "nsr_id"}, ns_instanciated_upd),
+            call("nslcmops", {"_id": "nslcmop_id"}, pending_tasks_before_loop_upd),
+            call("nsrs", {"_id": "nsr_id"}, after_instantiate_ns_upd),
+            call("nslcmops", {"_id": "nslcmop_id"}, after_instantiate_op_upd),
+        ]
+        self.check_db_update(db_update_expected_calls)
+        self.juju_paas_service.lcm_tasks.register.assert_called_with(
+            "ns",
+            self.nsr_id,
+            self.nslcmop_id,
+            "instantiate_juju_paas_service",
+            self.task,
+        )
+        self.instantiate_expected_calls(ensure_future_mock, kafka_msg)
+
+    @patch("osm_lcm.lcm_utils.time")
+    @patch("osm_lcm.paas_service.time")
+    @patch("osm_lcm.paas_service.asyncio.ensure_future")
+    @patch("osm_lcm.paas_service.asyncio.wait")
+    def test_terminate(
+        self, mock_await, ensure_future_mock, paas_mock_time, lcm_mock_time
+    ):
+        self.config_terminate_test(paas_mock_time, lcm_mock_time)
+        ensure_future_mock.return_value = self.task
+        mock_await.return_value = [self.task], []
+
+        ns_terminate_upd = {
+            "_admin.nsState": "TERMINATED",
+            "_admin.modified": self.time_value,
+        }
+
+        pending_tasks_before_loop_upd = {
+            "queuePosition": 0,
+            "stage": "Waiting for pending tasks for termination.: 0/1",
+            "_admin.modified": self.time_value,
+        }
+
+        pending_tasks_during_loop_upd = {
+            "queuePosition": 0,
+            "stage": "Waiting for pending tasks for termination.: 1/1",
+            "_admin.modified": self.time_value,
+        }
+
+        after_terminate_ns_upd = {
+            "detailed-status": "Done",
+            "operational-status": "terminated",
+            "_admin.nsState": "NOT_INSTANTIATED",
+            "_admin.nslcmop": None,
+            "_admin.current-operation": None,
+            "_admin.operation-type": None,
+            "currentOperation": "IDLE",
+            "currentOperationID": None,
+            "errorDescription": None,
+            "errorDetail": None,
+            "nsState": "NOT_INSTANTIATED",
+            "_admin.modified": self.time_value,
+        }
+
+        after_terminate_op_upd = {
+            "detailed-status": "Done",
+            "queuePosition": 0,
+            "stage": "COMPLETED",
+            "operationState": "COMPLETED",
+            "statusEnteredTime": 0,
+            "_admin.modified": self.time_value,
+        }
+
+        kafka_msg = {
+            "nsr_id": self.nsr_id,
+            "nslcmop_id": self.nslcmop_id,
+            "operationState": "COMPLETED",
+            "autoremove": False,
+        }
+
+        self.call_terminate()
+
+        self.juju_paas_service.logger.error.assert_not_called()
+        self.juju_paas_service.logger.exception().assert_not_called()
+
+        db_update_expected_calls = [
+            call("nsrs", {"_id": self.nsr_id}, self.before_terminate_ns_upd),
+            call("nslcmops", {"_id": self.nslcmop_id}, self.before_terminate_op_upd),
+            call("nsrs", {"_id": self.nsr_id}, ns_terminate_upd),
+            call("nslcmops", {"_id": self.nslcmop_id}, pending_tasks_before_loop_upd),
+            call("nslcmops", {"_id": self.nslcmop_id}, pending_tasks_during_loop_upd),
+            call("nsrs", {"_id": self.nsr_id}, after_terminate_ns_upd),
+            call("nslcmops", {"_id": self.nslcmop_id}, after_terminate_op_upd),
+        ]
+        self.check_db_update(db_update_expected_calls)
+
+        self.juju_paas_service.lcm_tasks.register.assert_called_with(
+            "ns", self.nsr_id, self.nslcmop_id, "terminate_juju_paas_service", self.task
+        )
+        self.terminate_expected_calls(ensure_future_mock, kafka_msg)
+
+    @patch("osm_lcm.lcm_utils.time")
+    @patch("osm_lcm.paas_service.time")
+    @patch("osm_lcm.paas_service.asyncio.ensure_future")
+    @patch("osm_lcm.paas_service.asyncio.wait")
+    def test_terminate_exception(
+        self, mock_await, ensure_future_mock, paas_mock_time, lcm_mock_time
+    ):
+        self.config_terminate_test(paas_mock_time, lcm_mock_time)
+        ensure_future_mock.side_effect = asyncio.CancelledError
+        mock_await.return_value = [self.task], []
+
+        after_terminate_ns_upd = {
+            "detailed-status": "Operation: terminate.nslcmop_id Detail: Operation was cancelled",
+            "_admin.nslcmop": None,
+            "_admin.current-operation": None,
+            "_admin.operation-type": None,
+            "currentOperation": "IDLE",
+            "currentOperationID": None,
+            "errorDescription": "Operation: terminate.nslcmop_id",
+            "errorDetail": "Operation was cancelled",
+            "nsState": "BROKEN",
+            "_admin.modified": self.time_value,
+        }
+
+        after_terminate_op_upd = {
+            "detailed-status": "Operation was cancelled",
+            "queuePosition": 0,
+            "stage": "FAILED",
+            "errorMessage": "Detail: Operation was cancelled",
+            "operationState": "FAILED",
+            "statusEnteredTime": 0,
+            "_admin.modified": self.time_value,
+        }
+
+        kafka_msg = {
+            "nsr_id": self.nsr_id,
+            "nslcmop_id": self.nslcmop_id,
+            "operationState": "FAILED",
+            "autoremove": False,
+        }
+
+        self.call_terminate()
+
+        db_update_expected_calls = [
+            call("nsrs", {"_id": "nsr_id"}, self.before_terminate_ns_upd),
+            call("nslcmops", {"_id": "nslcmop_id"}, self.before_terminate_op_upd),
+            call("nsrs", {"_id": "nsr_id"}, after_terminate_ns_upd),
+            call("nslcmops", {"_id": "nslcmop_id"}, after_terminate_op_upd),
+        ]
+
+        self.check_db_update(db_update_expected_calls)
+        self.juju_paas_service.lcm_tasks.register.assert_not_called()
+        self.terminate_expected_calls(ensure_future_mock, kafka_msg)
+
+    @patch("osm_lcm.lcm_utils.time")
+    @patch("osm_lcm.paas_service.time")
+    @patch("osm_lcm.paas_service.asyncio.ensure_future")
+    @patch("osm_lcm.paas_service.asyncio.wait")
+    def test_terminate_timeout(
+        self, mock_await, ensure_future_mock, paas_mock_time, lcm_mock_time
+    ):
+        self.config_terminate_test(paas_mock_time, lcm_mock_time)
+        ensure_future_mock.return_value = self.task
+        mock_await.return_value = [], [self.task]  # set timeout
+
+        ns_terminate_upd = {
+            "_admin.nsState": "TERMINATED",
+            "_admin.modified": self.time_value,
+        }
+
+        pending_tasks_before_loop_upd = {
+            "queuePosition": 0,
+            "stage": "Waiting for pending tasks for termination.: 0/1",
+            "_admin.modified": self.time_value,
+        }
+
+        after_terminate_ns_upd = {
+            "detailed-status": "Operation: terminate.nslcmop_id Detail: Terminate juju PaaS Service: Timeout",
+            "_admin.nslcmop": None,
+            "_admin.current-operation": None,
+            "_admin.operation-type": None,
+            "currentOperation": "IDLE",
+            "currentOperationID": None,
+            "errorDescription": "Operation: terminate.nslcmop_id",
+            "errorDetail": "Terminate juju PaaS Service: Timeout",
+            "nsState": "BROKEN",
+            "_admin.modified": self.time_value,
+        }
+
+        after_terminate_op_upd = {
+            "detailed-status": "Terminate juju PaaS Service: Timeout",
+            "queuePosition": 0,
+            "stage": "FAILED",
+            "errorMessage": "Detail: Terminate juju PaaS Service: Timeout",
+            "operationState": "FAILED",
+            "statusEnteredTime": 0,
+            "_admin.modified": self.time_value,
+        }
+
+        kafka_msg = {
+            "nsr_id": self.nsr_id,
+            "nslcmop_id": self.nslcmop_id,
+            "operationState": "FAILED",
+            "autoremove": False,
+        }
+
+        self.call_terminate()
+        db_update_expected_calls = [
+            call("nsrs", {"_id": "nsr_id"}, self.before_terminate_ns_upd),
+            call("nslcmops", {"_id": "nslcmop_id"}, self.before_terminate_op_upd),
+            call("nsrs", {"_id": "nsr_id"}, ns_terminate_upd),
+            call("nslcmops", {"_id": "nslcmop_id"}, pending_tasks_before_loop_upd),
+            call("nsrs", {"_id": "nsr_id"}, after_terminate_ns_upd),
+            call("nslcmops", {"_id": "nslcmop_id"}, after_terminate_op_upd),
+        ]
+
+        self.check_db_update(db_update_expected_calls)
+        self.juju_paas_service.lcm_tasks.register.assert_called_with(
+            "ns", self.nsr_id, self.nslcmop_id, "terminate_juju_paas_service", self.task
+        )
+        self.terminate_expected_calls(ensure_future_mock, kafka_msg)
+
+    def test_action(self):
+        with self.assertRaises(NotImplementedError):
+            self.loop.run_until_complete(
+                self.juju_paas_service.action(self.nsr_id, self.nslcmop_id)
+            )