Merge "Fix SqlAlchemy version upgrade issue"
authorJon Zhang <rong.zhang@windriver.com>
Tue, 9 May 2023 12:35:12 +0000 (12:35 +0000)
committerGerrit Code Review <gerrit@o-ran-sc.org>
Tue, 9 May 2023 12:35:12 +0000 (12:35 +0000)
charts/templates/deployment.yaml
charts/values.yaml
o2ims/adapter/clients/ocloud_client.py
o2ims/domain/ocloud.py
o2ims/domain/resource_type.py
o2ims/domain/stx_object.py
o2ims/service/auditor/dms_handler.py
o2ims/views/ocloud_dto.py
tests/integration-ocloud/test_clientdriver_stx.py
tests/locust/README.md
tests/locust/ocloud.py

index a5deaf6..72e3580 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2021 Wind River Systems, Inc.
+# Copyright (C) 2021-2023 Wind River Systems, Inc.
 #
 #  Licensed under the Apache License, Version 2.0 (the "License");
 #  you may not use this file except in compliance with the License.
@@ -29,6 +29,13 @@ spec:
     metadata:
       labels:
         app: o2api
+        {{- with .Values.podLabels }}
+        {{- toYaml . | nindent 8 }}
+        {{- end }}
+      annotations:
+        {{- with .Values.podAnnotations }}
+        {{- toYaml . | nindent 8 }}
+        {{- end }}
     spec:
       serviceAccountName: {{ .Values.o2ims.serviceaccountname }}
       {{- if .Values.imagePullSecrets }}
index aa6a487..0ab6f73 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2021 Wind River Systems, Inc.
+# Copyright (C) 2021-2023 Wind River Systems, Inc.
 #
 #  Licensed under the Apache License, Version 2.0 (the "License");
 #  you may not use this file except in compliance with the License.
@@ -22,6 +22,9 @@ replicaCount: 1
 nameOverride: ""
 fullnameOverride: ""
 
+podLabels: {}
+podAnnotations: {}
+
 # The default value "" doesn't work with binaryData,
 # So generate the value with:
 # echo "" | base64
index 4a87af9..d738d2a 100644 (file)
@@ -15,6 +15,7 @@
 # client talking to Stx standalone
 
 import uuid
+import json
 from typing import List
 # Optional,  Set
 
@@ -333,6 +334,50 @@ class StxClientImp(object):
         return ocloudModel.StxGenericModel(
             ResourceTypeEnum.PSERVER, self._hostconverter(host))
 
+    def _checkLabelExistOnHost(self, label_key, hostid) -> bool:
+        labels = self.stxclient.label.list(hostid)
+        return any(label_key == label.label_key for label in labels)
+
+    def _checkLabelExistOnCluster(self, label_key) -> bool:
+        hosts = self.stxclient.ihost.list()
+
+        def find_label_on_host():
+            result = next(
+                (
+                    (host, True)
+                    for host in hosts
+                    if self._checkLabelExistOnHost(label_key, host.uuid)
+                ),
+                (None, False),
+            )
+
+            if result[1]:
+                logger.info("host %s has the label %s" %
+                            (result[0].hostname, label_key))
+
+            return result[1]
+
+        return find_label_on_host()
+
+        # return any(self._checkLabelExistOnHost(label_key, host.uuid) for host
+        #    in hosts)
+
+    def _setK8sCapabilities(self, k8scluster):
+        capabilities = {}
+        if self._checkLabelExistOnCluster('OS'):
+            logger.debug("low latency host inside of the cluster")
+            capabilities['OS'] = 'low_latency'
+        setattr(k8scluster, 'capabilities', json.dumps(capabilities))
+        return k8scluster
+
+    def getLabelList(self, **filters) -> List[ocloudModel.StxGenericModel]:
+        hostid = filters.get('hostid', None)
+        assert (hostid is not None), 'missing hostid to query label list'
+        labels = self.stxclient.label.list(hostid)
+        return [ocloudModel.StxGenericModel(
+            ResourceTypeEnum.PSERVER_LABEL,
+            self._labelconverter(label)) for label in labels if label]
+
     def getK8sList(self, **filters) -> List[ocloudModel.StxGenericModel]:
         systems = self.stxclient.isystem.list()
         logger.debug('system controller distributed_cloud_role:' +
@@ -342,9 +387,10 @@ class StxClientImp(object):
                 systems[0].distributed_cloud_role != 'systemcontroller':
             k8sclusters = self.stxclient.kube_cluster.list()
             setattr(k8sclusters[0], 'cloud_name', systems[0].name)
-            logger.debug('k8sresources[0]:' + str(k8sclusters[0].to_dict()))
-            # logger.debug('k8sresources[0] cluster_api_endpoint: ' +
-            #  str(k8sclusters[0].cluster_api_endpoint))
+            k8sclusters[0] = self._setK8sCapabilities(k8sclusters[0])
+            # logger.debug('k8sresources[0]:' + str(k8sclusters[0].to_dict()))
+            logger.debug('k8sresources[0] cluster_api_endpoint: ' +
+                         str(k8sclusters[0].cluster_api_endpoint))
             return [ocloudModel.StxGenericModel(
                 ResourceTypeEnum.DMS,
                 self._k8sconverter(k8sres), self._k8shasher(k8sres))
@@ -354,9 +400,10 @@ class StxClientImp(object):
         if config.get_system_controller_as_respool():
             k8sclusters = self.stxclient.kube_cluster.list()
             setattr(k8sclusters[0], 'cloud_name', systems[0].name)
-            logger.debug('k8sresources[0]:' + str(k8sclusters[0].to_dict()))
-            # logger.debug('k8sresources[0] cluster_api_endpoint: ' +
-            #  str(k8sclusters[0].cluster_api_endpoint))
+            k8sclusters[0] = self._setK8sCapabilities(k8sclusters[0])
+            # logger.debug('k8sresources[0]:' + str(k8sclusters[0].to_dict()))
+            logger.debug('k8sresources[0] cluster_api_endpoint: ' +
+                         str(k8sclusters[0].cluster_api_endpoint))
             k8s_list.append(k8sclusters[0])
 
         subclouds = self.getSubcloudList()
@@ -368,6 +415,7 @@ class StxClientImp(object):
                 systems = subcloud_stxclient.isystem.list()
                 k8sclusters = subcloud_stxclient.kube_cluster.list()
                 setattr(k8sclusters[0], 'cloud_name', systems[0].name)
+                k8sclusters[0] = self._setK8sCapabilities(k8sclusters[0])
                 logger.debug('k8sresources[0]:' +
                              str(k8sclusters[0].to_dict()))
                 # logger.debug('k8sresources[0] cluster_api_endpoint: ' +
@@ -388,6 +436,7 @@ class StxClientImp(object):
             k8sclusters = self.stxclient.kube_cluster.list()
             # logger.debug("k8sresources[0]:" + str(k8sclusters[0].to_dict()))
             setattr(k8sclusters[0], 'cloud_name', systems[0].name)
+            k8sclusters[0] = self._setK8sCapabilities(k8sclusters[0])
             k8scluster = k8sclusters.pop()
         else:
             sname = name.split('.')
@@ -396,6 +445,7 @@ class StxClientImp(object):
             if cloud_name == systems[0].name:
                 k8scluster = self.stxclient.kube_cluster.get(k8s_name)
                 setattr(k8scluster, 'cloud_name', cloud_name)
+                k8scluster = self._setK8sCapabilities(k8scluster)
             else:
                 subclouds = self.getSubcloudList()
                 subcloud_id = [
@@ -404,6 +454,7 @@ class StxClientImp(object):
                 subcloud_stxclient = self.getSubcloudClient(subcloud_id)
                 k8scluster = subcloud_stxclient.kube_cluster.get(k8s_name)
                 setattr(k8scluster, 'cloud_name', cloud_name)
+                k8scluster = self._setK8sCapabilities(k8scluster)
                 # logger.debug('k8sresources[0]:' +
                 #  str(k8sclusters[0].to_dict()))
                 # logger.debug('k8sresources[0] cluster_api_endpoint: ' +
@@ -550,6 +601,22 @@ class StxClientImp(object):
         setattr(host, 'name', host.hostname)
         return host
 
+    @ staticmethod
+    def _labelconverter(label):
+        selected_keys = [
+            "uuid", "label_key", "label_value", "host_uuid"
+        ]
+        content = label.to_dict()
+        print(content)
+        filtered = dict(
+            filter(lambda item: item[0] in selected_keys, content.items()))
+        setattr(label, 'filtered', filtered)
+        setattr(label, 'name', label.uuid.split(
+            '-', 1)[0] + '-label-' + label.label_key)
+        setattr(label, 'updated_at', None)
+        setattr(label, 'created_at', None)
+        return label
+
     @ staticmethod
     def _cpuconverter(cpu):
         selected_keys = [
@@ -646,4 +713,5 @@ class StxClientImp(object):
     @ staticmethod
     def _k8shasher(cluster):
         return str(hash((cluster.cluster_name, cluster.cloud_name,
-                         cluster.cluster_api_endpoint, cluster.admin_user)))
+                         cluster.cluster_api_endpoint, cluster.admin_user,
+                         cluster.capabilities)))
index eb4f34b..ee3da89 100644 (file)
@@ -63,6 +63,8 @@ class DeploymentManager(AgRoot, Serializer):
             elif profile == DeploymentManagerProfileSOL018HelmCLI:
                 d['profileSupportList'].append(profile)
 
+        if 'capabilities' in d and d['capabilities'] != '':
+            d['capabilities'] = json.loads(d['capabilities'])
         return d
 
 
index 84b9285..3564cd6 100644 (file)
@@ -14,6 +14,7 @@ class ResourceTypeEnum(Enum):
     PSERVER_ETH = 16
     PSERVER_PCI_DEV = 17
     PSERVER_ACC = 18
+    PSERVER_LABEL = 19
     COMPUTE_AGGREGATE = 70
     NETWORK_AGGREGATE = 80
     STORAGE_AGGREGATE = 90
index 2eee7b7..549c4fc 100644 (file)
@@ -36,14 +36,16 @@ class StxGenericModel(AgRoot):
             self.createtime = datetime.datetime.strptime(
                 api_response.created_at.split('.')[0], "%Y-%m-%dT%H:%M:%S") \
                 if api_response.created_at else None
-            self.hash = content_hash
-            if not self.hash:
-                if hasattr(api_response, 'filtered'):
-                    self.filtered = api_response.filtered
-                    self.hash = str(hash((self.id, str(self.filtered))))
-                else:
-                    self.hash = str(hash((self.id, self.updatetime)))
-            self.content = json.dumps(api_response.to_dict())
+            self.filtered = getattr(api_response, 'filtered', None)
+            self.hash = content_hash or str(
+                hash((self.id, str(self.filtered)
+                      if self.filtered else self.updatetime)))
+
+            def handle_non_serializable(obj):
+                return repr(obj)
+            self.content = json.dumps(
+                vars(api_response), default=handle_non_serializable)
+
             if ResourceTypeEnum.RESOURCE_POOL == type:
                 self.res_pool_id = self.id
 
index f7d5405..11436b9 100644 (file)
@@ -77,10 +77,12 @@ def is_outdated(ocloud: DeploymentManager, stxobj: StxGenericModel):
 def create_by(stxobj: StxGenericModel, parentid: str) -> DeploymentManager:
     description = "A DMS"
     ocloudid = parentid
+    content = json.loads(stxobj.content)
+    # logger.info(stxobj)
+    # logger.info(content)
     supportedLocations = ''
-    capabilities = ''
+    capabilities = content['capabilities']
     capacity = ''
-    content = json.loads(stxobj.content)
     dmsendpoint = content['cluster_api_endpoint']
     profile = _convert_content(content)
     localmodel = DeploymentManager(
@@ -103,13 +105,16 @@ def update_by(target: DeploymentManager, stxobj: StxGenericModel,
               parentid: str) -> None:
     if target.deploymentManagerId != stxobj.id:
         raise MismatchedModel("Mismatched Id")
+    content = json.loads(stxobj.content)
+    logger.info(content)
     target.name = stxobj.name
     target.createtime = stxobj.createtime
     target.updatetime = stxobj.updatetime
     target.hash = stxobj.hash
     target.oCloudId = parentid
+    target.capabilities = content['capabilities']
     target.version_number = target.version_number + 1
-    target.profile = _convert_content(stxobj.content)
+    target.profile = _convert_content(content)
 
     target.events.append(events.DmsChanged(
         id=stxobj.id,
index 3007024..622bc46 100644 (file)
@@ -359,6 +359,14 @@ class ResourceDTO:
 
 class DeploymentManagerDTO:
 
+    capabilities = api_ims_inventory_v1.model(
+        "DeploymentManagerCapabilities", {
+            'OS': fields.String(
+                example='low_latency',
+                description='Show the OS capablities of ' +
+                'the Deployment Manager'),
+        })
+
     deployment_manager_list = api_ims_inventory_v1.model(
         "DeploymentManagerListDto",
         {
@@ -380,11 +388,11 @@ class DeploymentManagerDTO:
                 attribute='serviceUri',
                 example='https://128.224.115.51:6443',
                 description='The fully qualified URI to a Deployment ' +
-                'Management server for O2dms services.'),
+                'Management server for O2dms.'),
             # 'deploymentManagementServiceEndpoint': fields.String(
             # attribute='serviceUri'),
             # 'supportedLocations': fields.String,
-            # 'capabilities': fields.String,
+            'capabilities': fields.Nested(capabilities, True, True),
             # 'capacity': fields.String,
             'profileSupportList': fields.List(
                 fields.String,
@@ -469,11 +477,11 @@ class DeploymentManagerDTO:
                 attribute='serviceUri',
                 example='https://128.224.115.51:6443',
                 description='The fully qualified URI to a Deployment ' +
-                'Management server for O2dms services.'),
+                'Management server for O2dms.'),
             # 'deploymentManagementServiceEndpoint': fields.String(
             # attribute='serviceUri'),
             # 'supportedLocations': fields.String,
-            # 'capabilities': fields.String,
+            'capabilities': fields.Nested(capabilities, True, True),
             # 'capacity': fields.String,
             'extensions': fields.Nested(extensions, True, True)
         },
index 8ca1780..a9f404b 100644 (file)
@@ -89,6 +89,20 @@ def test_get_k8s_list(real_stx_aio_client):
         assert k8s3.id == k8s4.id
 
 
+def test_get_label_list(real_stx_aio_client):
+    stxClientImp = StxClientImp(real_stx_aio_client)
+    assert stxClientImp is not None
+    hostlist = stxClientImp.getPserverList()
+    assert len(hostlist) > 0
+
+    print(hostlist[0].id)
+
+    labellist = stxClientImp.getLabelList(hostid=hostlist[0].id)
+    assert len(labellist) > 0
+    label1 = labellist[0]
+    assert label1.id == "test"
+
+
 def test_get_cpu_list(real_stx_aio_client):
     stxClientImp = StxClientImp(real_stx_aio_client)
     assert stxClientImp is not None
index 21f12f2..d4bf4bb 100644 (file)
@@ -6,29 +6,38 @@ Here is the sample command to run one master worker with 7 sub worker
 
 ```bash
 # main worker:  
-locust -f ocloud.py -H http://128.224.115.34:30205 --master
+export SMO_TOKEN_DATA=<SMO token data>
+locust -f ocloud.py -H https://128.224.115.34:30205 --master
 
 # worker_1:  
+export SMO_TOKEN_DATA=<SMO token data>
 locust -f ocloud.py --worker
 #worker_2:  
+export SMO_TOKEN_DATA=<SMO token data>
 locust -f ocloud.py --worker
 #worker_3:  
+export SMO_TOKEN_DATA=<SMO token data>
 locust -f ocloud.py --worker
 #worker_4:  
+export SMO_TOKEN_DATA=<SMO token data>
 locust -f ocloud.py --worker
 #worker_5:  
+export SMO_TOKEN_DATA=<SMO token data>
 locust -f ocloud.py --worker
 #worker_6:  
+export SMO_TOKEN_DATA=<SMO token data>
 locust -f ocloud.py --worker
 #worker_7:  
+export SMO_TOKEN_DATA=<SMO token data>
 locust -f ocloud.py --worker
 ```
 
 If you can use goreman to run [goreman](github.com/mattn/goreman), feel free to use it.
 
 ```bash
+export SMO_TOKEN_DATA=<SMO token data>
 cat <<EOF >>Procfile
-ocloud:  locust -f ocloud.py -H http://128.224.115.34:30205 --master
+ocloud:  locust -f ocloud.py -H https://128.224.115.34:30205 --master
 ocloud_1:  locust -f ocloud.py --worker
 ocloud_2:  locust -f ocloud.py --worker
 ocloud_3:  locust -f ocloud.py --worker
index 84f4659..2aec696 100644 (file)
 #  See the License for the specific language governing permissions and
 #  limitations under the License.
 
+import os
 from locust import HttpUser, task, constant
 
+# bearer_token="Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IkJJb3A2V2JSb29nNjR2YnpzOE12VXpzRHJVNjVSLUp1dWhZX2kzV0hjc2cifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6InNtby10b2tlbi1xNjcyZyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJzbW8iLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIwNmQzNDY1Ny0yZGFlLTQyNDItODMzMC05OTI4MjFmYzk0N2UiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDpzbW8ifQ.PbDAaLwi4OdQ4CZUFa1TC2vP0IWJqTP2ECmv287uHCho4vpZU63pkS2SgdtbDHLbPK29wZKJ1q9mqv4fci2WdJ7w87sfbHT1dcC8VzfAq7aQ4Rx6xRtsnTmerWqgsXYF_JqpfpHQFVO2stkV5zvg902J5Yco09xez0V6tIGNNORyBXc0SrQ7nuyMoH4gxAunfE_nFB5bQd9dfJnD7gHdDmh2v0HzKEnOV2KUJVhVLGnXZRJmYq1hoDc9YrJRoXmGucescnMDqUh0t8bwVG5a0BQZlLcc1y7i3WXUWPbXsmJ-7RN2_jYERUlS70SmOfaKNSC-t2BvGuh1lmF6yQaoKA"
+bearer_token="Bearer "+os.environ.get("SMO_TOKEN_DATA", "")
 
 class QuickstartUser(HttpUser):
     wait_time = constant(0)
 
     @task
     def ocloud(self):
-        self.client.get("/o2ims_infrastructureInventory/v1/")
+        self.client.get("/o2ims-infrastructureInventory/v1/")
 
     @task
     def resource(self):
         resp = self.client.get(
-            "/o2ims_infrastructureInventory/v1/resourcePools")
+            "/o2ims-infrastructureInventory/v1/resourcePools")
         json_resp_dict = resp.json()
         self.client.get(
-            "/o2ims_infrastructureInventory/v1/resourcePools/%s/resources" %
+            "/o2ims-infrastructureInventory/v1/resourcePools/%s/resources" %
             json_resp_dict[0]['resourcePoolId'])
 
     @task
     def dms(self):
-        self.client.get("/o2ims_infrastructureInventory/v1/deploymentManagers")
+        self.client.get("/o2ims-infrastructureInventory/v1/deploymentManagers")
 
     def on_start(self):
-        pass
+        self.client.headers = {
+            'Authorization':bearer_token
+        }
+        self.client.verify = False