Enhanced SDNC status check and SDNC distribution check 07/137207/1
authorLukasz Rajewski <lukasz.rajewski@t-mobile.pl>
Mon, 12 Feb 2024 16:34:50 +0000 (17:34 +0100)
committerLukasz Rajewski <lukasz.rajewski@t-mobile.pl>
Mon, 12 Feb 2024 20:06:44 +0000 (21:06 +0100)
Enhanced SDNC status check and SDNC distribution check

Issue-ID: TEST-404
Signed-off-by: Lukasz Rajewski <lukasz.rajewski@t-mobile.pl>
Change-Id: I4ed88c73251c5569bc6bc0ea9a4a4737ca903d93

src/onaptests/steps/instantiate/sdnc_service.py
src/onaptests/steps/onboard/service.py
src/onaptests/utils/kubernetes.py [new file with mode: 0644]

index 6d88c64..9dce7e9 100644 (file)
@@ -42,7 +42,8 @@ class BaseSdncStep(BaseStep):
 class CheckSdncDbStep(BaseSdncStep):
     """Check MariaDB connection status."""
 
-    SDNC_QUERY = "SELECT * FROM svc_logic LIMIT 1;"
+    SDNC_QUERY_LOGIC = "SELECT * FROM svc_logic LIMIT 1;"
+    SDNC_QUERY_MODEL = "SELECT * FROM service_model LIMIT 1;"
     SDNC_DATABASE = "sdnctl"
     SDNC_DB_LOGIN = "login"
     SDNC_DB_PASSWORD = "password"
@@ -85,6 +86,13 @@ class CheckSdncDbStep(BaseSdncStep):
             self.password = None
             raise EnvironmentPreparationException("Error accessing secret") from e
 
+    def _check_query(self, conn, query):
+        cursor = conn.cursor()
+        cursor.execute(query)
+        for _ in cursor:
+            pass
+        cursor.close()
+
     @BaseStep.store_state
     def execute(self) -> None:
         """Check MariaDB connection."""
@@ -98,8 +106,11 @@ class CheckSdncDbStep(BaseSdncStep):
                 port=settings.SDNC_DB_PORT,
                 user=self.login,
                 password=self.password)
-            cursor = conn.cursor()
-            cursor.execute(self.SDNC_QUERY)
+            self._check_query(conn, self.SDNC_QUERY_LOGIC)
+            self._check_query(conn, self.SDNC_QUERY_MODEL)
+        except (mysql.errors.ProgrammingError,
+                mysql.errors.DatabaseError) as e:
+            raise OnapTestException(e) from e
         except Exception as e:
             raise OnapTestException("Cannot connect to SDNC Database") from e
         finally:
index d8a627e..77456ff 100644 (file)
@@ -2,6 +2,7 @@ import time
 from typing import Any, Dict, Iterator
 from urllib.parse import urlencode
 
+import mysql.connector as mysql
 from onapsdk.aai.service_design_and_creation import Model
 from onapsdk.configuration import settings
 from onapsdk.exceptions import InvalidResponse, ResourceNotFound
@@ -17,6 +18,7 @@ from yaml import SafeLoader, load
 
 import onaptests.utils.exceptions as onap_test_exceptions
 from onaptests.scenario.scenario_base import BaseScenarioStep
+from onaptests.utils.kubernetes import KubernetesHelper
 
 from ..base import BaseStep, YamlTemplateBaseStep
 from .pnf import YamlTemplatePnfOnboardStep
@@ -203,6 +205,7 @@ class VerifyServiceDistributionStep(BaseScenarioStep):
                 notified_module=notified_module))
         self.add_step(VerifyServiceDistributionInSoStep())
         self.add_step(VerifyServiceDistributionInAaiStep())
+        self.add_step(VerifyServiceDistributionInSdncStep())
 
     @property
     def description(self) -> str:
@@ -392,3 +395,50 @@ class VerifyServiceDistributionInAaiStep(BaseServiceDistributionComponentCheckSt
             msg = f"Service {self.service.name} is missing in AAI."
             self._logger.error(msg)
             raise onap_test_exceptions.ServiceDistributionException(msg) from e
+
+
+class VerifyServiceDistributionInSdncStep(BaseServiceDistributionComponentCheckStep):
+    """Check service distribution in SDNC step."""
+
+    SDNC_DATABASE = "sdnctl"
+    SDNC_DB_LOGIN = "login"
+    SDNC_DB_PASSWORD = "password"
+
+    def __init__(self):
+        """Initialize step."""
+        BaseServiceDistributionComponentCheckStep.__init__(
+            self, component_name="SDNC")
+
+    @BaseStep.store_state
+    def execute(self):
+        """Check service distribution status."""
+        super().execute()
+        login, password = KubernetesHelper.get_credentials_from_secret(
+            settings.SDNC_SECRET_NAME, self.SDNC_DB_LOGIN, self.SDNC_DB_PASSWORD)
+        conn = None
+        try:
+            conn = mysql.connect(
+                database=self.SDNC_DATABASE,
+                host=settings.SDNC_DB_PRIMARY_HOST,
+                port=settings.SDNC_DB_PORT,
+                user=login,
+                password=password)
+            cursor = conn.cursor()
+            cursor.execute(
+                f"SELECT * FROM service_model WHERE service_uuid = '{self.service.uuid}'")
+            for _ in cursor:
+                pass
+            if cursor.rowcount == 0:
+                msg = f"Service {self.service.name} is missing in SDNC."
+                self._logger.error(msg)
+                raise onap_test_exceptions.ServiceDistributionException(msg)
+            cursor.close()
+        except Exception as e:
+            msg = f"Service {self.service.name} is missing in SDNC."
+            raise onap_test_exceptions.ServiceDistributionException(msg) from e
+        finally:
+            if conn:
+                try:
+                    conn.close()
+                except Exception:
+                    pass
diff --git a/src/onaptests/utils/kubernetes.py b/src/onaptests/utils/kubernetes.py
new file mode 100644 (file)
index 0000000..05728ca
--- /dev/null
@@ -0,0 +1,50 @@
+import base64
+
+from kubernetes import client, config
+from onapsdk.configuration import settings
+
+from onaptests.utils.exceptions import EnvironmentPreparationException
+
+
+class KubernetesHelper:
+    """Helper class to perform operations on kubernetes cluster"""
+
+    @classmethod
+    def load_config(cls):
+        """Load kubernetes client configuration"""
+        if settings.IN_CLUSTER:
+            config.load_incluster_config()
+        else:
+            config.load_kube_config(config_file=settings.K8S_CONFIG)
+
+    @classmethod
+    def get_credentials_from_secret(cls,
+                                    secret_name: str,
+                                    login_key: str,
+                                    password_key: str,
+                                    namespace: str = settings.K8S_ONAP_NAMESPACE):
+        """Resolve SDNC datbase credentials from k8s secret.
+
+        Args:
+            secret_name (str): name of the secret to load
+            login_key (str): key of the login in secret
+            password_key (str): key of the password in secret
+            namespace (str): k8s namespace to load key from
+        """
+
+        cls.load_config()
+        api_instance = client.CoreV1Api()
+        try:
+            secret = api_instance.read_namespaced_secret(secret_name, namespace)
+            if secret.data:
+                if (login_key in secret.data and password_key in secret.data):
+                    login_base64 = secret.data[login_key]
+                    login = base64.b64decode(login_base64).decode("utf-8")
+                    password_base64 = secret.data[password_key]
+                    password = base64.b64decode(password_base64).decode("utf-8")
+                    return login, password
+                raise EnvironmentPreparationException(
+                    "Login key or password key not found in secret")
+            raise EnvironmentPreparationException("Secret data not found in secret")
+        except client.rest.ApiException as e:
+            raise EnvironmentPreparationException("Error accessing secret") from e