Update cluster configuration to support feature 11055 25/15225/4
authorrshri <shrinithi.r@tataelxsi.co.in>
Wed, 11 Jun 2025 11:17:42 +0000 (11:17 +0000)
committergarciadeblas <gerardo.garciadeblas@telefonica.com>
Tue, 22 Jul 2025 14:26:25 +0000 (16:26 +0200)
Change-Id: Ide21bc1d4ce6bdb54b8c82ab3cc456e4ba8bb39f
Signed-off-by: rshri <shrinithi.r@tataelxsi.co.in>
osm_nbi/k8s_topics.py
osm_nbi/validation.py

index 3cf676b..90b85c9 100644 (file)
@@ -171,47 +171,58 @@ class ClusterTopic(ACMTopic):
             EngineException, ValidationError, DbException, FsException, MsgException.
             Note: Exceptions are not captured on purpose. They should be captured at called
         """
+
         step = "checking quotas"  # first step must be defined outside try
         try:
-            self.check_quota(session)
+            if self.multiproject:
+                self.check_quota(session)
+
+            content = self._remove_envelop(indata)
+
             step = "name unique check"
-            # self.check_unique_name(session, indata["name"])
             self.cluster_unique_name_check(session, indata["name"])
+
             step = "validating input parameters"
-            cls_request = self._remove_envelop(indata)
-            self._update_input_with_kwargs(cls_request, kwargs)
-            cls_request = self._validate_input_new(cls_request, session["force"])
-            operation_params = cls_request
+            self._update_input_with_kwargs(content, kwargs)
+
+            content = self._validate_input_new(content, session, force=session["force"])
+
+            operation_params = indata.copy()
+
+            self.check_conflict_on_new(session, content)
+            self.format_on_new(
+                content, project_id=session["project_id"], make_public=session["public"]
+            )
 
             step = "filling cluster details from input data"
-            cls_create = self._create_cluster(
-                cls_request, rollback, session, indata, kwargs, headers
+            content = self._create_cluster(
+                content, rollback, session, indata, kwargs, headers
             )
 
             step = "creating cluster at database"
-            self.format_on_new(
-                cls_create, session["project_id"], make_public=session["public"]
-            )
+            _id = self.db.create(self.topic, content)
+
             op_id = self.format_on_operation(
-                cls_create,
+                content,
                 "create",
                 operation_params,
             )
-            _id = self.db.create(self.topic, cls_create)
+
             pubkey, privkey = self._generate_age_key()
-            cls_create["age_pubkey"] = self.db.encrypt(
+            content["age_pubkey"] = self.db.encrypt(
                 pubkey, schema_version="1.11", salt=_id
             )
-            cls_create["age_privkey"] = self.db.encrypt(
+            content["age_privkey"] = self.db.encrypt(
                 privkey, schema_version="1.11", salt=_id
             )
+
             # TODO: set age_pubkey and age_privkey in the default profiles
             rollback.append({"topic": self.topic, "_id": _id})
-            self.db.set_one("clusters", {"_id": _id}, cls_create)
+            self.db.set_one("clusters", {"_id": _id}, content)
             self._send_msg("create", {"cluster_id": _id, "operation_id": op_id})
 
             # To add the content in old collection "k8sclusters"
-            self.add_to_old_collection(cls_create, session)
+            self.add_to_old_collection(content, session)
 
             return _id, None
         except (
@@ -223,68 +234,115 @@ class ClusterTopic(ACMTopic):
         ) as e:
             raise type(e)("{} while '{}'".format(e, step), http_code=e.http_code)
 
-    def _create_cluster(self, cls_request, rollback, session, indata, kwargs, headers):
+    def _validate_input_new(self, content, session, force=False):
+        # validating vim and checking the mandatory parameters
+        vim_type = self.check_vim(session, content["vim_account"])
+
+        # for aws
+        if vim_type == "aws":
+            self._aws_check(content)
+
+        # for azure and gcp
+        elif vim_type in ["azure", "gcp"]:
+            self._params_check(content)
+
+        return super()._validate_input_new(content, force=session["force"])
+
+    def _aws_check(self, indata):
+        if "node_count" in indata or "node_size" in indata:
+            raise ValueError("node_count and node_size are not allowed for AWS")
+        return
+
+    def _params_check(self, indata):
+        if "node_count" not in indata and "node_size" not in indata:
+            raise ValueError("node_count and node_size are mandatory parameter")
+        return
+
+    def _create_cluster(self, content, rollback, session, indata, kwargs, headers):
+        private_subnet = indata.get("private_subnet")
+        public_subnet = indata.get("public_subnet")
+
+        # Enforce: if private_subnet is provided, public_subnet must also be provided
+        if (private_subnet and not public_subnet) or (
+            public_subnet and not private_subnet
+        ):
+            raise ValueError(
+                "'public_subnet' must be provided if 'private_subnet' is given and viceversa."
+            )
+
+        # private Subnet validation
+        if private_subnet:
+            count = len(private_subnet)
+            if count != 2:
+                raise ValueError(
+                    f"private_subnet must contain exactly 2 items, got {count}"
+                )
+
+        # public Subnet validation
+        public_subnet = indata.get("public_subnet")
+        if public_subnet:
+            count = len(public_subnet)
+            if count != 1:
+                raise ValueError(
+                    f"public_subnet must contain exactly 1 items, got {count}"
+                )
+
+        content["infra_controller_profiles"] = [
+            self._create_default_profiles(
+                rollback, session, indata, kwargs, headers, self.infra_contr_topic
+            )
+        ]
+        content["infra_config_profiles"] = [
+            self._create_default_profiles(
+                rollback, session, indata, kwargs, headers, self.infra_conf_topic
+            )
+        ]
+        content["resource_profiles"] = [
+            self._create_default_profiles(
+                rollback, session, indata, kwargs, headers, self.resource_topic
+            )
+        ]
+        content["app_profiles"] = [
+            self._create_default_profiles(
+                rollback, session, indata, kwargs, headers, self.app_topic
+            )
+        ]
+        content["created"] = "true"
+        content["state"] = "IN_CREATION"
+        content["operatingState"] = "PROCESSING"
+        content["git_name"] = self.create_gitname(content, session)
+        content["resourceState"] = "IN_PROGRESS.REQUEST_RECEIVED"
+
         # Get the vim_account details
         vim_account_details = self.db.get_one(
-            "vim_accounts", {"name": cls_request["vim_account"]}
+            "vim_accounts", {"name": content["vim_account"]}
         )
 
-        # Check whether the region name and resource group have been given
-        if "region_name" in indata:
-            region_name = cls_request["region_name"]
-        else:
-            region_name = vim_account_details["config"].get("region_name")
-
-        cls_desc = {
-            "name": cls_request["name"],
-            "vim_account": self.check_vim(session, cls_request["vim_account"]),
-            "k8s_version": cls_request["k8s_version"],
-            "node_size": cls_request["node_size"],
-            "node_count": cls_request["node_count"],
-            "bootstrap": cls_request["bootstrap"],
-            "region_name": region_name,
-            "infra_controller_profiles": [
-                self._create_default_profiles(
-                    rollback, session, indata, kwargs, headers, self.infra_contr_topic
-                )
-            ],
-            "infra_config_profiles": [
-                self._create_default_profiles(
-                    rollback, session, indata, kwargs, headers, self.infra_conf_topic
-                )
-            ],
-            "resource_profiles": [
-                self._create_default_profiles(
-                    rollback, session, indata, kwargs, headers, self.resource_topic
-                )
-            ],
-            "app_profiles": [
-                self._create_default_profiles(
-                    rollback, session, indata, kwargs, headers, self.app_topic
-                )
-            ],
-            "created": "true",
-            "state": "IN_CREATION",
-            "operatingState": "PROCESSING",
-            "git_name": self.create_gitname(cls_request, session),
-            "resourceState": "IN_PROGRESS.REQUEST_RECEIVED",
-        }
         # Add optional fields if they exist in the request
-        if "resource_group" in indata:
-            resource_group = cls_request["resource_group"]
-        else:
-            resource_group = vim_account_details["config"].get("resource_group")
-        if resource_group:
-            cls_desc["resource_group"] = resource_group
-        if "description" in cls_request:
-            cls_desc["description"] = cls_request["description"]
-        return cls_desc
+
+        if "region_name" not in indata:
+            region_name = vim_account_details.get("config", {}).get("region_name")
+            if region_name:
+                content["region_name"] = region_name
+
+        if "resource_group" not in indata:
+            resource_group = vim_account_details.get("config", {}).get("resource_group")
+            if resource_group:
+                content["resource_group"] = resource_group
+
+        version = "k8s_version" in content
+        if not version:
+            content["k8s_version"] = "1.28"
+        content["node_count"] = indata.get("node_count", 0)
+        content["ksu_count"] = "0"
+        self.logger.info(f"cotent is : {content}")
+        return content
 
     def check_vim(self, session, name):
         try:
             vim_account_details = self.db.get_one("vim_accounts", {"name": name})
             if vim_account_details is not None:
-                return name
+                return vim_account_details["vim_type"]
         except ValidationError as e:
             raise EngineException(
                 e,
index 95556ff..1df72b4 100644 (file)
@@ -1093,8 +1093,8 @@ vnfpkgop_new_schema = {
 }
 
 clustercreation_new_schema = {
+    "$schema": "http://json-schema.org/draft-07/schema#",
     "title": "cluster creation operation input schema",
-    "$schema": "http://json-schema.org/draft-04/schema#",
     "type": "object",
     "properties": {
         "name": name_schema,
@@ -1105,26 +1105,32 @@ clustercreation_new_schema = {
         "description": description_schema,
         "region_name": string_schema,
         "resource_group": string_schema,
-        "infra_controller_profiles": shortname_schema,
-        "infra_config_profiles": shortname_schema,
-        "resource_profiles": shortname_schema,
-        "app_profiles": shortname_schema,
-        "created": string_schema,
-        "state": string_schema,
-        "operatingState": string_schema,
-        "git_name": string_schema,
-        "resourceState": string_schema,
         "bootstrap": bool_schema,
+        # "vim_type": string_schema,
+        "private_subnet": {  # Subnets validation
+            "type": "array",
+            "items": {  # Each item in the array must be a string (subnet ID)
+                "type": "string",
+                "pattern": "^subnet-[a-f0-9]+$",  # Optional: Add a regex pattern for basic subnet ID format
+            },
+            # "minItems": 2, # Minimum 2 subnets
+            "uniqueItems": True,  # Subnet IDs must be unique
+        },
+        "public_subnet": {  # Subnets validation
+            "type": "array",
+            "items": {  # Each item in the array must be a string (subnet ID)
+                "type": "string",
+                "pattern": "^subnet-[a-f0-9]+$",  # Optional: Add a regex pattern for basic subnet ID format
+            },
+            # "minItems": 2, # Minimum 2 subnets
+            "uniqueItems": True,  # Subnet IDs must be unique
+        },
+        "iam_role": string_schema,
     },
-    "required": [
-        "name",
-        "vim_account",
-        "k8s_version",
-        "node_size",
-        "node_count",
-    ],
+    "required": ["vim_account", "name", "k8s_version"],
     "additionalProperties": False,
 }
+
 clusterregistration_new_schema = {
     "title": "cluster registration input schema",
     "$schema": "http://json-schema.org/draft-04/schema#",