Add ocloud watcher and tests 60/6960/5
authorBin Yang <bin.yang@windriver.com>
Thu, 28 Oct 2021 11:55:47 +0000 (19:55 +0800)
committerBin Yang <bin.yang@windriver.com>
Fri, 29 Oct 2021 01:50:44 +0000 (01:50 +0000)
Issue-ID: INF-196
Signed-off-by: Bin Yang <bin.yang@windriver.com>
Change-Id: I3c0fb09913f5a064e84cecc3f6fdb6072c58be5a

o2ims/adapter/ocloud_repository.py
o2ims/domain/stx_object.py
o2ims/service/auditor/__init__.py [new file with mode: 0644]
o2ims/service/auditor/base.py [new file with mode: 0644]
o2ims/service/watcher/__init__.py [new file with mode: 0644]
o2ims/service/watcher/base.py [new file with mode: 0644]
tests/conftest.py
tests/integration/test_clientdriver_fake_stx_sa.py
tests/unit/test_watcher.py [new file with mode: 0644]

index 8a547fe..ca90209 100644 (file)
@@ -13,7 +13,7 @@
 #  limitations under the License.
 
 import abc
-from typing import Set
+from typing import List, Set
 # from o2ims.adapter import orm
 from o2ims.domain import ocloud
 
@@ -32,6 +32,9 @@ class OcloudRepository(abc.ABC):
             self.seen.add(ocloud)
         return ocloud
 
+    def list(self) -> List[ocloud.Ocloud]:
+        return self._list()
+
     def update(self, ocloud: ocloud.Ocloud):
         self._update(ocloud)
 
@@ -64,18 +67,8 @@ class OcloudSqlAlchemyRepository(OcloudRepository):
         return self.session.query(ocloud.Ocloud).filter_by(
             oCloudId=ocloudid).first()
 
+    def _list(self) -> List[ocloud.Ocloud]:
+        return self.session.query()
+
     def _update(self, ocloud: ocloud.Ocloud):
         self.session.add(ocloud)
-
-    # def _update_fields(self, ocloudid: str, updatefields: dict):
-    #     dmslist = updatefields.pop("deploymentManagers", None)
-    #     if dmslist:
-    #         self._update_dms_list(dmslist)
-    #     if updatefields:
-    #         self.session.query(ocloud.Ocloud).filter_by(
-    # oCloudId=ocloudid).update(updatefields)
-
-    # def _update_dms_list(self, dms_list: list):
-    #     for dms in dms_list or []:
-    #         self.session.query(ocloud.DeploymentManager).filter_by(
-    # deploymentManagerId=dms.deploymentManagerId).update(dms)
index 0a17092..7345694 100644 (file)
 #  limitations under the License.\r
 \r
 # from dataclasses import dataclass\r
-import datetime\r
+import datetime\r
 import json\r
 \r
 \r
+class MismatchedModel(Exception):\r
+    pass\r
+\r
+\r
 class StxGenericModel:\r
     def __init__(self, api_response: dict = None) -> None:\r
         if api_response:\r
@@ -26,12 +30,14 @@ class StxGenericModel:
             self.createtime = api_response.created_at\r
             self.name = api_response.name\r
 \r
-    # def __init__(self, id: str, name: str,\r
-    #              lastupdate: datetime, content: str) -> None:\r
-    #     self.id = id\r
-    #     self.name = name\r
-    #     self.lastupdate = lastupdate\r
-    #     self.content = content\r
+    def is_outdated(self, newmodel) -> bool:\r
+        return self.updatetime < newmodel.updatetime\r
+\r
+    def update_by(self, newmodel) -> None:\r
+        if self.id != newmodel.id:\r
+            raise MismatchedModel("Mismatched model")\r
+        self.name = newmodel.name\r
 \r
-    def isChanged(self, updatetime: datetime) -> bool:\r
-        return True if self.updatetime > updatetime else False\r
+        self.content = newmodel.content\r
+        self.createtime = newmodel.createtime\r
+        self.updatetime = newmodel.updatetime\r
diff --git a/o2ims/service/auditor/__init__.py b/o2ims/service/auditor/__init__.py
new file mode 100644 (file)
index 0000000..b514342
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright (C) 2021 Wind River Systems, Inc.\r
+#\r
+#  Licensed under the Apache License, Version 2.0 (the "License");\r
+#  you may not use this file except in compliance with the License.\r
+#  You may obtain a copy of the License at\r
+#\r
+#      http://www.apache.org/licenses/LICENSE-2.0\r
+#\r
+#  Unless required by applicable law or agreed to in writing, software\r
+#  distributed under the License is distributed on an "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+#  See the License for the specific language governing permissions and\r
+#  limitations under the License.\r
diff --git a/o2ims/service/auditor/base.py b/o2ims/service/auditor/base.py
new file mode 100644 (file)
index 0000000..b514342
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright (C) 2021 Wind River Systems, Inc.\r
+#\r
+#  Licensed under the Apache License, Version 2.0 (the "License");\r
+#  you may not use this file except in compliance with the License.\r
+#  You may obtain a copy of the License at\r
+#\r
+#      http://www.apache.org/licenses/LICENSE-2.0\r
+#\r
+#  Unless required by applicable law or agreed to in writing, software\r
+#  distributed under the License is distributed on an "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+#  See the License for the specific language governing permissions and\r
+#  limitations under the License.\r
diff --git a/o2ims/service/watcher/__init__.py b/o2ims/service/watcher/__init__.py
new file mode 100644 (file)
index 0000000..b514342
--- /dev/null
@@ -0,0 +1,13 @@
+# Copyright (C) 2021 Wind River Systems, Inc.\r
+#\r
+#  Licensed under the Apache License, Version 2.0 (the "License");\r
+#  you may not use this file except in compliance with the License.\r
+#  You may obtain a copy of the License at\r
+#\r
+#      http://www.apache.org/licenses/LICENSE-2.0\r
+#\r
+#  Unless required by applicable law or agreed to in writing, software\r
+#  distributed under the License is distributed on an "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+#  See the License for the specific language governing permissions and\r
+#  limitations under the License.\r
diff --git a/o2ims/service/watcher/base.py b/o2ims/service/watcher/base.py
new file mode 100644 (file)
index 0000000..4ea23ff
--- /dev/null
@@ -0,0 +1,68 @@
+# Copyright (C) 2021 Wind River Systems, Inc.\r
+#\r
+#  Licensed under the Apache License, Version 2.0 (the "License");\r
+#  you may not use this file except in compliance with the License.\r
+#  You may obtain a copy of the License at\r
+#\r
+#      http://www.apache.org/licenses/LICENSE-2.0\r
+#\r
+#  Unless required by applicable law or agreed to in writing, software\r
+#  distributed under the License is distributed on an "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+#  See the License for the specific language governing permissions and\r
+#  limitations under the License.\r
+\r
+from o2ims.service.client.base_client import BaseClient\r
+from o2ims.domain.stx_object import StxGenericModel\r
+from o2ims.adapter.ocloud_repository import OcloudRepository\r
+\r
+\r
+class InvalidOcloudState(Exception):\r
+    pass\r
+\r
+\r
+class BaseWatcher(object):\r
+    def __init__(self, client: BaseClient) -> None:\r
+        super().__init__()\r
+        self._client = client\r
+\r
+    def probe(self):\r
+        self._probe()\r
+\r
+    def _probe(self):\r
+        pass\r
+\r
+\r
+class OcloudWather(BaseWatcher):\r
+    def __init__(self, ocloud_client: BaseClient,\r
+                 repo: OcloudRepository) -> None:\r
+        super().__init__(ocloud_client)\r
+        self._repo = repo\r
+\r
+    def _probe(self):\r
+        ocloudmodel = self._client.get(None)\r
+        if ocloudmodel:\r
+            self._compare_and_update(ocloudmodel)\r
+\r
+    def _compare_and_update(self, ocloudmodel: StxGenericModel) -> bool:\r
+        # localmodel = self._repo.get(ocloudmodel.id)\r
+        oclouds = self._repo.list()\r
+        if len(oclouds) > 1:\r
+            raise InvalidOcloudState("More than 1 ocloud is found")\r
+        if len(oclouds) == 0:\r
+            self._repo.add(ocloudmodel)\r
+        else:\r
+            localmodel = oclouds.pop()\r
+            if localmodel.is_outdated(ocloudmodel):\r
+                localmodel.update_by(ocloudmodel)\r
+                self._repo.update(localmodel)\r
+\r
+\r
+class ResourcePoolWatcher(object):\r
+    def __init__(self) -> None:\r
+        super().__init__()\r
+\r
+\r
+class ResourceWatcher(object):\r
+    def __init__(self) -> None:\r
+        super().__init__()\r
index c6b0904..211ad3e 100644 (file)
@@ -14,6 +14,7 @@ from tenacity import retry, stop_after_delay
 from o2ims.adapter.orm import metadata, start_o2ims_mappers\r
 from o2ims.adapter.clients.orm_stx import start_o2ims_stx_mappers\r
 from o2ims import config\r
+from o2ims.domain import stx_object as ocloudModel\r
 \r
 \r
 @pytest.fixture\r
@@ -36,9 +37,6 @@ def mappers():
     yield\r
     clear_mappers()\r
 \r
-@pytest.fixture\r
-def fake_stx_client():\r
-    pass\r
 \r
 @retry(stop=stop_after_delay(10))\r
 def wait_for_postgres_to_come_up(engine):\r
index 177546c..8f262b8 100644 (file)
@@ -26,6 +26,7 @@ from o2ims.domain import stx_object as ocloudModel
 \r
 # pytestmark = pytest.mark.usefixtures("mappers")\r
 \r
+\r
 class FakeStxSaClientImp(object):\r
     def __init__(self):\r
         super().__init__()\r
diff --git a/tests/unit/test_watcher.py b/tests/unit/test_watcher.py
new file mode 100644 (file)
index 0000000..ec28519
--- /dev/null
@@ -0,0 +1,71 @@
+# Copyright (C) 2021 Wind River Systems, Inc.\r
+#\r
+#  Licensed under the Apache License, Version 2.0 (the "License");\r
+#  you may not use this file except in compliance with the License.\r
+#  You may obtain a copy of the License at\r
+#\r
+#      http://www.apache.org/licenses/LICENSE-2.0\r
+#\r
+#  Unless required by applicable law or agreed to in writing, software\r
+#  distributed under the License is distributed on an "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+#  See the License for the specific language governing permissions and\r
+#  limitations under the License.\r
+\r
+from datetime import datetime\r
+import json\r
+from typing import List\r
+from o2ims.service.client.base_client import BaseClient\r
+import pytest\r
+from o2ims.domain import ocloud\r
+from o2ims import config\r
+import uuid\r
+from o2ims.service.watcher.base import OcloudWather\r
+from o2ims.domain import stx_object as ocloudModel\r
+from o2ims.adapter.ocloud_repository import OcloudRepository\r
+\r
+class FakeOcloudClient(BaseClient):\r
+    def __init__(self):\r
+        super().__init__()\r
+        fakeCloud = ocloudModel.StxGenericModel()\r
+        fakeCloud.id = uuid.uuid4()\r
+        fakeCloud.name = 'stx1'\r
+        fakeCloud.content = json.dumps({})\r
+        fakeCloud.createtime = datetime.now()\r
+        fakeCloud.updatetime = datetime.now\r
+        self.fakeCloud = fakeCloud\r
+\r
+    def _get(self, id) -> ocloudModel.StxGenericModel:\r
+        return self.fakeCloud\r
+\r
+    def _list(self):\r
+        return [self.fakeCloud]\r
+\r
+class FakeOcloudRepo(OcloudRepository):\r
+    def __init__(self):\r
+        super().__init__()\r
+        self.oclouds = []\r
+\r
+    def _add(self, ocloud: ocloud.Ocloud):\r
+        self.oclouds.append(ocloud)\r
+\r
+    def _get(self, ocloudid) -> ocloud.Ocloud:\r
+        filtered = [o for o in self.oclouds if o.id == ocloudid]\r
+        return filtered.pop()\r
+\r
+    def _list(self) -> List[ocloud.Ocloud]:\r
+        return [x for x in self.oclouds]\r
+\r
+    def _update(self, ocloud: ocloud.Ocloud):\r
+        filtered = [o for o in self.oclouds if o.id == ocloud.id]\r
+        assert len(filtered) == 1\r
+        ocloud1 = filtered.pop()\r
+        ocloud1.update_by(ocloud)\r
+\r
+def test_probe_new_ocloud():\r
+    fakeRepo = FakeOcloudRepo()\r
+    fakeClient = FakeOcloudClient()\r
+    ocloudwatcher = OcloudWather(fakeClient, fakeRepo)\r
+    ocloudwatcher.probe()\r
+    assert len(fakeRepo.oclouds) == 1\r
+    assert fakeRepo.oclouds[0].name == "stx1"\r