blob: 3a2d8b7e0f463dc278db26fa0cf4281cb37f1d8c [file] [log] [blame]
rshri932105f2024-07-05 15:11:55 +00001# -*- coding: utf-8 -*-
2
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12# implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16__author__ = (
17 "Shrinithi R <shrinithi.r@tataelxsi.co.in>",
18 "Shahithya Y <shahithya.y@tataelxsi.co.in>",
19)
20
rshric3564942024-11-12 18:12:38 +000021import copy
rshri932105f2024-07-05 15:11:55 +000022import logging
yshahd940c652024-10-17 06:11:12 +000023from time import time
garciadeblas72412282024-11-07 12:41:54 +010024import traceback
rshri932105f2024-07-05 15:11:55 +000025from osm_lcm.lcm_utils import LcmBase
26from copy import deepcopy
27from osm_lcm import odu_workflows
28from osm_lcm import vim_sdn
rshri948f7de2024-12-02 03:42:35 +000029from osm_lcm.data_utils.list_utils import find_in_list
garciadeblasbc96f382025-01-22 16:02:18 +010030from osm_lcm.n2vc.kubectl import Kubectl
31import yaml
rshri932105f2024-07-05 15:11:55 +000032
yshah2f39b8a2024-12-19 11:06:24 +000033MAP_PROFILE = {
34 "infra_controller_profiles": "infra-controllers",
35 "infra_config_profiles": "infra-configs",
36 "resource_profiles": "managed_resources",
37 "app_profiles": "apps",
38}
39
rshri932105f2024-07-05 15:11:55 +000040
garciadeblas72412282024-11-07 12:41:54 +010041class GitOpsLcm(LcmBase):
garciadeblasea865ff2024-11-20 12:42:49 +010042 db_collection = "gitops"
yshah564ec9c2024-11-29 07:33:32 +000043 workflow_status = None
44 resource_status = None
45
46 profile_collection_mapping = {
47 "infra_controller_profiles": "k8sinfra_controller",
48 "infra_config_profiles": "k8sinfra_config",
49 "resource_profiles": "k8sresource",
50 "app_profiles": "k8sapp",
51 }
garciadeblasea865ff2024-11-20 12:42:49 +010052
yshah4998f502025-02-11 12:37:04 +000053 profile_type_mapping = {
54 "infra-controllers": "infra_controller_profiles",
55 "infra-configs": "infra_config_profiles",
56 "managed-resources": "resource_profiles",
57 "applications": "app_profiles",
58 }
59
garciadeblas72412282024-11-07 12:41:54 +010060 def __init__(self, msg, lcm_tasks, config):
61 self.logger = logging.getLogger("lcm.gitops")
62 self.lcm_tasks = lcm_tasks
63 self.odu = odu_workflows.OduWorkflow(msg, self.lcm_tasks, config)
64 self._checkloop_kustomization_timeout = 900
65 self._checkloop_resource_timeout = 900
66 self._workflows = {}
67 super().__init__(msg, self.logger)
68
69 async def check_dummy_operation(self, op_id, op_params, content):
70 self.logger.info(f"Operation {op_id}. Params: {op_params}. Content: {content}")
71 return True, "OK"
72
garciadeblasea865ff2024-11-20 12:42:49 +010073 def initialize_operation(self, item_id, op_id):
74 db_item = self.db.get_one(self.db_collection, {"_id": item_id})
75 operation = next(
76 (op for op in db_item.get("operationHistory", []) if op["op_id"] == op_id),
77 None,
78 )
79 operation["workflowState"] = "PROCESSING"
80 operation["resourceState"] = "NOT_READY"
81 operation["operationState"] = "IN_PROGRESS"
82 operation["gitOperationInfo"] = None
83 db_item["current_operation"] = operation["op_id"]
84 self.db.set_one(self.db_collection, {"_id": item_id}, db_item)
85
yshah564ec9c2024-11-29 07:33:32 +000086 def get_operation_params(self, item, operation_id):
87 operation_history = item.get("operationHistory", [])
88 operation = find_in_list(
89 operation_history, lambda op: op["op_id"] == operation_id
90 )
91 return operation.get("operationParams", {})
92
93 def get_operation_type(self, item, operation_id):
94 operation_history = item.get("operationHistory", [])
95 operation = find_in_list(
96 operation_history, lambda op: op["op_id"] == operation_id
97 )
98 return operation.get("operationType", {})
99
garciadeblasbe890702024-12-20 11:39:13 +0100100 def update_state_operation_history(
101 self, content, op_id, workflow_state=None, resource_state=None
102 ):
103 self.logger.info(
104 f"Update state of operation {op_id} in Operation History in DB"
105 )
106 self.logger.info(
107 f"Workflow state: {workflow_state}. Resource state: {resource_state}"
108 )
109 self.logger.debug(f"Content: {content}")
110
111 op_num = 0
112 for operation in content["operationHistory"]:
113 self.logger.debug("Operations: {}".format(operation))
114 if operation["op_id"] == op_id:
115 self.logger.debug("Found operation number: {}".format(op_num))
116 if workflow_state is not None:
117 operation["workflowState"] = workflow_state
118
119 if resource_state is not None:
120 operation["resourceState"] = resource_state
121 break
122 op_num += 1
123 self.logger.debug("content: {}".format(content))
124
125 return content
126
garciadeblas7eae6f42024-11-08 10:41:38 +0100127 def update_operation_history(
garciadeblasf9092892024-12-12 11:07:08 +0100128 self, content, op_id, workflow_status=None, resource_status=None, op_end=True
garciadeblas7eae6f42024-11-08 10:41:38 +0100129 ):
130 self.logger.info(
131 f"Update Operation History in DB. Workflow status: {workflow_status}. Resource status: {resource_status}"
132 )
133 self.logger.debug(f"Content: {content}")
134
garciadeblas7eae6f42024-11-08 10:41:38 +0100135 op_num = 0
136 for operation in content["operationHistory"]:
137 self.logger.debug("Operations: {}".format(operation))
138 if operation["op_id"] == op_id:
139 self.logger.debug("Found operation number: {}".format(op_num))
garciadeblas8bde3f42024-12-20 10:37:12 +0100140 if workflow_status is not None:
141 if workflow_status:
142 operation["workflowState"] = "COMPLETED"
143 operation["result"] = True
144 else:
145 operation["workflowState"] = "ERROR"
146 operation["operationState"] = "FAILED"
147 operation["result"] = False
garciadeblas7eae6f42024-11-08 10:41:38 +0100148
garciadeblas8bde3f42024-12-20 10:37:12 +0100149 if resource_status is not None:
150 if resource_status:
151 operation["resourceState"] = "READY"
152 operation["operationState"] = "COMPLETED"
153 operation["result"] = True
154 else:
155 operation["resourceState"] = "NOT_READY"
156 operation["operationState"] = "FAILED"
157 operation["result"] = False
garciadeblas7eae6f42024-11-08 10:41:38 +0100158
garciadeblasf9092892024-12-12 11:07:08 +0100159 if op_end:
160 now = time()
161 operation["endDate"] = now
garciadeblas7eae6f42024-11-08 10:41:38 +0100162 break
163 op_num += 1
164 self.logger.debug("content: {}".format(content))
165
166 return content
167
garciadeblas713e1962025-01-17 12:49:19 +0100168 async def check_workflow_and_update_db(self, op_id, workflow_name, db_content):
yshah564ec9c2024-11-29 07:33:32 +0000169 workflow_status, workflow_msg = await self.odu.check_workflow_status(
garciadeblas36fe58b2025-02-05 16:36:17 +0100170 op_id, workflow_name
yshah564ec9c2024-11-29 07:33:32 +0000171 )
172 self.logger.info(
173 "Workflow Status: {} Workflow Message: {}".format(
174 workflow_status, workflow_msg
175 )
176 )
177 operation_type = self.get_operation_type(db_content, op_id)
178 if operation_type == "create" and workflow_status:
179 db_content["state"] = "CREATED"
180 elif operation_type == "create" and not workflow_status:
181 db_content["state"] = "FAILED_CREATION"
182 elif operation_type == "delete" and workflow_status:
183 db_content["state"] = "DELETED"
184 elif operation_type == "delete" and not workflow_status:
185 db_content["state"] = "FAILED_DELETION"
186
187 if workflow_status:
188 db_content["resourceState"] = "IN_PROGRESS.GIT_SYNCED"
189 else:
190 db_content["resourceState"] = "ERROR"
191
192 db_content = self.update_operation_history(
193 db_content, op_id, workflow_status, None
194 )
195 self.db.set_one(self.db_collection, {"_id": db_content["_id"]}, db_content)
196 return workflow_status
197
garciadeblas713e1962025-01-17 12:49:19 +0100198 async def check_resource_and_update_db(
199 self, resource_name, op_id, op_params, db_content
200 ):
yshah564ec9c2024-11-29 07:33:32 +0000201 workflow_status = True
202
203 resource_status, resource_msg = await self.check_resource_status(
204 resource_name, op_id, op_params, db_content
205 )
206 self.logger.info(
207 "Resource Status: {} Resource Message: {}".format(
208 resource_status, resource_msg
209 )
210 )
211
212 if resource_status:
213 db_content["resourceState"] = "READY"
214 else:
215 db_content["resourceState"] = "ERROR"
216
217 db_content = self.update_operation_history(
218 db_content, op_id, workflow_status, resource_status
219 )
220 db_content["operatingState"] = "IDLE"
221 db_content["current_operation"] = None
222 return resource_status, db_content
223
garciadeblasbc96f382025-01-22 16:02:18 +0100224 async def common_check_list(
garciadeblas619a0a32025-02-06 13:34:37 +0100225 self, op_id, checkings_list, db_collection, db_item, kubectl_obj=None
garciadeblasbc96f382025-01-22 16:02:18 +0100226 ):
garciadeblas72412282024-11-07 12:41:54 +0100227 try:
228 for checking in checkings_list:
229 if checking["enable"]:
230 status, message = await self.odu.readiness_loop(
garciadeblas36fe58b2025-02-05 16:36:17 +0100231 op_id=op_id,
garciadeblas72412282024-11-07 12:41:54 +0100232 item=checking["item"],
233 name=checking["name"],
234 namespace=checking["namespace"],
garciadeblas6c82c352025-01-27 16:53:45 +0100235 condition=checking.get("condition"),
garciadeblasbc96f382025-01-22 16:02:18 +0100236 deleted=checking.get("deleted", False),
garciadeblas72412282024-11-07 12:41:54 +0100237 timeout=checking["timeout"],
garciadeblas619a0a32025-02-06 13:34:37 +0100238 kubectl_obj=kubectl_obj,
garciadeblas72412282024-11-07 12:41:54 +0100239 )
240 if not status:
garciadeblasc5e9d572025-01-21 18:48:58 +0100241 error_message = "Resources not ready: "
242 error_message += checking.get("error_message", "")
243 return status, f"{error_message}: {message}"
garciadeblas7eae6f42024-11-08 10:41:38 +0100244 else:
245 db_item["resourceState"] = checking["resourceState"]
garciadeblasbe890702024-12-20 11:39:13 +0100246 db_item = self.update_state_operation_history(
247 db_item, op_id, None, checking["resourceState"]
garciadeblas7eae6f42024-11-08 10:41:38 +0100248 )
249 self.db.set_one(db_collection, {"_id": db_item["_id"]}, db_item)
garciadeblas72412282024-11-07 12:41:54 +0100250 except Exception as e:
251 self.logger.debug(traceback.format_exc())
252 self.logger.debug(f"Exception: {e}", exc_info=True)
253 return False, f"Unexpected exception: {e}"
254 return True, "OK"
255
256 async def check_resource_status(self, key, op_id, op_params, content):
257 self.logger.info(
garciadeblasbc96f382025-01-22 16:02:18 +0100258 f"Check resource status. Key: {key}. Operation: {op_id}. Params: {op_params}."
garciadeblas72412282024-11-07 12:41:54 +0100259 )
garciadeblasbc96f382025-01-22 16:02:18 +0100260 self.logger.debug(f"Check resource status. Content: {content}")
garciadeblas72412282024-11-07 12:41:54 +0100261 check_resource_function = self._workflows.get(key, {}).get(
262 "check_resource_function"
263 )
264 self.logger.info("check_resource function : {}".format(check_resource_function))
265 if check_resource_function:
266 return await check_resource_function(op_id, op_params, content)
267 else:
268 return await self.check_dummy_operation(op_id, op_params, content)
269
yshah408de812025-02-28 09:01:51 +0000270 def check_force_delete_and_delete_from_db(
271 self, _id, workflow_status, resource_status, force
272 ):
273 self.logger.info(
274 f" Force: {force} Workflow status: {workflow_status} Resource Status: {resource_status}"
275 )
276 if force and (not workflow_status or not resource_status):
277 self.db.del_one(self.db_collection, {"_id": _id})
278 return True
279 return False
280
garciadeblase4479af2025-03-11 15:44:25 +0100281 def decrypt_age_keys(self, content, fields=["age_pubkey", "age_privkey"]):
282 self.db.encrypt_decrypt_fields(
283 content,
284 "decrypt",
285 fields,
286 schema_version="1.11",
287 salt=content["_id"],
288 )
289
290 def encrypt_age_keys(self, content, fields=["age_pubkey", "age_privkey"]):
291 self.db.encrypt_decrypt_fields(
292 content,
293 "encrypt",
294 fields,
295 schema_version="1.11",
296 salt=content["_id"],
297 )
298
garciadeblas995cbf32024-12-18 12:54:00 +0100299 def decrypted_copy(self, content, fields=["age_pubkey", "age_privkey"]):
300 # This deep copy is intended to be passed to ODU workflows.
301 content_copy = copy.deepcopy(content)
rshric3564942024-11-12 18:12:38 +0000302
303 # decrypting the key
304 self.db.encrypt_decrypt_fields(
garciadeblas995cbf32024-12-18 12:54:00 +0100305 content_copy,
rshric3564942024-11-12 18:12:38 +0000306 "decrypt",
garciadeblas995cbf32024-12-18 12:54:00 +0100307 fields,
rshric3564942024-11-12 18:12:38 +0000308 schema_version="1.11",
garciadeblas995cbf32024-12-18 12:54:00 +0100309 salt=content_copy["_id"],
rshric3564942024-11-12 18:12:38 +0000310 )
garciadeblas995cbf32024-12-18 12:54:00 +0100311 return content_copy
rshric3564942024-11-12 18:12:38 +0000312
yshah6441de12025-05-19 12:29:01 +0000313 def delete_ksu_dependency(self, _id, data):
314 used_oka = []
315 existing_oka = []
316
317 for oka_data in data["oka"]:
318 if oka_data.get("_id"):
319 used_oka.append(oka_data["_id"])
320
321 all_ksu_data = self.db.get_list("ksus", {})
322 for ksu_data in all_ksu_data:
323 if ksu_data["_id"] != _id:
324 for oka_data in ksu_data["oka"]:
325 if oka_data.get("_id"):
326 if oka_data["_id"] not in existing_oka:
327 existing_oka.append(oka_data["_id"])
328
329 self.logger.info(f"Used OKA: {used_oka}")
330 self.logger.info(f"Existing OKA: {existing_oka}")
331
332 for oka_id in used_oka:
333 if oka_id not in existing_oka:
334 self.db.set_one(
335 "okas", {"_id": oka_id}, {"_admin.usageState": "NOT_IN_USE"}
336 )
337
338 return
339
yshah4998f502025-02-11 12:37:04 +0000340 def delete_profile_ksu(self, _id, profile_type):
341 filter_q = {"profile": {"_id": _id, "profile_type": profile_type}}
342 ksu_list = self.db.get_list("ksus", filter_q)
yshah6441de12025-05-19 12:29:01 +0000343 for ksu_data in ksu_list:
344 self.delete_ksu_dependency(ksu_data["_id"], ksu_data)
345
yshah4998f502025-02-11 12:37:04 +0000346 if ksu_list:
347 self.db.del_list("ksus", filter_q)
348 return
349
garciadeblasbc96f382025-01-22 16:02:18 +0100350 def cluster_kubectl(self, db_cluster):
351 cluster_kubeconfig = db_cluster["credentials"]
352 kubeconfig_path = f"/tmp/{db_cluster['_id']}_kubeconfig.yaml"
353 with open(kubeconfig_path, "w") as kubeconfig_file:
354 yaml.safe_dump(cluster_kubeconfig, kubeconfig_file)
355 return Kubectl(config_file=kubeconfig_path)
356
garciadeblas72412282024-11-07 12:41:54 +0100357
358class ClusterLcm(GitOpsLcm):
garciadeblas96b94f52024-07-08 16:18:21 +0200359 db_collection = "clusters"
rshri932105f2024-07-05 15:11:55 +0000360
361 def __init__(self, msg, lcm_tasks, config):
362 """
363 Init, Connect to database, filesystem storage, and messaging
364 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
365 :return: None
366 """
garciadeblas72412282024-11-07 12:41:54 +0100367 super().__init__(msg, lcm_tasks, config)
368 self._workflows = {
369 "create_cluster": {
370 "check_resource_function": self.check_create_cluster,
371 },
garciadeblasb0a42c22024-11-13 16:00:10 +0100372 "register_cluster": {
373 "check_resource_function": self.check_register_cluster,
374 },
375 "update_cluster": {
376 "check_resource_function": self.check_update_cluster,
377 },
garciadeblasbc96f382025-01-22 16:02:18 +0100378 "delete_cluster": {
379 "check_resource_function": self.check_delete_cluster,
380 },
garciadeblas72412282024-11-07 12:41:54 +0100381 }
rshri932105f2024-07-05 15:11:55 +0000382 self.regist = vim_sdn.K8sClusterLcm(msg, self.lcm_tasks, config)
383
rshri948f7de2024-12-02 03:42:35 +0000384 async def create(self, params, order_id):
rshri932105f2024-07-05 15:11:55 +0000385 self.logger.info("cluster Create Enter")
garciadeblas5861b0d2025-04-04 00:19:13 +0200386 workflow_status = None
387 resource_status = None
rshri932105f2024-07-05 15:11:55 +0000388
garciadeblas995cbf32024-12-18 12:54:00 +0100389 # To get the cluster and op ids
rshri948f7de2024-12-02 03:42:35 +0000390 cluster_id = params["cluster_id"]
rshri948f7de2024-12-02 03:42:35 +0000391 op_id = params["operation_id"]
rshri948f7de2024-12-02 03:42:35 +0000392
393 # To initialize the operation states
394 self.initialize_operation(cluster_id, op_id)
395
garciadeblas995cbf32024-12-18 12:54:00 +0100396 # To get the cluster
397 db_cluster = self.db.get_one("clusters", {"_id": cluster_id})
398
399 # To get the operation params details
400 op_params = self.get_operation_params(db_cluster, op_id)
401
402 # To copy the cluster content and decrypting fields to use in workflows
garciadeblase4479af2025-03-11 15:44:25 +0100403 db_cluster_copy = self.decrypted_copy(db_cluster)
garciadeblas995cbf32024-12-18 12:54:00 +0100404 workflow_content = {
garciadeblase4479af2025-03-11 15:44:25 +0100405 "cluster": db_cluster_copy,
garciadeblas995cbf32024-12-18 12:54:00 +0100406 }
rshric3564942024-11-12 18:12:38 +0000407
rshri948f7de2024-12-02 03:42:35 +0000408 # To get the vim account details
rshric3564942024-11-12 18:12:38 +0000409 db_vim = self.db.get_one("vim_accounts", {"name": db_cluster["vim_account"]})
garciadeblas995cbf32024-12-18 12:54:00 +0100410 workflow_content["vim_account"] = db_vim
rshric3564942024-11-12 18:12:38 +0000411
garciadeblasdc805482025-02-04 16:08:51 +0100412 workflow_res, workflow_name = await self.odu.launch_workflow(
garciadeblas995cbf32024-12-18 12:54:00 +0100413 "create_cluster", op_id, op_params, workflow_content
garciadeblas96b94f52024-07-08 16:18:21 +0200414 )
garciadeblasdc805482025-02-04 16:08:51 +0100415 if not workflow_res:
416 self.logger.error(f"Failed to launch workflow: {workflow_name}")
417 db_cluster["state"] = "FAILED_CREATION"
418 db_cluster["resourceState"] = "ERROR"
419 db_cluster = self.update_operation_history(
420 db_cluster, op_id, workflow_status=False, resource_status=None
421 )
422 self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster)
423 # Clean items used in the workflow, no matter if the workflow succeeded
424 clean_status, clean_msg = await self.odu.clean_items_workflow(
425 "create_cluster", op_id, op_params, workflow_content
426 )
427 self.logger.info(
428 f"clean_status is :{clean_status} and clean_msg is :{clean_msg}"
429 )
430 return
rshri932105f2024-07-05 15:11:55 +0000431
garciadeblas891f2002025-02-03 16:12:43 +0100432 self.logger.info("workflow_name is: {}".format(workflow_name))
garciadeblas96b94f52024-07-08 16:18:21 +0200433 workflow_status, workflow_msg = await self.odu.check_workflow_status(
garciadeblas36fe58b2025-02-05 16:36:17 +0100434 op_id, workflow_name
garciadeblas96b94f52024-07-08 16:18:21 +0200435 )
rshri932105f2024-07-05 15:11:55 +0000436 self.logger.info(
garciadeblas891f2002025-02-03 16:12:43 +0100437 "workflow_status is: {} and workflow_msg is: {}".format(
rshri932105f2024-07-05 15:11:55 +0000438 workflow_status, workflow_msg
439 )
440 )
441 if workflow_status:
garciadeblas96b94f52024-07-08 16:18:21 +0200442 db_cluster["state"] = "CREATED"
443 db_cluster["resourceState"] = "IN_PROGRESS.GIT_SYNCED"
rshri932105f2024-07-05 15:11:55 +0000444 else:
garciadeblas96b94f52024-07-08 16:18:21 +0200445 db_cluster["state"] = "FAILED_CREATION"
446 db_cluster["resourceState"] = "ERROR"
rshri932105f2024-07-05 15:11:55 +0000447 # has to call update_operation_history return content
yshahcb9075f2024-11-22 12:08:57 +0000448 db_cluster = self.update_operation_history(
449 db_cluster, op_id, workflow_status, None
450 )
garciadeblas96b94f52024-07-08 16:18:21 +0200451 self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster)
rshri932105f2024-07-05 15:11:55 +0000452
garciadeblas28bff0f2024-09-16 12:53:07 +0200453 # Clean items used in the workflow, no matter if the workflow succeeded
454 clean_status, clean_msg = await self.odu.clean_items_workflow(
garciadeblas995cbf32024-12-18 12:54:00 +0100455 "create_cluster", op_id, op_params, workflow_content
garciadeblas28bff0f2024-09-16 12:53:07 +0200456 )
457 self.logger.info(
458 f"clean_status is :{clean_status} and clean_msg is :{clean_msg}"
459 )
460
rshri932105f2024-07-05 15:11:55 +0000461 if workflow_status:
garciadeblas72412282024-11-07 12:41:54 +0100462 resource_status, resource_msg = await self.check_resource_status(
garciadeblas995cbf32024-12-18 12:54:00 +0100463 "create_cluster", op_id, op_params, workflow_content
rshri932105f2024-07-05 15:11:55 +0000464 )
465 self.logger.info(
466 "resource_status is :{} and resource_msg is :{}".format(
467 resource_status, resource_msg
468 )
469 )
470 if resource_status:
garciadeblas96b94f52024-07-08 16:18:21 +0200471 db_cluster["resourceState"] = "READY"
rshri932105f2024-07-05 15:11:55 +0000472 else:
garciadeblas96b94f52024-07-08 16:18:21 +0200473 db_cluster["resourceState"] = "ERROR"
rshri932105f2024-07-05 15:11:55 +0000474
garciadeblas96b94f52024-07-08 16:18:21 +0200475 db_cluster["operatingState"] = "IDLE"
476 db_cluster = self.update_operation_history(
yshahcb9075f2024-11-22 12:08:57 +0000477 db_cluster, op_id, workflow_status, resource_status
rshri932105f2024-07-05 15:11:55 +0000478 )
shahithya70a3fc92024-11-12 11:01:05 +0000479 db_cluster["current_operation"] = None
garciadeblas3e5eeec2025-01-21 11:49:38 +0100480
481 # Retrieve credentials
482 cluster_creds = None
483 if db_cluster["resourceState"] == "READY" and db_cluster["state"] == "CREATED":
484 result, cluster_creds = await self.odu.get_cluster_credentials(db_cluster)
485 # TODO: manage the case where the credentials are not available
486 if result:
487 db_cluster["credentials"] = cluster_creds
488
489 # Update db_cluster
garciadeblas96b94f52024-07-08 16:18:21 +0200490 self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster)
garciadeblase4479af2025-03-11 15:44:25 +0100491 self.update_default_profile_agekeys(db_cluster_copy)
garciadeblas96b94f52024-07-08 16:18:21 +0200492 self.update_profile_state(db_cluster, workflow_status, resource_status)
rshri948f7de2024-12-02 03:42:35 +0000493
garciadeblas3e5eeec2025-01-21 11:49:38 +0100494 # Register the cluster in k8sclusters collection
rshri948f7de2024-12-02 03:42:35 +0000495 db_register = self.db.get_one("k8sclusters", {"name": db_cluster["name"]})
garciadeblas3e5eeec2025-01-21 11:49:38 +0100496 if cluster_creds:
rshri948f7de2024-12-02 03:42:35 +0000497 db_register["credentials"] = cluster_creds
garciadeblas3e5eeec2025-01-21 11:49:38 +0100498 # To call the lcm.py for registering the cluster in k8scluster lcm.
rshri948f7de2024-12-02 03:42:35 +0000499 self.db.set_one("k8sclusters", {"_id": db_register["_id"]}, db_register)
500 register = await self.regist.create(db_register, order_id)
501 self.logger.debug(f"Register is : {register}")
502 else:
503 db_register["_admin"]["operationalState"] = "ERROR"
504 result, cluster_creds = await self.odu.get_cluster_credentials(db_cluster)
505 # To call the lcm.py for registering the cluster in k8scluster lcm.
506 db_register["credentials"] = cluster_creds
507 self.db.set_one("k8sclusters", {"_id": db_register["_id"]}, db_register)
508
rshri932105f2024-07-05 15:11:55 +0000509 return
510
garciadeblas72412282024-11-07 12:41:54 +0100511 async def check_create_cluster(self, op_id, op_params, content):
garciadeblas7eae6f42024-11-08 10:41:38 +0100512 self.logger.info(
513 f"check_create_cluster Operation {op_id}. Params: {op_params}."
514 )
garciadeblas72412282024-11-07 12:41:54 +0100515 db_cluster = content["cluster"]
516 cluster_name = db_cluster["git_name"].lower()
517 cluster_kustomization_name = cluster_name
518 db_vim_account = content["vim_account"]
519 cloud_type = db_vim_account["vim_type"]
garciadeblasbccc0602025-05-30 11:19:06 +0200520 nodegroup_name = ""
garciadeblas72412282024-11-07 12:41:54 +0100521 if cloud_type == "aws":
garciadeblasbccc0602025-05-30 11:19:06 +0200522 nodegroup_name = f"{cluster_name}-nodegroup"
garciadeblas72412282024-11-07 12:41:54 +0100523 cluster_name = f"{cluster_name}-cluster"
524 elif cloud_type == "gcp":
garciadeblasbccc0602025-05-30 11:19:06 +0200525 nodegroup_name = f"nodepool-{cluster_name}"
garciadeblas72412282024-11-07 12:41:54 +0100526 bootstrap = op_params.get("bootstrap", True)
527 if cloud_type in ("azure", "gcp", "aws"):
528 checkings_list = [
529 {
530 "item": "kustomization",
531 "name": cluster_kustomization_name,
532 "namespace": "managed-resources",
garciadeblas6c82c352025-01-27 16:53:45 +0100533 "condition": {
534 "jsonpath_filter": "status.conditions[?(@.type=='Ready')].status",
535 "value": "True",
536 },
yshahcb9075f2024-11-22 12:08:57 +0000537 "timeout": 1500,
garciadeblas72412282024-11-07 12:41:54 +0100538 "enable": True,
garciadeblas7eae6f42024-11-08 10:41:38 +0100539 "resourceState": "IN_PROGRESS.KUSTOMIZATION_READY",
garciadeblas72412282024-11-07 12:41:54 +0100540 },
541 {
542 "item": f"cluster_{cloud_type}",
543 "name": cluster_name,
544 "namespace": "",
garciadeblas6c82c352025-01-27 16:53:45 +0100545 "condition": {
546 "jsonpath_filter": "status.conditions[?(@.type=='Synced')].status",
547 "value": "True",
548 },
garciadeblas72412282024-11-07 12:41:54 +0100549 "timeout": self._checkloop_resource_timeout,
550 "enable": True,
garciadeblas7eae6f42024-11-08 10:41:38 +0100551 "resourceState": "IN_PROGRESS.RESOURCE_SYNCED.CLUSTER",
garciadeblas72412282024-11-07 12:41:54 +0100552 },
553 {
554 "item": f"cluster_{cloud_type}",
555 "name": cluster_name,
556 "namespace": "",
garciadeblas6c82c352025-01-27 16:53:45 +0100557 "condition": {
558 "jsonpath_filter": "status.conditions[?(@.type=='Ready')].status",
559 "value": "True",
560 },
garciadeblas72412282024-11-07 12:41:54 +0100561 "timeout": self._checkloop_resource_timeout,
562 "enable": True,
garciadeblas7eae6f42024-11-08 10:41:38 +0100563 "resourceState": "IN_PROGRESS.RESOURCE_READY.CLUSTER",
garciadeblas72412282024-11-07 12:41:54 +0100564 },
565 {
566 "item": "kustomization",
567 "name": f"{cluster_kustomization_name}-bstrp-fluxctrl",
568 "namespace": "managed-resources",
garciadeblas6c82c352025-01-27 16:53:45 +0100569 "condition": {
570 "jsonpath_filter": "status.conditions[?(@.type=='Ready')].status",
571 "value": "True",
572 },
yshahcb9075f2024-11-22 12:08:57 +0000573 "timeout": self._checkloop_resource_timeout,
garciadeblas72412282024-11-07 12:41:54 +0100574 "enable": bootstrap,
garciadeblas7eae6f42024-11-08 10:41:38 +0100575 "resourceState": "IN_PROGRESS.BOOTSTRAP_OK",
garciadeblas72412282024-11-07 12:41:54 +0100576 },
577 ]
578 else:
579 return False, "Not suitable VIM account to check cluster status"
garciadeblasbccc0602025-05-30 11:19:06 +0200580 if nodegroup_name:
581 nodegroup_check = {
582 "item": f"nodegroup_{cloud_type}",
583 "name": nodegroup_name,
garciadeblas72412282024-11-07 12:41:54 +0100584 "namespace": "",
garciadeblas6c82c352025-01-27 16:53:45 +0100585 "condition": {
586 "jsonpath_filter": "status.conditions[?(@.type=='Ready')].status",
587 "value": "True",
588 },
garciadeblas72412282024-11-07 12:41:54 +0100589 "timeout": self._checkloop_resource_timeout,
590 "enable": True,
garciadeblasbccc0602025-05-30 11:19:06 +0200591 "resourceState": "IN_PROGRESS.RESOURCE_READY.NODEGROUP",
garciadeblas72412282024-11-07 12:41:54 +0100592 }
garciadeblasbccc0602025-05-30 11:19:06 +0200593 checkings_list.insert(3, nodegroup_check)
yshahcb9075f2024-11-22 12:08:57 +0000594 return await self.common_check_list(
595 op_id, checkings_list, "clusters", db_cluster
596 )
garciadeblas72412282024-11-07 12:41:54 +0100597
garciadeblase4479af2025-03-11 15:44:25 +0100598 def update_default_profile_agekeys(self, db_cluster):
599 profiles = [
600 "infra_controller_profiles",
601 "infra_config_profiles",
602 "app_profiles",
603 "resource_profiles",
604 ]
605 self.logger.debug("the db_cluster is :{}".format(db_cluster))
606 for profile_type in profiles:
607 profile_id = db_cluster[profile_type]
608 db_collection = self.profile_collection_mapping[profile_type]
609 db_profile = self.db.get_one(db_collection, {"_id": profile_id})
610 db_profile["age_pubkey"] = db_cluster["age_pubkey"]
611 db_profile["age_privkey"] = db_cluster["age_privkey"]
612 self.encrypt_age_keys(db_profile)
613 self.db.set_one(db_collection, {"_id": db_profile["_id"]}, db_profile)
614
garciadeblas96b94f52024-07-08 16:18:21 +0200615 def update_profile_state(self, db_cluster, workflow_status, resource_status):
rshri932105f2024-07-05 15:11:55 +0000616 profiles = [
617 "infra_controller_profiles",
618 "infra_config_profiles",
619 "app_profiles",
620 "resource_profiles",
621 ]
garciadeblase4479af2025-03-11 15:44:25 +0100622 self.logger.debug("the db_cluster is :{}".format(db_cluster))
rshri932105f2024-07-05 15:11:55 +0000623 for profile_type in profiles:
garciadeblas96b94f52024-07-08 16:18:21 +0200624 profile_id = db_cluster[profile_type]
rshri948f7de2024-12-02 03:42:35 +0000625 db_collection = self.profile_collection_mapping[profile_type]
rshri932105f2024-07-05 15:11:55 +0000626 db_profile = self.db.get_one(db_collection, {"_id": profile_id})
yshahcb9075f2024-11-22 12:08:57 +0000627 op_id = db_profile["operationHistory"][-1].get("op_id")
garciadeblas96b94f52024-07-08 16:18:21 +0200628 db_profile["state"] = db_cluster["state"]
629 db_profile["resourceState"] = db_cluster["resourceState"]
630 db_profile["operatingState"] = db_cluster["operatingState"]
rshri932105f2024-07-05 15:11:55 +0000631 db_profile = self.update_operation_history(
yshahcb9075f2024-11-22 12:08:57 +0000632 db_profile, op_id, workflow_status, resource_status
rshri932105f2024-07-05 15:11:55 +0000633 )
rshri932105f2024-07-05 15:11:55 +0000634 self.db.set_one(db_collection, {"_id": db_profile["_id"]}, db_profile)
635
rshri948f7de2024-12-02 03:42:35 +0000636 async def delete(self, params, order_id):
rshri932105f2024-07-05 15:11:55 +0000637 self.logger.info("cluster delete Enter")
rshri948f7de2024-12-02 03:42:35 +0000638
garciadeblas0248bcb2025-02-12 16:45:40 +0100639 try:
640 # To get the cluster and op ids
641 cluster_id = params["cluster_id"]
642 op_id = params["operation_id"]
rshri948f7de2024-12-02 03:42:35 +0000643
garciadeblas0248bcb2025-02-12 16:45:40 +0100644 # To initialize the operation states
645 self.initialize_operation(cluster_id, op_id)
rshri948f7de2024-12-02 03:42:35 +0000646
garciadeblas0248bcb2025-02-12 16:45:40 +0100647 # To get the cluster
648 db_cluster = self.db.get_one("clusters", {"_id": cluster_id})
garciadeblas995cbf32024-12-18 12:54:00 +0100649
garciadeblas0248bcb2025-02-12 16:45:40 +0100650 # To get the operation params details
651 op_params = self.get_operation_params(db_cluster, op_id)
garciadeblas995cbf32024-12-18 12:54:00 +0100652
garciadeblas0248bcb2025-02-12 16:45:40 +0100653 # To copy the cluster content and decrypting fields to use in workflows
654 workflow_content = {
655 "cluster": self.decrypted_copy(db_cluster),
656 }
rshri948f7de2024-12-02 03:42:35 +0000657
garciadeblas0248bcb2025-02-12 16:45:40 +0100658 # To get the vim account details
659 db_vim = self.db.get_one(
660 "vim_accounts", {"name": db_cluster["vim_account"]}
661 )
662 workflow_content["vim_account"] = db_vim
663 except Exception as e:
664 self.logger.debug(traceback.format_exc())
665 self.logger.debug(f"Exception: {e}", exc_info=True)
666 raise e
garciadeblasbc96f382025-01-22 16:02:18 +0100667
garciadeblasdc805482025-02-04 16:08:51 +0100668 workflow_res, workflow_name = await self.odu.launch_workflow(
garciadeblas995cbf32024-12-18 12:54:00 +0100669 "delete_cluster", op_id, op_params, workflow_content
garciadeblas96b94f52024-07-08 16:18:21 +0200670 )
garciadeblasdc805482025-02-04 16:08:51 +0100671 if not workflow_res:
672 self.logger.error(f"Failed to launch workflow: {workflow_name}")
673 db_cluster["state"] = "FAILED_DELETION"
674 db_cluster["resourceState"] = "ERROR"
675 db_cluster = self.update_operation_history(
676 db_cluster, op_id, workflow_status=False, resource_status=None
677 )
678 self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster)
679 # Clean items used in the workflow, no matter if the workflow succeeded
680 clean_status, clean_msg = await self.odu.clean_items_workflow(
681 "delete_cluster", op_id, op_params, workflow_content
682 )
683 self.logger.info(
684 f"clean_status is :{clean_status} and clean_msg is :{clean_msg}"
685 )
686 return
rshri932105f2024-07-05 15:11:55 +0000687
garciadeblas891f2002025-02-03 16:12:43 +0100688 self.logger.info("workflow_name is: {}".format(workflow_name))
garciadeblas96b94f52024-07-08 16:18:21 +0200689 workflow_status, workflow_msg = await self.odu.check_workflow_status(
garciadeblas36fe58b2025-02-05 16:36:17 +0100690 op_id, workflow_name
garciadeblas96b94f52024-07-08 16:18:21 +0200691 )
rshri932105f2024-07-05 15:11:55 +0000692 self.logger.info(
garciadeblas891f2002025-02-03 16:12:43 +0100693 "workflow_status is: {} and workflow_msg is: {}".format(
rshri932105f2024-07-05 15:11:55 +0000694 workflow_status, workflow_msg
695 )
696 )
697 if workflow_status:
garciadeblas96b94f52024-07-08 16:18:21 +0200698 db_cluster["state"] = "DELETED"
699 db_cluster["resourceState"] = "IN_PROGRESS.GIT_SYNCED"
rshri932105f2024-07-05 15:11:55 +0000700 else:
garciadeblas96b94f52024-07-08 16:18:21 +0200701 db_cluster["state"] = "FAILED_DELETION"
702 db_cluster["resourceState"] = "ERROR"
rshri932105f2024-07-05 15:11:55 +0000703 # has to call update_operation_history return content
yshahcb9075f2024-11-22 12:08:57 +0000704 db_cluster = self.update_operation_history(
705 db_cluster, op_id, workflow_status, None
706 )
garciadeblas96b94f52024-07-08 16:18:21 +0200707 self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster)
rshri932105f2024-07-05 15:11:55 +0000708
garciadeblas98f9a3d2024-12-10 13:42:47 +0100709 # Clean items used in the workflow or in the cluster, no matter if the workflow succeeded
710 clean_status, clean_msg = await self.odu.clean_items_workflow(
garciadeblas995cbf32024-12-18 12:54:00 +0100711 "delete_cluster", op_id, op_params, workflow_content
garciadeblas98f9a3d2024-12-10 13:42:47 +0100712 )
713 self.logger.info(
714 f"clean_status is :{clean_status} and clean_msg is :{clean_msg}"
715 )
716
rshri932105f2024-07-05 15:11:55 +0000717 if workflow_status:
garciadeblas72412282024-11-07 12:41:54 +0100718 resource_status, resource_msg = await self.check_resource_status(
garciadeblas995cbf32024-12-18 12:54:00 +0100719 "delete_cluster", op_id, op_params, workflow_content
rshri932105f2024-07-05 15:11:55 +0000720 )
721 self.logger.info(
722 "resource_status is :{} and resource_msg is :{}".format(
723 resource_status, resource_msg
724 )
725 )
726 if resource_status:
garciadeblas96b94f52024-07-08 16:18:21 +0200727 db_cluster["resourceState"] = "READY"
rshri932105f2024-07-05 15:11:55 +0000728 else:
garciadeblas96b94f52024-07-08 16:18:21 +0200729 db_cluster["resourceState"] = "ERROR"
rshri932105f2024-07-05 15:11:55 +0000730
garciadeblas96b94f52024-07-08 16:18:21 +0200731 db_cluster["operatingState"] = "IDLE"
732 db_cluster = self.update_operation_history(
yshahcb9075f2024-11-22 12:08:57 +0000733 db_cluster, op_id, workflow_status, resource_status
garciadeblas96b94f52024-07-08 16:18:21 +0200734 )
shahithya70a3fc92024-11-12 11:01:05 +0000735 db_cluster["current_operation"] = None
garciadeblas96b94f52024-07-08 16:18:21 +0200736 self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster)
rshri932105f2024-07-05 15:11:55 +0000737
yshah408de812025-02-28 09:01:51 +0000738 force = params.get("force", False)
739 if force:
740 force_delete_status = self.check_force_delete_and_delete_from_db(
741 cluster_id, workflow_status, resource_status, force
742 )
743 if force_delete_status:
744 return
745
garciadeblas96b94f52024-07-08 16:18:21 +0200746 # To delete it from DB
747 if db_cluster["state"] == "DELETED":
748 self.delete_cluster(db_cluster)
rshri948f7de2024-12-02 03:42:35 +0000749
750 # To delete it from k8scluster collection
751 self.db.del_one("k8sclusters", {"name": db_cluster["name"]})
752
rshri932105f2024-07-05 15:11:55 +0000753 return
754
garciadeblasbc96f382025-01-22 16:02:18 +0100755 async def check_delete_cluster(self, op_id, op_params, content):
756 self.logger.info(
757 f"check_delete_cluster Operation {op_id}. Params: {op_params}."
758 )
759 self.logger.debug(f"Content: {content}")
760 db_cluster = content["cluster"]
761 cluster_name = db_cluster["git_name"].lower()
762 cluster_kustomization_name = cluster_name
763 db_vim_account = content["vim_account"]
764 cloud_type = db_vim_account["vim_type"]
765 if cloud_type == "aws":
766 cluster_name = f"{cluster_name}-cluster"
767 if cloud_type in ("azure", "gcp", "aws"):
768 checkings_list = [
769 {
770 "item": "kustomization",
771 "name": cluster_kustomization_name,
772 "namespace": "managed-resources",
773 "deleted": True,
774 "timeout": self._checkloop_kustomization_timeout,
775 "enable": True,
776 "resourceState": "IN_PROGRESS.KUSTOMIZATION_DELETED",
777 },
778 {
779 "item": f"cluster_{cloud_type}",
780 "name": cluster_name,
781 "namespace": "",
782 "deleted": True,
783 "timeout": self._checkloop_resource_timeout,
784 "enable": True,
785 "resourceState": "IN_PROGRESS.RESOURCE_DELETED.CLUSTER",
786 },
787 ]
788 else:
789 return False, "Not suitable VIM account to check cluster status"
790 return await self.common_check_list(
791 op_id, checkings_list, "clusters", db_cluster
792 )
793
garciadeblas96b94f52024-07-08 16:18:21 +0200794 def delete_cluster(self, db_cluster):
795 # Actually, item_content is equal to db_cluster
rshri932105f2024-07-05 15:11:55 +0000796 # detach profiles
797 update_dict = None
798 profiles_to_detach = [
799 "infra_controller_profiles",
800 "infra_config_profiles",
801 "app_profiles",
802 "resource_profiles",
803 ]
rshri948f7de2024-12-02 03:42:35 +0000804 """
rshri932105f2024-07-05 15:11:55 +0000805 profiles_collection = {
806 "infra_controller_profiles": "k8sinfra_controller",
807 "infra_config_profiles": "k8sinfra_config",
808 "app_profiles": "k8sapp",
809 "resource_profiles": "k8sresource",
810 }
rshri948f7de2024-12-02 03:42:35 +0000811 """
rshri932105f2024-07-05 15:11:55 +0000812 for profile_type in profiles_to_detach:
garciadeblas96b94f52024-07-08 16:18:21 +0200813 if db_cluster.get(profile_type):
garciadeblas96b94f52024-07-08 16:18:21 +0200814 profile_ids = db_cluster[profile_type]
rshri932105f2024-07-05 15:11:55 +0000815 profile_ids_copy = deepcopy(profile_ids)
rshri932105f2024-07-05 15:11:55 +0000816 for profile_id in profile_ids_copy:
rshri948f7de2024-12-02 03:42:35 +0000817 db_collection = self.profile_collection_mapping[profile_type]
rshri932105f2024-07-05 15:11:55 +0000818 db_profile = self.db.get_one(db_collection, {"_id": profile_id})
garciadeblasc2552852024-10-22 12:39:32 +0200819 self.logger.debug("the db_profile is :{}".format(db_profile))
820 self.logger.debug(
garciadeblas96b94f52024-07-08 16:18:21 +0200821 "the item_content name is :{}".format(db_cluster["name"])
rshri932105f2024-07-05 15:11:55 +0000822 )
garciadeblasc2552852024-10-22 12:39:32 +0200823 self.logger.debug(
rshri932105f2024-07-05 15:11:55 +0000824 "the db_profile name is :{}".format(db_profile["name"])
825 )
garciadeblas96b94f52024-07-08 16:18:21 +0200826 if db_cluster["name"] == db_profile["name"]:
yshah4998f502025-02-11 12:37:04 +0000827 self.delete_profile_ksu(profile_id, profile_type)
rshri932105f2024-07-05 15:11:55 +0000828 self.db.del_one(db_collection, {"_id": profile_id})
829 else:
rshri932105f2024-07-05 15:11:55 +0000830 profile_ids.remove(profile_id)
831 update_dict = {profile_type: profile_ids}
rshri932105f2024-07-05 15:11:55 +0000832 self.db.set_one(
garciadeblas96b94f52024-07-08 16:18:21 +0200833 "clusters", {"_id": db_cluster["_id"]}, update_dict
rshri932105f2024-07-05 15:11:55 +0000834 )
garciadeblas96b94f52024-07-08 16:18:21 +0200835 self.db.del_one("clusters", {"_id": db_cluster["_id"]})
rshri932105f2024-07-05 15:11:55 +0000836
rshri948f7de2024-12-02 03:42:35 +0000837 async def attach_profile(self, params, order_id):
rshri932105f2024-07-05 15:11:55 +0000838 self.logger.info("profile attach Enter")
rshri948f7de2024-12-02 03:42:35 +0000839
garciadeblas995cbf32024-12-18 12:54:00 +0100840 # To get the cluster and op ids
rshri948f7de2024-12-02 03:42:35 +0000841 cluster_id = params["cluster_id"]
rshri948f7de2024-12-02 03:42:35 +0000842 op_id = params["operation_id"]
rshri948f7de2024-12-02 03:42:35 +0000843
844 # To initialize the operation states
845 self.initialize_operation(cluster_id, op_id)
846
garciadeblas995cbf32024-12-18 12:54:00 +0100847 # To get the cluster
848 db_cluster = self.db.get_one("clusters", {"_id": cluster_id})
849
850 # To get the operation params details
851 op_params = self.get_operation_params(db_cluster, op_id)
852
853 # To copy the cluster content and decrypting fields to use in workflows
854 workflow_content = {
855 "cluster": self.decrypted_copy(db_cluster),
856 }
rshri948f7de2024-12-02 03:42:35 +0000857
858 # To get the profile details
859 profile_id = params["profile_id"]
860 profile_type = params["profile_type"]
861 profile_collection = self.profile_collection_mapping[profile_type]
862 db_profile = self.db.get_one(profile_collection, {"_id": profile_id})
863 db_profile["profile_type"] = profile_type
864 # content["profile"] = db_profile
garciadeblas995cbf32024-12-18 12:54:00 +0100865 workflow_content["profile"] = db_profile
rshri932105f2024-07-05 15:11:55 +0000866
garciadeblasdc805482025-02-04 16:08:51 +0100867 workflow_res, workflow_name = await self.odu.launch_workflow(
garciadeblas995cbf32024-12-18 12:54:00 +0100868 "attach_profile_to_cluster", op_id, op_params, workflow_content
garciadeblas96b94f52024-07-08 16:18:21 +0200869 )
garciadeblasdc805482025-02-04 16:08:51 +0100870 if not workflow_res:
871 self.logger.error(f"Failed to launch workflow: {workflow_name}")
872 db_cluster["resourceState"] = "ERROR"
873 self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster)
874 db_cluster = self.update_operation_history(
875 db_cluster, op_id, workflow_status=False, resource_status=None
876 )
877 return
rshri932105f2024-07-05 15:11:55 +0000878
garciadeblas891f2002025-02-03 16:12:43 +0100879 self.logger.info("workflow_name is: {}".format(workflow_name))
garciadeblas96b94f52024-07-08 16:18:21 +0200880 workflow_status, workflow_msg = await self.odu.check_workflow_status(
garciadeblas36fe58b2025-02-05 16:36:17 +0100881 op_id, workflow_name
garciadeblas96b94f52024-07-08 16:18:21 +0200882 )
rshri932105f2024-07-05 15:11:55 +0000883 self.logger.info(
garciadeblas891f2002025-02-03 16:12:43 +0100884 "workflow_status is: {} and workflow_msg is: {}".format(
rshri932105f2024-07-05 15:11:55 +0000885 workflow_status, workflow_msg
886 )
887 )
888 if workflow_status:
889 db_cluster["resourceState"] = "IN_PROGRESS.GIT_SYNCED"
890 else:
891 db_cluster["resourceState"] = "ERROR"
892 # has to call update_operation_history return content
yshahcb9075f2024-11-22 12:08:57 +0000893 db_cluster = self.update_operation_history(
894 db_cluster, op_id, workflow_status, None
895 )
rshri932105f2024-07-05 15:11:55 +0000896 self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster)
897
898 if workflow_status:
garciadeblas72412282024-11-07 12:41:54 +0100899 resource_status, resource_msg = await self.check_resource_status(
garciadeblas995cbf32024-12-18 12:54:00 +0100900 "attach_profile_to_cluster", op_id, op_params, workflow_content
rshri932105f2024-07-05 15:11:55 +0000901 )
902 self.logger.info(
903 "resource_status is :{} and resource_msg is :{}".format(
904 resource_status, resource_msg
905 )
906 )
907 if resource_status:
908 db_cluster["resourceState"] = "READY"
909 else:
910 db_cluster["resourceState"] = "ERROR"
911
912 db_cluster["operatingState"] = "IDLE"
913 db_cluster = self.update_operation_history(
yshahcb9075f2024-11-22 12:08:57 +0000914 db_cluster, op_id, workflow_status, resource_status
rshri932105f2024-07-05 15:11:55 +0000915 )
rshri932105f2024-07-05 15:11:55 +0000916 profile_list = db_cluster[profile_type]
rshri932105f2024-07-05 15:11:55 +0000917 if resource_status:
rshri932105f2024-07-05 15:11:55 +0000918 profile_list.append(profile_id)
rshri932105f2024-07-05 15:11:55 +0000919 db_cluster[profile_type] = profile_list
shahithya70a3fc92024-11-12 11:01:05 +0000920 db_cluster["current_operation"] = None
rshri932105f2024-07-05 15:11:55 +0000921 self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster)
922
923 return
924
rshri948f7de2024-12-02 03:42:35 +0000925 async def detach_profile(self, params, order_id):
rshri932105f2024-07-05 15:11:55 +0000926 self.logger.info("profile dettach Enter")
rshri948f7de2024-12-02 03:42:35 +0000927
garciadeblas995cbf32024-12-18 12:54:00 +0100928 # To get the cluster and op ids
rshri948f7de2024-12-02 03:42:35 +0000929 cluster_id = params["cluster_id"]
rshri948f7de2024-12-02 03:42:35 +0000930 op_id = params["operation_id"]
rshri948f7de2024-12-02 03:42:35 +0000931
932 # To initialize the operation states
933 self.initialize_operation(cluster_id, op_id)
934
garciadeblas995cbf32024-12-18 12:54:00 +0100935 # To get the cluster
936 db_cluster = self.db.get_one("clusters", {"_id": cluster_id})
937
938 # To get the operation params details
939 op_params = self.get_operation_params(db_cluster, op_id)
940
941 # To copy the cluster content and decrypting fields to use in workflows
942 workflow_content = {
943 "cluster": self.decrypted_copy(db_cluster),
944 }
rshri948f7de2024-12-02 03:42:35 +0000945
946 # To get the profile details
947 profile_id = params["profile_id"]
948 profile_type = params["profile_type"]
949 profile_collection = self.profile_collection_mapping[profile_type]
950 db_profile = self.db.get_one(profile_collection, {"_id": profile_id})
951 db_profile["profile_type"] = profile_type
garciadeblas995cbf32024-12-18 12:54:00 +0100952 workflow_content["profile"] = db_profile
rshri932105f2024-07-05 15:11:55 +0000953
garciadeblasdc805482025-02-04 16:08:51 +0100954 workflow_res, workflow_name = await self.odu.launch_workflow(
garciadeblas995cbf32024-12-18 12:54:00 +0100955 "detach_profile_from_cluster", op_id, op_params, workflow_content
garciadeblas96b94f52024-07-08 16:18:21 +0200956 )
garciadeblasdc805482025-02-04 16:08:51 +0100957 if not workflow_res:
958 self.logger.error(f"Failed to launch workflow: {workflow_name}")
959 db_cluster["resourceState"] = "ERROR"
960 db_cluster = self.update_operation_history(
961 db_cluster, op_id, workflow_status=False, resource_status=None
962 )
963 self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster)
964 return
rshri932105f2024-07-05 15:11:55 +0000965
garciadeblas891f2002025-02-03 16:12:43 +0100966 self.logger.info("workflow_name is: {}".format(workflow_name))
garciadeblas96b94f52024-07-08 16:18:21 +0200967 workflow_status, workflow_msg = await self.odu.check_workflow_status(
garciadeblas36fe58b2025-02-05 16:36:17 +0100968 op_id, workflow_name
garciadeblas96b94f52024-07-08 16:18:21 +0200969 )
rshri932105f2024-07-05 15:11:55 +0000970 self.logger.info(
garciadeblas891f2002025-02-03 16:12:43 +0100971 "workflow_status is: {} and workflow_msg is: {}".format(
rshri932105f2024-07-05 15:11:55 +0000972 workflow_status, workflow_msg
973 )
974 )
975 if workflow_status:
976 db_cluster["resourceState"] = "IN_PROGRESS.GIT_SYNCED"
977 else:
978 db_cluster["resourceState"] = "ERROR"
979 # has to call update_operation_history return content
yshahcb9075f2024-11-22 12:08:57 +0000980 db_cluster = self.update_operation_history(
981 db_cluster, op_id, workflow_status, None
982 )
rshri932105f2024-07-05 15:11:55 +0000983 self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster)
984
985 if workflow_status:
garciadeblas72412282024-11-07 12:41:54 +0100986 resource_status, resource_msg = await self.check_resource_status(
garciadeblas995cbf32024-12-18 12:54:00 +0100987 "detach_profile_from_cluster", op_id, op_params, workflow_content
rshri932105f2024-07-05 15:11:55 +0000988 )
989 self.logger.info(
990 "resource_status is :{} and resource_msg is :{}".format(
991 resource_status, resource_msg
992 )
993 )
994 if resource_status:
995 db_cluster["resourceState"] = "READY"
996 else:
997 db_cluster["resourceState"] = "ERROR"
998
999 db_cluster["operatingState"] = "IDLE"
1000 db_cluster = self.update_operation_history(
yshahcb9075f2024-11-22 12:08:57 +00001001 db_cluster, op_id, workflow_status, resource_status
rshri932105f2024-07-05 15:11:55 +00001002 )
rshri932105f2024-07-05 15:11:55 +00001003 profile_list = db_cluster[profile_type]
1004 self.logger.info("profile list is : {}".format(profile_list))
1005 if resource_status:
rshri932105f2024-07-05 15:11:55 +00001006 profile_list.remove(profile_id)
rshri932105f2024-07-05 15:11:55 +00001007 db_cluster[profile_type] = profile_list
shahithya70a3fc92024-11-12 11:01:05 +00001008 db_cluster["current_operation"] = None
rshri932105f2024-07-05 15:11:55 +00001009 self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster)
1010
1011 return
1012
rshri948f7de2024-12-02 03:42:35 +00001013 async def register(self, params, order_id):
rshri932105f2024-07-05 15:11:55 +00001014 self.logger.info("cluster register enter")
garciadeblas5861b0d2025-04-04 00:19:13 +02001015 workflow_status = None
1016 resource_status = None
rshri932105f2024-07-05 15:11:55 +00001017
garciadeblas995cbf32024-12-18 12:54:00 +01001018 # To get the cluster and op ids
rshri948f7de2024-12-02 03:42:35 +00001019 cluster_id = params["cluster_id"]
rshri948f7de2024-12-02 03:42:35 +00001020 op_id = params["operation_id"]
rshri948f7de2024-12-02 03:42:35 +00001021
1022 # To initialize the operation states
1023 self.initialize_operation(cluster_id, op_id)
1024
garciadeblas995cbf32024-12-18 12:54:00 +01001025 # To get the cluster
1026 db_cluster = self.db.get_one("clusters", {"_id": cluster_id})
1027
1028 # To get the operation params details
1029 op_params = self.get_operation_params(db_cluster, op_id)
1030
1031 # To copy the cluster content and decrypting fields to use in workflows
garciadeblas5861b0d2025-04-04 00:19:13 +02001032 db_cluster_copy = self.decrypted_copy(db_cluster)
garciadeblas995cbf32024-12-18 12:54:00 +01001033 workflow_content = {
garciadeblas5861b0d2025-04-04 00:19:13 +02001034 "cluster": db_cluster_copy,
garciadeblas995cbf32024-12-18 12:54:00 +01001035 }
rshric3564942024-11-12 18:12:38 +00001036
garciadeblasdc805482025-02-04 16:08:51 +01001037 workflow_res, workflow_name = await self.odu.launch_workflow(
garciadeblas995cbf32024-12-18 12:54:00 +01001038 "register_cluster", op_id, op_params, workflow_content
garciadeblas96b94f52024-07-08 16:18:21 +02001039 )
garciadeblasdc805482025-02-04 16:08:51 +01001040 if not workflow_res:
1041 self.logger.error(f"Failed to launch workflow: {workflow_name}")
1042 db_cluster["state"] = "FAILED_CREATION"
1043 db_cluster["resourceState"] = "ERROR"
1044 db_cluster = self.update_operation_history(
1045 db_cluster, op_id, workflow_status=False, resource_status=None
1046 )
1047 self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster)
1048 # Clean items used in the workflow, no matter if the workflow succeeded
1049 clean_status, clean_msg = await self.odu.clean_items_workflow(
1050 "register_cluster", op_id, op_params, workflow_content
1051 )
1052 self.logger.info(
1053 f"clean_status is :{clean_status} and clean_msg is :{clean_msg}"
1054 )
1055 return
rshri932105f2024-07-05 15:11:55 +00001056
garciadeblas891f2002025-02-03 16:12:43 +01001057 self.logger.info("workflow_name is: {}".format(workflow_name))
garciadeblas96b94f52024-07-08 16:18:21 +02001058 workflow_status, workflow_msg = await self.odu.check_workflow_status(
garciadeblas36fe58b2025-02-05 16:36:17 +01001059 op_id, workflow_name
garciadeblas96b94f52024-07-08 16:18:21 +02001060 )
rshri932105f2024-07-05 15:11:55 +00001061 self.logger.info(
garciadeblas891f2002025-02-03 16:12:43 +01001062 "workflow_status is: {} and workflow_msg is: {}".format(
rshri932105f2024-07-05 15:11:55 +00001063 workflow_status, workflow_msg
1064 )
1065 )
1066 if workflow_status:
garciadeblas96b94f52024-07-08 16:18:21 +02001067 db_cluster["state"] = "CREATED"
1068 db_cluster["resourceState"] = "IN_PROGRESS.GIT_SYNCED"
rshri932105f2024-07-05 15:11:55 +00001069 else:
garciadeblas96b94f52024-07-08 16:18:21 +02001070 db_cluster["state"] = "FAILED_CREATION"
1071 db_cluster["resourceState"] = "ERROR"
rshri932105f2024-07-05 15:11:55 +00001072 # has to call update_operation_history return content
yshahcb9075f2024-11-22 12:08:57 +00001073 db_cluster = self.update_operation_history(
1074 db_cluster, op_id, workflow_status, None
1075 )
garciadeblas96b94f52024-07-08 16:18:21 +02001076 self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster)
rshri932105f2024-07-05 15:11:55 +00001077
garciadeblasdde3a312024-09-17 13:25:06 +02001078 # Clean items used in the workflow, no matter if the workflow succeeded
1079 clean_status, clean_msg = await self.odu.clean_items_workflow(
garciadeblas995cbf32024-12-18 12:54:00 +01001080 "register_cluster", op_id, op_params, workflow_content
garciadeblasdde3a312024-09-17 13:25:06 +02001081 )
1082 self.logger.info(
1083 f"clean_status is :{clean_status} and clean_msg is :{clean_msg}"
1084 )
1085
rshri932105f2024-07-05 15:11:55 +00001086 if workflow_status:
garciadeblas72412282024-11-07 12:41:54 +01001087 resource_status, resource_msg = await self.check_resource_status(
garciadeblas995cbf32024-12-18 12:54:00 +01001088 "register_cluster", op_id, op_params, workflow_content
rshri932105f2024-07-05 15:11:55 +00001089 )
1090 self.logger.info(
1091 "resource_status is :{} and resource_msg is :{}".format(
1092 resource_status, resource_msg
1093 )
1094 )
1095 if resource_status:
garciadeblas96b94f52024-07-08 16:18:21 +02001096 db_cluster["resourceState"] = "READY"
rshri932105f2024-07-05 15:11:55 +00001097 else:
garciadeblas96b94f52024-07-08 16:18:21 +02001098 db_cluster["resourceState"] = "ERROR"
rshri932105f2024-07-05 15:11:55 +00001099
garciadeblas96b94f52024-07-08 16:18:21 +02001100 db_cluster["operatingState"] = "IDLE"
1101 db_cluster = self.update_operation_history(
yshahcb9075f2024-11-22 12:08:57 +00001102 db_cluster, op_id, workflow_status, resource_status
rshri932105f2024-07-05 15:11:55 +00001103 )
shahithya70a3fc92024-11-12 11:01:05 +00001104 db_cluster["current_operation"] = None
garciadeblas96b94f52024-07-08 16:18:21 +02001105 self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster)
rshri948f7de2024-12-02 03:42:35 +00001106
garciadeblas5861b0d2025-04-04 00:19:13 +02001107 # Update default profile agekeys and state
1108 self.update_default_profile_agekeys(db_cluster_copy)
1109 self.update_profile_state(db_cluster, workflow_status, resource_status)
1110
rshri948f7de2024-12-02 03:42:35 +00001111 db_register = self.db.get_one("k8sclusters", {"name": db_cluster["name"]})
1112 db_register["credentials"] = db_cluster["credentials"]
1113 self.db.set_one("k8sclusters", {"_id": db_register["_id"]}, db_register)
1114
1115 if db_cluster["resourceState"] == "READY" and db_cluster["state"] == "CREATED":
1116 # To call the lcm.py for registering the cluster in k8scluster lcm.
1117 register = await self.regist.create(db_register, order_id)
1118 self.logger.debug(f"Register is : {register}")
1119 else:
1120 db_register["_admin"]["operationalState"] = "ERROR"
1121 self.db.set_one("k8sclusters", {"_id": db_register["_id"]}, db_register)
1122
rshri932105f2024-07-05 15:11:55 +00001123 return
1124
garciadeblasbc96f382025-01-22 16:02:18 +01001125 async def check_register_cluster(self, op_id, op_params, content):
1126 self.logger.info(
1127 f"check_register_cluster Operation {op_id}. Params: {op_params}."
1128 )
1129 # self.logger.debug(f"Content: {content}")
1130 db_cluster = content["cluster"]
1131 cluster_name = db_cluster["git_name"].lower()
1132 cluster_kustomization_name = cluster_name
1133 bootstrap = op_params.get("bootstrap", True)
1134 checkings_list = [
1135 {
1136 "item": "kustomization",
1137 "name": f"{cluster_kustomization_name}-bstrp-fluxctrl",
1138 "namespace": "managed-resources",
garciadeblas6c82c352025-01-27 16:53:45 +01001139 "condition": {
1140 "jsonpath_filter": "status.conditions[?(@.type=='Ready')].status",
1141 "value": "True",
1142 },
garciadeblasbc96f382025-01-22 16:02:18 +01001143 "timeout": self._checkloop_kustomization_timeout,
1144 "enable": bootstrap,
1145 "resourceState": "IN_PROGRESS.BOOTSTRAP_OK",
1146 },
1147 ]
1148 return await self.common_check_list(
1149 op_id, checkings_list, "clusters", db_cluster
1150 )
1151
rshri948f7de2024-12-02 03:42:35 +00001152 async def deregister(self, params, order_id):
rshri932105f2024-07-05 15:11:55 +00001153 self.logger.info("cluster deregister enter")
1154
garciadeblas995cbf32024-12-18 12:54:00 +01001155 # To get the cluster and op ids
rshri948f7de2024-12-02 03:42:35 +00001156 cluster_id = params["cluster_id"]
rshri948f7de2024-12-02 03:42:35 +00001157 op_id = params["operation_id"]
rshri948f7de2024-12-02 03:42:35 +00001158
1159 # To initialize the operation states
1160 self.initialize_operation(cluster_id, op_id)
1161
garciadeblas995cbf32024-12-18 12:54:00 +01001162 # To get the cluster
1163 db_cluster = self.db.get_one("clusters", {"_id": cluster_id})
1164
1165 # To get the operation params details
1166 op_params = self.get_operation_params(db_cluster, op_id)
1167
1168 # To copy the cluster content and decrypting fields to use in workflows
1169 workflow_content = {
1170 "cluster": self.decrypted_copy(db_cluster),
1171 }
rshri932105f2024-07-05 15:11:55 +00001172
garciadeblasdc805482025-02-04 16:08:51 +01001173 workflow_res, workflow_name = await self.odu.launch_workflow(
garciadeblas995cbf32024-12-18 12:54:00 +01001174 "deregister_cluster", op_id, op_params, workflow_content
garciadeblas96b94f52024-07-08 16:18:21 +02001175 )
garciadeblasdc805482025-02-04 16:08:51 +01001176 if not workflow_res:
1177 self.logger.error(f"Failed to launch workflow: {workflow_name}")
1178 db_cluster["state"] = "FAILED_DELETION"
1179 db_cluster["resourceState"] = "ERROR"
1180 db_cluster = self.update_operation_history(
1181 db_cluster, op_id, workflow_status=False, resource_status=None
1182 )
1183 self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster)
garciadeblasdc805482025-02-04 16:08:51 +01001184 return
rshri932105f2024-07-05 15:11:55 +00001185
garciadeblas891f2002025-02-03 16:12:43 +01001186 self.logger.info("workflow_name is: {}".format(workflow_name))
garciadeblas96b94f52024-07-08 16:18:21 +02001187 workflow_status, workflow_msg = await self.odu.check_workflow_status(
garciadeblas36fe58b2025-02-05 16:36:17 +01001188 op_id, workflow_name
garciadeblas96b94f52024-07-08 16:18:21 +02001189 )
rshri932105f2024-07-05 15:11:55 +00001190 self.logger.info(
garciadeblas891f2002025-02-03 16:12:43 +01001191 "workflow_status is: {} and workflow_msg is: {}".format(
rshri932105f2024-07-05 15:11:55 +00001192 workflow_status, workflow_msg
1193 )
1194 )
1195 if workflow_status:
garciadeblas96b94f52024-07-08 16:18:21 +02001196 db_cluster["resourceState"] = "IN_PROGRESS.GIT_SYNCED"
rshri932105f2024-07-05 15:11:55 +00001197 else:
garciadeblas96b94f52024-07-08 16:18:21 +02001198 db_cluster["state"] = "FAILED_DELETION"
1199 db_cluster["resourceState"] = "ERROR"
rshri932105f2024-07-05 15:11:55 +00001200 # has to call update_operation_history return content
yshahcb9075f2024-11-22 12:08:57 +00001201 db_cluster = self.update_operation_history(
1202 db_cluster, op_id, workflow_status, None
1203 )
garciadeblas96b94f52024-07-08 16:18:21 +02001204 self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster)
rshri932105f2024-07-05 15:11:55 +00001205
1206 if workflow_status:
garciadeblas72412282024-11-07 12:41:54 +01001207 resource_status, resource_msg = await self.check_resource_status(
garciadeblas995cbf32024-12-18 12:54:00 +01001208 "deregister_cluster", op_id, op_params, workflow_content
rshri932105f2024-07-05 15:11:55 +00001209 )
1210 self.logger.info(
1211 "resource_status is :{} and resource_msg is :{}".format(
1212 resource_status, resource_msg
1213 )
1214 )
1215 if resource_status:
garciadeblas96b94f52024-07-08 16:18:21 +02001216 db_cluster["resourceState"] = "READY"
rshri932105f2024-07-05 15:11:55 +00001217 else:
garciadeblas96b94f52024-07-08 16:18:21 +02001218 db_cluster["resourceState"] = "ERROR"
rshri932105f2024-07-05 15:11:55 +00001219
garciadeblas96b94f52024-07-08 16:18:21 +02001220 db_cluster = self.update_operation_history(
yshahcb9075f2024-11-22 12:08:57 +00001221 db_cluster, op_id, workflow_status, resource_status
garciadeblas96b94f52024-07-08 16:18:21 +02001222 )
1223 self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster)
rshri932105f2024-07-05 15:11:55 +00001224
garciadeblas14984462025-02-05 09:32:52 +01001225 await self.delete(params, order_id)
1226 # Clean items used in the workflow or in the cluster, no matter if the workflow succeeded
1227 clean_status, clean_msg = await self.odu.clean_items_workflow(
1228 "deregister_cluster", op_id, op_params, workflow_content
1229 )
1230 self.logger.info(
1231 f"clean_status is :{clean_status} and clean_msg is :{clean_msg}"
1232 )
1233 return
rshri932105f2024-07-05 15:11:55 +00001234
rshri948f7de2024-12-02 03:42:35 +00001235 async def get_creds(self, params, order_id):
garciadeblas96b94f52024-07-08 16:18:21 +02001236 self.logger.info("Cluster get creds Enter")
rshri948f7de2024-12-02 03:42:35 +00001237 cluster_id = params["cluster_id"]
1238 op_id = params["operation_id"]
1239 db_cluster = self.db.get_one("clusters", {"_id": cluster_id})
garciadeblas96b94f52024-07-08 16:18:21 +02001240 result, cluster_creds = await self.odu.get_cluster_credentials(db_cluster)
1241 if result:
1242 db_cluster["credentials"] = cluster_creds
yshahd940c652024-10-17 06:11:12 +00001243 op_len = 0
1244 for operations in db_cluster["operationHistory"]:
1245 if operations["op_id"] == op_id:
1246 db_cluster["operationHistory"][op_len]["result"] = result
1247 db_cluster["operationHistory"][op_len]["endDate"] = time()
1248 op_len += 1
shahithya70a3fc92024-11-12 11:01:05 +00001249 db_cluster["current_operation"] = None
yshahd940c652024-10-17 06:11:12 +00001250 self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster)
rshri948f7de2024-12-02 03:42:35 +00001251 self.logger.info("Cluster Get Creds Exit")
yshah771dea82024-07-05 15:11:49 +00001252 return
1253
rshri948f7de2024-12-02 03:42:35 +00001254 async def update(self, params, order_id):
garciadeblas96b94f52024-07-08 16:18:21 +02001255 self.logger.info("Cluster update Enter")
rshri948f7de2024-12-02 03:42:35 +00001256 # To get the cluster details
1257 cluster_id = params["cluster_id"]
1258 db_cluster = self.db.get_one("clusters", {"_id": cluster_id})
1259
1260 # To get the operation params details
1261 op_id = params["operation_id"]
1262 op_params = self.get_operation_params(db_cluster, op_id)
yshah771dea82024-07-05 15:11:49 +00001263
garciadeblas995cbf32024-12-18 12:54:00 +01001264 # To copy the cluster content and decrypting fields to use in workflows
1265 workflow_content = {
1266 "cluster": self.decrypted_copy(db_cluster),
1267 }
rshric3564942024-11-12 18:12:38 +00001268
1269 # vim account details
1270 db_vim = self.db.get_one("vim_accounts", {"name": db_cluster["vim_account"]})
garciadeblas995cbf32024-12-18 12:54:00 +01001271 workflow_content["vim_account"] = db_vim
rshric3564942024-11-12 18:12:38 +00001272
garciadeblasdc805482025-02-04 16:08:51 +01001273 workflow_res, workflow_name = await self.odu.launch_workflow(
garciadeblas995cbf32024-12-18 12:54:00 +01001274 "update_cluster", op_id, op_params, workflow_content
garciadeblas96b94f52024-07-08 16:18:21 +02001275 )
garciadeblasdc805482025-02-04 16:08:51 +01001276 if not workflow_res:
1277 self.logger.error(f"Failed to launch workflow: {workflow_name}")
1278 db_cluster["resourceState"] = "ERROR"
1279 db_cluster = self.update_operation_history(
1280 db_cluster, op_id, workflow_status=False, resource_status=None
1281 )
1282 self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster)
1283 # Clean items used in the workflow, no matter if the workflow succeeded
1284 clean_status, clean_msg = await self.odu.clean_items_workflow(
1285 "update_cluster", op_id, op_params, workflow_content
1286 )
1287 self.logger.info(
1288 f"clean_status is :{clean_status} and clean_msg is :{clean_msg}"
1289 )
1290 return
garciadeblas891f2002025-02-03 16:12:43 +01001291 self.logger.info("workflow_name is: {}".format(workflow_name))
garciadeblas96b94f52024-07-08 16:18:21 +02001292 workflow_status, workflow_msg = await self.odu.check_workflow_status(
garciadeblas36fe58b2025-02-05 16:36:17 +01001293 op_id, workflow_name
garciadeblas96b94f52024-07-08 16:18:21 +02001294 )
1295 self.logger.info(
1296 "Workflow Status: {} Workflow Message: {}".format(
1297 workflow_status, workflow_msg
yshah771dea82024-07-05 15:11:49 +00001298 )
garciadeblas96b94f52024-07-08 16:18:21 +02001299 )
1300
1301 if workflow_status:
1302 db_cluster["resourceState"] = "IN_PROGRESS.GIT_SYNCED"
1303 else:
1304 db_cluster["resourceState"] = "ERROR"
1305
yshahcb9075f2024-11-22 12:08:57 +00001306 db_cluster = self.update_operation_history(
1307 db_cluster, op_id, workflow_status, None
1308 )
garciadeblas96b94f52024-07-08 16:18:21 +02001309 # self.logger.info("Db content: {}".format(db_content))
1310 # self.db.set_one(self.db_collection, {"_id": _id}, db_cluster)
1311 self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster)
1312
garciadeblas28bff0f2024-09-16 12:53:07 +02001313 # Clean items used in the workflow, no matter if the workflow succeeded
1314 clean_status, clean_msg = await self.odu.clean_items_workflow(
garciadeblas995cbf32024-12-18 12:54:00 +01001315 "update_cluster", op_id, op_params, workflow_content
garciadeblas28bff0f2024-09-16 12:53:07 +02001316 )
1317 self.logger.info(
1318 f"clean_status is :{clean_status} and clean_msg is :{clean_msg}"
1319 )
garciadeblas96b94f52024-07-08 16:18:21 +02001320 if workflow_status:
garciadeblas72412282024-11-07 12:41:54 +01001321 resource_status, resource_msg = await self.check_resource_status(
garciadeblas995cbf32024-12-18 12:54:00 +01001322 "update_cluster", op_id, op_params, workflow_content
garciadeblas96b94f52024-07-08 16:18:21 +02001323 )
1324 self.logger.info(
1325 "Resource Status: {} Resource Message: {}".format(
1326 resource_status, resource_msg
1327 )
1328 )
yshah771dea82024-07-05 15:11:49 +00001329
1330 if resource_status:
garciadeblas96b94f52024-07-08 16:18:21 +02001331 db_cluster["resourceState"] = "READY"
yshah771dea82024-07-05 15:11:49 +00001332 else:
garciadeblas96b94f52024-07-08 16:18:21 +02001333 db_cluster["resourceState"] = "ERROR"
yshah771dea82024-07-05 15:11:49 +00001334
yshah0defcd52024-11-18 07:41:35 +00001335 db_cluster = self.update_operation_history(
yshahcb9075f2024-11-22 12:08:57 +00001336 db_cluster, op_id, workflow_status, resource_status
yshah0defcd52024-11-18 07:41:35 +00001337 )
1338
garciadeblas96b94f52024-07-08 16:18:21 +02001339 db_cluster["operatingState"] = "IDLE"
garciadeblas96b94f52024-07-08 16:18:21 +02001340 # self.logger.info("db_cluster: {}".format(db_cluster))
garciadeblas6c82c352025-01-27 16:53:45 +01001341 # TODO: verify condition
garciadeblas96b94f52024-07-08 16:18:21 +02001342 # For the moment, if the workflow completed successfully, then we update the db accordingly.
1343 if workflow_status:
1344 if "k8s_version" in op_params:
1345 db_cluster["k8s_version"] = op_params["k8s_version"]
yshah0defcd52024-11-18 07:41:35 +00001346 if "node_count" in op_params:
garciadeblas96b94f52024-07-08 16:18:21 +02001347 db_cluster["node_count"] = op_params["node_count"]
yshah0defcd52024-11-18 07:41:35 +00001348 if "node_size" in op_params:
1349 db_cluster["node_count"] = op_params["node_size"]
garciadeblas96b94f52024-07-08 16:18:21 +02001350 # self.db.set_one(self.db_collection, {"_id": _id}, db_content)
shahithya70a3fc92024-11-12 11:01:05 +00001351 db_cluster["current_operation"] = None
garciadeblas96b94f52024-07-08 16:18:21 +02001352 self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster)
yshah771dea82024-07-05 15:11:49 +00001353 return
1354
garciadeblasbc96f382025-01-22 16:02:18 +01001355 async def check_update_cluster(self, op_id, op_params, content):
1356 self.logger.info(
1357 f"check_update_cluster Operation {op_id}. Params: {op_params}."
1358 )
1359 self.logger.debug(f"Content: {content}")
garciadeblas39eb5092025-01-27 18:31:06 +01001360 # return await self.check_dummy_operation(op_id, op_params, content)
1361 db_cluster = content["cluster"]
1362 cluster_name = db_cluster["git_name"].lower()
1363 cluster_kustomization_name = cluster_name
1364 db_vim_account = content["vim_account"]
1365 cloud_type = db_vim_account["vim_type"]
1366 if cloud_type == "aws":
1367 cluster_name = f"{cluster_name}-cluster"
1368 if cloud_type in ("azure", "gcp", "aws"):
1369 checkings_list = [
1370 {
1371 "item": "kustomization",
1372 "name": cluster_kustomization_name,
1373 "namespace": "managed-resources",
1374 "condition": {
1375 "jsonpath_filter": "status.conditions[?(@.type=='Ready')].status",
1376 "value": "True",
1377 },
1378 "timeout": self._checkloop_kustomization_timeout,
1379 "enable": True,
1380 "resourceState": "IN_PROGRESS.KUSTOMIZATION_READY",
1381 },
1382 ]
1383 else:
1384 return False, "Not suitable VIM account to check cluster status"
1385 # Scale operation
1386 if "node_count" in op_params:
garciadeblasbccc0602025-05-30 11:19:06 +02001387 if cloud_type in ("azure", "gcp"):
1388 checkings_list.append(
1389 {
1390 "item": f"cluster_{cloud_type}",
1391 "name": cluster_name,
1392 "namespace": "",
1393 "condition": {
1394 "jsonpath_filter": "status.atProvider.defaultNodePool[0].nodeCount",
1395 "value": f"{op_params['node_count']}",
1396 },
1397 "timeout": self._checkloop_resource_timeout * 3,
1398 "enable": True,
1399 "resourceState": "IN_PROGRESS.RESOURCE_READY.NODE_COUNT.CLUSTER",
1400 }
1401 )
1402 elif cloud_type == "aws":
1403 checkings_list.append(
1404 {
1405 "item": f"nodegroup_{cloud_type}",
1406 "name": f"{cluster_name}-nodegroup",
1407 "namespace": "",
1408 "condition": {
1409 "jsonpath_filter": "status.atProvider.scalingConfig[0].desiredSize",
1410 "value": f"{op_params['node_count']}",
1411 },
1412 "timeout": self._checkloop_resource_timeout * 3,
1413 "enable": True,
1414 "resourceState": "IN_PROGRESS.RESOURCE_READY.NODE_COUNT.CLUSTER",
1415 }
1416 )
1417
garciadeblas39eb5092025-01-27 18:31:06 +01001418 # Upgrade operation
1419 if "k8s_version" in op_params:
1420 checkings_list.append(
1421 {
1422 "item": f"cluster_{cloud_type}",
1423 "name": cluster_name,
1424 "namespace": "",
1425 "condition": {
1426 "jsonpath_filter": "status.atProvider.defaultNodePool[0].orchestratorVersion",
1427 "value": op_params["k8s_version"],
1428 },
1429 "timeout": self._checkloop_resource_timeout * 2,
1430 "enable": True,
1431 "resourceState": "IN_PROGRESS.RESOURCE_READY.K8S_VERSION.CLUSTER",
1432 }
1433 )
1434 return await self.common_check_list(
1435 op_id, checkings_list, "clusters", db_cluster
1436 )
garciadeblasbc96f382025-01-22 16:02:18 +01001437
yshah771dea82024-07-05 15:11:49 +00001438
garciadeblas72412282024-11-07 12:41:54 +01001439class CloudCredentialsLcm(GitOpsLcm):
yshah771dea82024-07-05 15:11:49 +00001440 db_collection = "vim_accounts"
1441
1442 def __init__(self, msg, lcm_tasks, config):
1443 """
1444 Init, Connect to database, filesystem storage, and messaging
1445 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
1446 :return: None
1447 """
garciadeblas72412282024-11-07 12:41:54 +01001448 super().__init__(msg, lcm_tasks, config)
yshah771dea82024-07-05 15:11:49 +00001449
yshah564ec9c2024-11-29 07:33:32 +00001450 async def add(self, params, order_id):
yshah771dea82024-07-05 15:11:49 +00001451 self.logger.info("Cloud Credentials create")
yshah564ec9c2024-11-29 07:33:32 +00001452 vim_id = params["_id"]
1453 op_id = vim_id
1454 op_params = params
1455 db_content = self.db.get_one(self.db_collection, {"_id": vim_id})
1456 vim_config = db_content.get("config", {})
1457 self.db.encrypt_decrypt_fields(
1458 vim_config.get("credentials"),
1459 "decrypt",
1460 ["password", "secret"],
1461 schema_version=db_content["schema_version"],
1462 salt=vim_id,
1463 )
1464
garciadeblasdc805482025-02-04 16:08:51 +01001465 workflow_res, workflow_name = await self.odu.launch_workflow(
yshah564ec9c2024-11-29 07:33:32 +00001466 "create_cloud_credentials", op_id, op_params, db_content
yshah771dea82024-07-05 15:11:49 +00001467 )
1468
1469 workflow_status, workflow_msg = await self.odu.check_workflow_status(
garciadeblas36fe58b2025-02-05 16:36:17 +01001470 op_id, workflow_name
yshah771dea82024-07-05 15:11:49 +00001471 )
1472
1473 self.logger.info(
1474 "Workflow Status: {} Workflow Msg: {}".format(workflow_status, workflow_msg)
1475 )
1476
garciadeblas28bff0f2024-09-16 12:53:07 +02001477 # Clean items used in the workflow, no matter if the workflow succeeded
1478 clean_status, clean_msg = await self.odu.clean_items_workflow(
yshah564ec9c2024-11-29 07:33:32 +00001479 "create_cloud_credentials", op_id, op_params, db_content
garciadeblas28bff0f2024-09-16 12:53:07 +02001480 )
1481 self.logger.info(
1482 f"clean_status is :{clean_status} and clean_msg is :{clean_msg}"
1483 )
1484
yshah771dea82024-07-05 15:11:49 +00001485 if workflow_status:
garciadeblas72412282024-11-07 12:41:54 +01001486 resource_status, resource_msg = await self.check_resource_status(
yshah564ec9c2024-11-29 07:33:32 +00001487 "create_cloud_credentials", op_id, op_params, db_content
yshah771dea82024-07-05 15:11:49 +00001488 )
1489 self.logger.info(
1490 "Resource Status: {} Resource Message: {}".format(
1491 resource_status, resource_msg
1492 )
1493 )
garciadeblas15b8a302024-09-23 12:40:13 +02001494
yshah564ec9c2024-11-29 07:33:32 +00001495 db_content["_admin"]["operationalState"] = "ENABLED"
1496 for operation in db_content["_admin"]["operations"]:
garciadeblas15b8a302024-09-23 12:40:13 +02001497 if operation["lcmOperationType"] == "create":
1498 operation["operationState"] = "ENABLED"
yshah564ec9c2024-11-29 07:33:32 +00001499 self.logger.info("Content : {}".format(db_content))
1500 self.db.set_one("vim_accounts", {"_id": db_content["_id"]}, db_content)
yshah771dea82024-07-05 15:11:49 +00001501 return
1502
yshah564ec9c2024-11-29 07:33:32 +00001503 async def edit(self, params, order_id):
1504 self.logger.info("Cloud Credentials Update")
1505 vim_id = params["_id"]
1506 op_id = vim_id
1507 op_params = params
1508 db_content = self.db.get_one("vim_accounts", {"_id": vim_id})
1509 vim_config = db_content.get("config", {})
1510 self.db.encrypt_decrypt_fields(
1511 vim_config.get("credentials"),
1512 "decrypt",
1513 ["password", "secret"],
1514 schema_version=db_content["schema_version"],
1515 salt=vim_id,
1516 )
1517
garciadeblasdc805482025-02-04 16:08:51 +01001518 workflow_res, workflow_name = await self.odu.launch_workflow(
yshah564ec9c2024-11-29 07:33:32 +00001519 "update_cloud_credentials", op_id, op_params, db_content
yshah771dea82024-07-05 15:11:49 +00001520 )
1521 workflow_status, workflow_msg = await self.odu.check_workflow_status(
garciadeblas36fe58b2025-02-05 16:36:17 +01001522 op_id, workflow_name
yshah771dea82024-07-05 15:11:49 +00001523 )
1524 self.logger.info(
1525 "Workflow Status: {} Workflow Msg: {}".format(workflow_status, workflow_msg)
1526 )
1527
garciadeblas28bff0f2024-09-16 12:53:07 +02001528 # Clean items used in the workflow, no matter if the workflow succeeded
1529 clean_status, clean_msg = await self.odu.clean_items_workflow(
yshah564ec9c2024-11-29 07:33:32 +00001530 "update_cloud_credentials", op_id, op_params, db_content
garciadeblas28bff0f2024-09-16 12:53:07 +02001531 )
1532 self.logger.info(
1533 f"clean_status is :{clean_status} and clean_msg is :{clean_msg}"
1534 )
1535
yshah771dea82024-07-05 15:11:49 +00001536 if workflow_status:
garciadeblas72412282024-11-07 12:41:54 +01001537 resource_status, resource_msg = await self.check_resource_status(
yshah564ec9c2024-11-29 07:33:32 +00001538 "update_cloud_credentials", op_id, op_params, db_content
yshah771dea82024-07-05 15:11:49 +00001539 )
1540 self.logger.info(
1541 "Resource Status: {} Resource Message: {}".format(
1542 resource_status, resource_msg
1543 )
1544 )
1545 return
1546
yshah564ec9c2024-11-29 07:33:32 +00001547 async def remove(self, params, order_id):
1548 self.logger.info("Cloud Credentials remove")
1549 vim_id = params["_id"]
1550 op_id = vim_id
1551 op_params = params
1552 db_content = self.db.get_one("vim_accounts", {"_id": vim_id})
1553
garciadeblasdc805482025-02-04 16:08:51 +01001554 workflow_res, workflow_name = await self.odu.launch_workflow(
yshah564ec9c2024-11-29 07:33:32 +00001555 "delete_cloud_credentials", op_id, op_params, db_content
yshah771dea82024-07-05 15:11:49 +00001556 )
1557 workflow_status, workflow_msg = await self.odu.check_workflow_status(
garciadeblas36fe58b2025-02-05 16:36:17 +01001558 op_id, workflow_name
yshah771dea82024-07-05 15:11:49 +00001559 )
1560 self.logger.info(
1561 "Workflow Status: {} Workflow Msg: {}".format(workflow_status, workflow_msg)
1562 )
1563
1564 if workflow_status:
garciadeblas72412282024-11-07 12:41:54 +01001565 resource_status, resource_msg = await self.check_resource_status(
yshah564ec9c2024-11-29 07:33:32 +00001566 "delete_cloud_credentials", op_id, op_params, db_content
yshah771dea82024-07-05 15:11:49 +00001567 )
1568 self.logger.info(
1569 "Resource Status: {} Resource Message: {}".format(
1570 resource_status, resource_msg
1571 )
1572 )
yshah564ec9c2024-11-29 07:33:32 +00001573 self.db.del_one(self.db_collection, {"_id": db_content["_id"]})
yshah771dea82024-07-05 15:11:49 +00001574 return
1575
rshri932105f2024-07-05 15:11:55 +00001576
garciadeblas72412282024-11-07 12:41:54 +01001577class K8sAppLcm(GitOpsLcm):
rshri948f7de2024-12-02 03:42:35 +00001578 db_collection = "k8sapp"
1579
rshri932105f2024-07-05 15:11:55 +00001580 def __init__(self, msg, lcm_tasks, config):
1581 """
1582 Init, Connect to database, filesystem storage, and messaging
1583 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
1584 :return: None
1585 """
garciadeblas72412282024-11-07 12:41:54 +01001586 super().__init__(msg, lcm_tasks, config)
rshri932105f2024-07-05 15:11:55 +00001587
rshri948f7de2024-12-02 03:42:35 +00001588 async def create(self, params, order_id):
rshri932105f2024-07-05 15:11:55 +00001589 self.logger.info("App Create Enter")
1590
rshri948f7de2024-12-02 03:42:35 +00001591 op_id = params["operation_id"]
1592 profile_id = params["profile_id"]
1593
1594 # To initialize the operation states
1595 self.initialize_operation(profile_id, op_id)
1596
1597 content = self.db.get_one("k8sapp", {"_id": profile_id})
1598 content["profile_type"] = "applications"
1599 op_params = self.get_operation_params(content, op_id)
1600 self.db.set_one("k8sapp", {"_id": content["_id"]}, content)
1601
garciadeblasdc805482025-02-04 16:08:51 +01001602 workflow_res, workflow_name = await self.odu.launch_workflow(
garciadeblas96b94f52024-07-08 16:18:21 +02001603 "create_profile", op_id, op_params, content
1604 )
garciadeblas891f2002025-02-03 16:12:43 +01001605 self.logger.info("workflow_name is: {}".format(workflow_name))
rshri932105f2024-07-05 15:11:55 +00001606
garciadeblas713e1962025-01-17 12:49:19 +01001607 workflow_status = await self.check_workflow_and_update_db(
1608 op_id, workflow_name, content
1609 )
rshri932105f2024-07-05 15:11:55 +00001610
1611 if workflow_status:
garciadeblas713e1962025-01-17 12:49:19 +01001612 resource_status, content = await self.check_resource_and_update_db(
garciadeblas96b94f52024-07-08 16:18:21 +02001613 "create_profile", op_id, op_params, content
rshri932105f2024-07-05 15:11:55 +00001614 )
yshah564ec9c2024-11-29 07:33:32 +00001615 self.db.set_one(self.db_collection, {"_id": content["_id"]}, content)
1616 self.logger.info(f"App Create Exit with resource status: {resource_status}")
rshri932105f2024-07-05 15:11:55 +00001617 return
1618
rshri948f7de2024-12-02 03:42:35 +00001619 async def delete(self, params, order_id):
rshri932105f2024-07-05 15:11:55 +00001620 self.logger.info("App delete Enter")
rshri932105f2024-07-05 15:11:55 +00001621
rshri948f7de2024-12-02 03:42:35 +00001622 op_id = params["operation_id"]
1623 profile_id = params["profile_id"]
1624
1625 # To initialize the operation states
1626 self.initialize_operation(profile_id, op_id)
1627
1628 content = self.db.get_one("k8sapp", {"_id": profile_id})
1629 op_params = self.get_operation_params(content, op_id)
1630
garciadeblasdc805482025-02-04 16:08:51 +01001631 workflow_res, workflow_name = await self.odu.launch_workflow(
garciadeblas96b94f52024-07-08 16:18:21 +02001632 "delete_profile", op_id, op_params, content
1633 )
garciadeblas891f2002025-02-03 16:12:43 +01001634 self.logger.info("workflow_name is: {}".format(workflow_name))
rshri932105f2024-07-05 15:11:55 +00001635
garciadeblas713e1962025-01-17 12:49:19 +01001636 workflow_status = await self.check_workflow_and_update_db(
1637 op_id, workflow_name, content
1638 )
rshri932105f2024-07-05 15:11:55 +00001639
1640 if workflow_status:
garciadeblas713e1962025-01-17 12:49:19 +01001641 resource_status, content = await self.check_resource_and_update_db(
garciadeblas96b94f52024-07-08 16:18:21 +02001642 "delete_profile", op_id, op_params, content
rshri932105f2024-07-05 15:11:55 +00001643 )
rshri932105f2024-07-05 15:11:55 +00001644
yshah408de812025-02-28 09:01:51 +00001645 force = params.get("force", False)
1646 if force:
1647 force_delete_status = self.check_force_delete_and_delete_from_db(
1648 profile_id, workflow_status, resource_status, force
1649 )
1650 if force_delete_status:
1651 return
1652
1653 self.logger.info(f"Resource status: {resource_status}")
yshah564ec9c2024-11-29 07:33:32 +00001654 if resource_status:
1655 content["state"] = "DELETED"
yshah4998f502025-02-11 12:37:04 +00001656 profile_type = self.profile_type_mapping[content["profile_type"]]
1657 self.delete_profile_ksu(profile_id, profile_type)
yshah564ec9c2024-11-29 07:33:32 +00001658 self.db.set_one(self.db_collection, {"_id": content["_id"]}, content)
1659 self.db.del_one(self.db_collection, {"_id": content["_id"]})
1660 self.logger.info(f"App Delete Exit with resource status: {resource_status}")
rshri932105f2024-07-05 15:11:55 +00001661 return
1662
1663
garciadeblas72412282024-11-07 12:41:54 +01001664class K8sResourceLcm(GitOpsLcm):
rshri948f7de2024-12-02 03:42:35 +00001665 db_collection = "k8sresource"
1666
rshri932105f2024-07-05 15:11:55 +00001667 def __init__(self, msg, lcm_tasks, config):
1668 """
1669 Init, Connect to database, filesystem storage, and messaging
1670 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
1671 :return: None
1672 """
garciadeblas72412282024-11-07 12:41:54 +01001673 super().__init__(msg, lcm_tasks, config)
rshri932105f2024-07-05 15:11:55 +00001674
rshri948f7de2024-12-02 03:42:35 +00001675 async def create(self, params, order_id):
rshri932105f2024-07-05 15:11:55 +00001676 self.logger.info("Resource Create Enter")
1677
rshri948f7de2024-12-02 03:42:35 +00001678 op_id = params["operation_id"]
1679 profile_id = params["profile_id"]
1680
1681 # To initialize the operation states
1682 self.initialize_operation(profile_id, op_id)
1683
1684 content = self.db.get_one("k8sresource", {"_id": profile_id})
1685 content["profile_type"] = "managed-resources"
1686 op_params = self.get_operation_params(content, op_id)
1687 self.db.set_one("k8sresource", {"_id": content["_id"]}, content)
1688
garciadeblasdc805482025-02-04 16:08:51 +01001689 workflow_res, workflow_name = await self.odu.launch_workflow(
garciadeblas96b94f52024-07-08 16:18:21 +02001690 "create_profile", op_id, op_params, content
1691 )
garciadeblas891f2002025-02-03 16:12:43 +01001692 self.logger.info("workflow_name is: {}".format(workflow_name))
rshri932105f2024-07-05 15:11:55 +00001693
garciadeblas713e1962025-01-17 12:49:19 +01001694 workflow_status = await self.check_workflow_and_update_db(
1695 op_id, workflow_name, content
1696 )
rshri932105f2024-07-05 15:11:55 +00001697
1698 if workflow_status:
garciadeblas713e1962025-01-17 12:49:19 +01001699 resource_status, content = await self.check_resource_and_update_db(
garciadeblas96b94f52024-07-08 16:18:21 +02001700 "create_profile", op_id, op_params, content
rshri932105f2024-07-05 15:11:55 +00001701 )
yshah564ec9c2024-11-29 07:33:32 +00001702 self.db.set_one(self.db_collection, {"_id": content["_id"]}, content)
1703 self.logger.info(
1704 f"Resource Create Exit with resource status: {resource_status}"
rshri932105f2024-07-05 15:11:55 +00001705 )
rshri932105f2024-07-05 15:11:55 +00001706 return
1707
rshri948f7de2024-12-02 03:42:35 +00001708 async def delete(self, params, order_id):
rshri932105f2024-07-05 15:11:55 +00001709 self.logger.info("Resource delete Enter")
rshri948f7de2024-12-02 03:42:35 +00001710
1711 op_id = params["operation_id"]
1712 profile_id = params["profile_id"]
1713
1714 # To initialize the operation states
1715 self.initialize_operation(profile_id, op_id)
1716
1717 content = self.db.get_one("k8sresource", {"_id": profile_id})
1718 op_params = self.get_operation_params(content, op_id)
rshri932105f2024-07-05 15:11:55 +00001719
garciadeblasdc805482025-02-04 16:08:51 +01001720 workflow_res, workflow_name = await self.odu.launch_workflow(
garciadeblas96b94f52024-07-08 16:18:21 +02001721 "delete_profile", op_id, op_params, content
1722 )
garciadeblas891f2002025-02-03 16:12:43 +01001723 self.logger.info("workflow_name is: {}".format(workflow_name))
rshri932105f2024-07-05 15:11:55 +00001724
garciadeblas713e1962025-01-17 12:49:19 +01001725 workflow_status = await self.check_workflow_and_update_db(
1726 op_id, workflow_name, content
1727 )
rshri932105f2024-07-05 15:11:55 +00001728
1729 if workflow_status:
garciadeblas713e1962025-01-17 12:49:19 +01001730 resource_status, content = await self.check_resource_and_update_db(
garciadeblas96b94f52024-07-08 16:18:21 +02001731 "delete_profile", op_id, op_params, content
rshri932105f2024-07-05 15:11:55 +00001732 )
rshri932105f2024-07-05 15:11:55 +00001733
yshah408de812025-02-28 09:01:51 +00001734 force = params.get("force", False)
1735 if force:
1736 force_delete_status = self.check_force_delete_and_delete_from_db(
1737 profile_id, workflow_status, resource_status, force
1738 )
1739 if force_delete_status:
1740 return
1741
yshah564ec9c2024-11-29 07:33:32 +00001742 if resource_status:
1743 content["state"] = "DELETED"
yshah4998f502025-02-11 12:37:04 +00001744 profile_type = self.profile_type_mapping[content["profile_type"]]
1745 self.delete_profile_ksu(profile_id, profile_type)
yshah564ec9c2024-11-29 07:33:32 +00001746 self.db.set_one(self.db_collection, {"_id": content["_id"]}, content)
1747 self.db.del_one(self.db_collection, {"_id": content["_id"]})
1748 self.logger.info(
1749 f"Resource Delete Exit with resource status: {resource_status}"
garciadeblas96b94f52024-07-08 16:18:21 +02001750 )
rshri932105f2024-07-05 15:11:55 +00001751 return
1752
1753
garciadeblas72412282024-11-07 12:41:54 +01001754class K8sInfraControllerLcm(GitOpsLcm):
rshri948f7de2024-12-02 03:42:35 +00001755 db_collection = "k8sinfra_controller"
1756
rshri932105f2024-07-05 15:11:55 +00001757 def __init__(self, msg, lcm_tasks, config):
1758 """
1759 Init, Connect to database, filesystem storage, and messaging
1760 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
1761 :return: None
1762 """
garciadeblas72412282024-11-07 12:41:54 +01001763 super().__init__(msg, lcm_tasks, config)
rshri932105f2024-07-05 15:11:55 +00001764
rshri948f7de2024-12-02 03:42:35 +00001765 async def create(self, params, order_id):
rshri932105f2024-07-05 15:11:55 +00001766 self.logger.info("Infra controller Create Enter")
1767
rshri948f7de2024-12-02 03:42:35 +00001768 op_id = params["operation_id"]
1769 profile_id = params["profile_id"]
1770
1771 # To initialize the operation states
1772 self.initialize_operation(profile_id, op_id)
1773
1774 content = self.db.get_one("k8sinfra_controller", {"_id": profile_id})
1775 content["profile_type"] = "infra-controllers"
1776 op_params = self.get_operation_params(content, op_id)
1777 self.db.set_one("k8sinfra_controller", {"_id": content["_id"]}, content)
1778
garciadeblasdc805482025-02-04 16:08:51 +01001779 workflow_res, workflow_name = await self.odu.launch_workflow(
garciadeblas96b94f52024-07-08 16:18:21 +02001780 "create_profile", op_id, op_params, content
1781 )
garciadeblas891f2002025-02-03 16:12:43 +01001782 self.logger.info("workflow_name is: {}".format(workflow_name))
rshri932105f2024-07-05 15:11:55 +00001783
garciadeblas713e1962025-01-17 12:49:19 +01001784 workflow_status = await self.check_workflow_and_update_db(
1785 op_id, workflow_name, content
1786 )
rshri932105f2024-07-05 15:11:55 +00001787
1788 if workflow_status:
garciadeblas713e1962025-01-17 12:49:19 +01001789 resource_status, content = await self.check_resource_and_update_db(
garciadeblas96b94f52024-07-08 16:18:21 +02001790 "create_profile", op_id, op_params, content
rshri932105f2024-07-05 15:11:55 +00001791 )
yshah564ec9c2024-11-29 07:33:32 +00001792 self.db.set_one(self.db_collection, {"_id": content["_id"]}, content)
1793 self.logger.info(
1794 f"Infra Controller Create Exit with resource status: {resource_status}"
rshri932105f2024-07-05 15:11:55 +00001795 )
rshri932105f2024-07-05 15:11:55 +00001796 return
1797
rshri948f7de2024-12-02 03:42:35 +00001798 async def delete(self, params, order_id):
rshri932105f2024-07-05 15:11:55 +00001799 self.logger.info("Infra controller delete Enter")
rshri932105f2024-07-05 15:11:55 +00001800
rshri948f7de2024-12-02 03:42:35 +00001801 op_id = params["operation_id"]
1802 profile_id = params["profile_id"]
1803
1804 # To initialize the operation states
1805 self.initialize_operation(profile_id, op_id)
1806
1807 content = self.db.get_one("k8sinfra_controller", {"_id": profile_id})
1808 op_params = self.get_operation_params(content, op_id)
1809
garciadeblasdc805482025-02-04 16:08:51 +01001810 workflow_res, workflow_name = await self.odu.launch_workflow(
garciadeblas96b94f52024-07-08 16:18:21 +02001811 "delete_profile", op_id, op_params, content
1812 )
garciadeblas891f2002025-02-03 16:12:43 +01001813 self.logger.info("workflow_name is: {}".format(workflow_name))
rshri932105f2024-07-05 15:11:55 +00001814
garciadeblas713e1962025-01-17 12:49:19 +01001815 workflow_status = await self.check_workflow_and_update_db(
1816 op_id, workflow_name, content
1817 )
rshri932105f2024-07-05 15:11:55 +00001818
1819 if workflow_status:
garciadeblas713e1962025-01-17 12:49:19 +01001820 resource_status, content = await self.check_resource_and_update_db(
garciadeblas96b94f52024-07-08 16:18:21 +02001821 "delete_profile", op_id, op_params, content
rshri932105f2024-07-05 15:11:55 +00001822 )
rshri932105f2024-07-05 15:11:55 +00001823
yshah408de812025-02-28 09:01:51 +00001824 force = params.get("force", False)
1825 if force:
1826 force_delete_status = self.check_force_delete_and_delete_from_db(
1827 profile_id, workflow_status, resource_status, force
1828 )
1829 if force_delete_status:
1830 return
1831
yshah564ec9c2024-11-29 07:33:32 +00001832 if resource_status:
1833 content["state"] = "DELETED"
yshah4998f502025-02-11 12:37:04 +00001834 profile_type = self.profile_type_mapping[content["profile_type"]]
1835 self.delete_profile_ksu(profile_id, profile_type)
yshah564ec9c2024-11-29 07:33:32 +00001836 self.db.set_one(self.db_collection, {"_id": content["_id"]}, content)
1837 self.db.del_one(self.db_collection, {"_id": content["_id"]})
1838 self.logger.info(
1839 f"Infra Controller Delete Exit with resource status: {resource_status}"
garciadeblas96b94f52024-07-08 16:18:21 +02001840 )
rshri932105f2024-07-05 15:11:55 +00001841 return
1842
1843
garciadeblas72412282024-11-07 12:41:54 +01001844class K8sInfraConfigLcm(GitOpsLcm):
rshri948f7de2024-12-02 03:42:35 +00001845 db_collection = "k8sinfra_config"
1846
rshri932105f2024-07-05 15:11:55 +00001847 def __init__(self, msg, lcm_tasks, config):
1848 """
1849 Init, Connect to database, filesystem storage, and messaging
1850 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
1851 :return: None
1852 """
garciadeblas72412282024-11-07 12:41:54 +01001853 super().__init__(msg, lcm_tasks, config)
rshri932105f2024-07-05 15:11:55 +00001854
rshri948f7de2024-12-02 03:42:35 +00001855 async def create(self, params, order_id):
rshri932105f2024-07-05 15:11:55 +00001856 self.logger.info("Infra config Create Enter")
1857
rshri948f7de2024-12-02 03:42:35 +00001858 op_id = params["operation_id"]
1859 profile_id = params["profile_id"]
1860
1861 # To initialize the operation states
1862 self.initialize_operation(profile_id, op_id)
1863
1864 content = self.db.get_one("k8sinfra_config", {"_id": profile_id})
1865 content["profile_type"] = "infra-configs"
1866 op_params = self.get_operation_params(content, op_id)
1867 self.db.set_one("k8sinfra_config", {"_id": content["_id"]}, content)
1868
garciadeblasdc805482025-02-04 16:08:51 +01001869 workflow_res, workflow_name = await self.odu.launch_workflow(
garciadeblas96b94f52024-07-08 16:18:21 +02001870 "create_profile", op_id, op_params, content
1871 )
garciadeblas891f2002025-02-03 16:12:43 +01001872 self.logger.info("workflow_name is: {}".format(workflow_name))
rshri932105f2024-07-05 15:11:55 +00001873
garciadeblas713e1962025-01-17 12:49:19 +01001874 workflow_status = await self.check_workflow_and_update_db(
1875 op_id, workflow_name, content
1876 )
rshri932105f2024-07-05 15:11:55 +00001877
1878 if workflow_status:
garciadeblas713e1962025-01-17 12:49:19 +01001879 resource_status, content = await self.check_resource_and_update_db(
garciadeblas96b94f52024-07-08 16:18:21 +02001880 "create_profile", op_id, op_params, content
rshri932105f2024-07-05 15:11:55 +00001881 )
yshah564ec9c2024-11-29 07:33:32 +00001882 self.db.set_one(self.db_collection, {"_id": content["_id"]}, content)
1883 self.logger.info(
1884 f"Infra Config Create Exit with resource status: {resource_status}"
rshri932105f2024-07-05 15:11:55 +00001885 )
rshri932105f2024-07-05 15:11:55 +00001886 return
1887
rshri948f7de2024-12-02 03:42:35 +00001888 async def delete(self, params, order_id):
rshri932105f2024-07-05 15:11:55 +00001889 self.logger.info("Infra config delete Enter")
1890
rshri948f7de2024-12-02 03:42:35 +00001891 op_id = params["operation_id"]
1892 profile_id = params["profile_id"]
1893
1894 # To initialize the operation states
1895 self.initialize_operation(profile_id, op_id)
1896
1897 content = self.db.get_one("k8sinfra_config", {"_id": profile_id})
1898 op_params = self.get_operation_params(content, op_id)
1899
garciadeblasdc805482025-02-04 16:08:51 +01001900 workflow_res, workflow_name = await self.odu.launch_workflow(
garciadeblas96b94f52024-07-08 16:18:21 +02001901 "delete_profile", op_id, op_params, content
1902 )
garciadeblas891f2002025-02-03 16:12:43 +01001903 self.logger.info("workflow_name is: {}".format(workflow_name))
rshri932105f2024-07-05 15:11:55 +00001904
garciadeblas713e1962025-01-17 12:49:19 +01001905 workflow_status = await self.check_workflow_and_update_db(
1906 op_id, workflow_name, content
1907 )
yshah564ec9c2024-11-29 07:33:32 +00001908
rshri932105f2024-07-05 15:11:55 +00001909 if workflow_status:
garciadeblas713e1962025-01-17 12:49:19 +01001910 resource_status, content = await self.check_resource_and_update_db(
yshah564ec9c2024-11-29 07:33:32 +00001911 "delete_profile", op_id, op_params, content
rshri932105f2024-07-05 15:11:55 +00001912 )
yshah564ec9c2024-11-29 07:33:32 +00001913
yshah408de812025-02-28 09:01:51 +00001914 force = params.get("force", False)
1915 if force:
1916 force_delete_status = self.check_force_delete_and_delete_from_db(
1917 profile_id, workflow_status, resource_status, force
1918 )
1919 if force_delete_status:
1920 return
1921
rshri932105f2024-07-05 15:11:55 +00001922 if resource_status:
yshah564ec9c2024-11-29 07:33:32 +00001923 content["state"] = "DELETED"
yshah4998f502025-02-11 12:37:04 +00001924 profile_type = self.profile_type_mapping[content["profile_type"]]
1925 self.delete_profile_ksu(profile_id, profile_type)
yshah564ec9c2024-11-29 07:33:32 +00001926 self.db.set_one(self.db_collection, {"_id": content["_id"]}, content)
1927 self.db.del_one(self.db_collection, {"_id": content["_id"]})
1928 self.logger.info(
1929 f"Infra Config Delete Exit with resource status: {resource_status}"
garciadeblas96b94f52024-07-08 16:18:21 +02001930 )
rshri932105f2024-07-05 15:11:55 +00001931
rshri932105f2024-07-05 15:11:55 +00001932 return
yshah771dea82024-07-05 15:11:49 +00001933
1934
garciadeblas72412282024-11-07 12:41:54 +01001935class OkaLcm(GitOpsLcm):
yshah771dea82024-07-05 15:11:49 +00001936 db_collection = "okas"
1937
1938 def __init__(self, msg, lcm_tasks, config):
1939 """
1940 Init, Connect to database, filesystem storage, and messaging
1941 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
1942 :return: None
1943 """
garciadeblas72412282024-11-07 12:41:54 +01001944 super().__init__(msg, lcm_tasks, config)
yshah771dea82024-07-05 15:11:49 +00001945
yshah564ec9c2024-11-29 07:33:32 +00001946 async def create(self, params, order_id):
garciadeblas96b94f52024-07-08 16:18:21 +02001947 self.logger.info("OKA Create Enter")
yshah564ec9c2024-11-29 07:33:32 +00001948 op_id = params["operation_id"]
1949 oka_id = params["oka_id"]
1950 self.initialize_operation(oka_id, op_id)
1951 db_content = self.db.get_one(self.db_collection, {"_id": oka_id})
1952 op_params = self.get_operation_params(db_content, op_id)
yshah771dea82024-07-05 15:11:49 +00001953
garciadeblasdc805482025-02-04 16:08:51 +01001954 workflow_res, workflow_name = await self.odu.launch_workflow(
garciadeblas96b94f52024-07-08 16:18:21 +02001955 "create_oka", op_id, op_params, db_content
1956 )
yshah564ec9c2024-11-29 07:33:32 +00001957
garciadeblas713e1962025-01-17 12:49:19 +01001958 workflow_status = await self.check_workflow_and_update_db(
1959 op_id, workflow_name, db_content
1960 )
yshah771dea82024-07-05 15:11:49 +00001961
1962 if workflow_status:
garciadeblas713e1962025-01-17 12:49:19 +01001963 resource_status, db_content = await self.check_resource_and_update_db(
garciadeblas96b94f52024-07-08 16:18:21 +02001964 "create_oka", op_id, op_params, db_content
yshah771dea82024-07-05 15:11:49 +00001965 )
garciadeblas96b94f52024-07-08 16:18:21 +02001966 self.db.set_one(self.db_collection, {"_id": db_content["_id"]}, db_content)
garciadeblasc1c67892025-02-21 10:15:49 +01001967
1968 # Clean items used in the workflow, no matter if the workflow succeeded
1969 clean_status, clean_msg = await self.odu.clean_items_workflow(
1970 "create_oka", op_id, op_params, db_content
1971 )
1972 self.logger.info(
1973 f"clean_status is :{clean_status} and clean_msg is :{clean_msg}"
1974 )
yshah564ec9c2024-11-29 07:33:32 +00001975 self.logger.info(f"OKA Create Exit with resource status: {resource_status}")
yshah771dea82024-07-05 15:11:49 +00001976 return
1977
yshah564ec9c2024-11-29 07:33:32 +00001978 async def edit(self, params, order_id):
garciadeblas96b94f52024-07-08 16:18:21 +02001979 self.logger.info("OKA Edit Enter")
yshah564ec9c2024-11-29 07:33:32 +00001980 op_id = params["operation_id"]
1981 oka_id = params["oka_id"]
1982 self.initialize_operation(oka_id, op_id)
1983 db_content = self.db.get_one(self.db_collection, {"_id": oka_id})
1984 op_params = self.get_operation_params(db_content, op_id)
yshah771dea82024-07-05 15:11:49 +00001985
garciadeblasdc805482025-02-04 16:08:51 +01001986 workflow_res, workflow_name = await self.odu.launch_workflow(
yshah564ec9c2024-11-29 07:33:32 +00001987 "update_oka", op_id, op_params, db_content
garciadeblas96b94f52024-07-08 16:18:21 +02001988 )
garciadeblas713e1962025-01-17 12:49:19 +01001989 workflow_status = await self.check_workflow_and_update_db(
1990 op_id, workflow_name, db_content
1991 )
yshah771dea82024-07-05 15:11:49 +00001992
1993 if workflow_status:
garciadeblas713e1962025-01-17 12:49:19 +01001994 resource_status, db_content = await self.check_resource_and_update_db(
garciadeblas96b94f52024-07-08 16:18:21 +02001995 "update_oka", op_id, op_params, db_content
yshah771dea82024-07-05 15:11:49 +00001996 )
garciadeblas96b94f52024-07-08 16:18:21 +02001997 self.db.set_one(self.db_collection, {"_id": db_content["_id"]}, db_content)
garciadeblasc1c67892025-02-21 10:15:49 +01001998 # Clean items used in the workflow, no matter if the workflow succeeded
1999 clean_status, clean_msg = await self.odu.clean_items_workflow(
2000 "update_oka", op_id, op_params, db_content
2001 )
2002 self.logger.info(
2003 f"clean_status is :{clean_status} and clean_msg is :{clean_msg}"
2004 )
yshah564ec9c2024-11-29 07:33:32 +00002005 self.logger.info(f"OKA Update Exit with resource status: {resource_status}")
yshah771dea82024-07-05 15:11:49 +00002006 return
2007
yshah564ec9c2024-11-29 07:33:32 +00002008 async def delete(self, params, order_id):
garciadeblas96b94f52024-07-08 16:18:21 +02002009 self.logger.info("OKA delete Enter")
yshah564ec9c2024-11-29 07:33:32 +00002010 op_id = params["operation_id"]
2011 oka_id = params["oka_id"]
2012 self.initialize_operation(oka_id, op_id)
2013 db_content = self.db.get_one(self.db_collection, {"_id": oka_id})
2014 op_params = self.get_operation_params(db_content, op_id)
yshah771dea82024-07-05 15:11:49 +00002015
garciadeblasdc805482025-02-04 16:08:51 +01002016 workflow_res, workflow_name = await self.odu.launch_workflow(
yshah564ec9c2024-11-29 07:33:32 +00002017 "delete_oka", op_id, op_params, db_content
garciadeblas96b94f52024-07-08 16:18:21 +02002018 )
garciadeblas713e1962025-01-17 12:49:19 +01002019 workflow_status = await self.check_workflow_and_update_db(
2020 op_id, workflow_name, db_content
2021 )
yshah771dea82024-07-05 15:11:49 +00002022
2023 if workflow_status:
garciadeblas713e1962025-01-17 12:49:19 +01002024 resource_status, db_content = await self.check_resource_and_update_db(
garciadeblas96b94f52024-07-08 16:18:21 +02002025 "delete_oka", op_id, op_params, db_content
yshah771dea82024-07-05 15:11:49 +00002026 )
yshah771dea82024-07-05 15:11:49 +00002027
yshah408de812025-02-28 09:01:51 +00002028 force = params.get("force", False)
2029 if force:
2030 force_delete_status = self.check_force_delete_and_delete_from_db(
2031 oka_id, workflow_status, resource_status, force
2032 )
2033 if force_delete_status:
2034 return
2035
yshah564ec9c2024-11-29 07:33:32 +00002036 if resource_status:
2037 db_content["state"] == "DELETED"
2038 self.db.set_one(self.db_collection, {"_id": db_content["_id"]}, db_content)
garciadeblas96b94f52024-07-08 16:18:21 +02002039 self.db.del_one(self.db_collection, {"_id": db_content["_id"]})
garciadeblasc1c67892025-02-21 10:15:49 +01002040 # Clean items used in the workflow, no matter if the workflow succeeded
2041 clean_status, clean_msg = await self.odu.clean_items_workflow(
2042 "delete_oka", op_id, op_params, db_content
2043 )
2044 self.logger.info(
2045 f"clean_status is :{clean_status} and clean_msg is :{clean_msg}"
2046 )
yshah564ec9c2024-11-29 07:33:32 +00002047 self.logger.info(f"OKA Delete Exit with resource status: {resource_status}")
yshah771dea82024-07-05 15:11:49 +00002048 return
2049
2050
garciadeblas72412282024-11-07 12:41:54 +01002051class KsuLcm(GitOpsLcm):
yshah771dea82024-07-05 15:11:49 +00002052 db_collection = "ksus"
2053
2054 def __init__(self, msg, lcm_tasks, config):
2055 """
2056 Init, Connect to database, filesystem storage, and messaging
2057 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
2058 :return: None
2059 """
garciadeblas72412282024-11-07 12:41:54 +01002060 super().__init__(msg, lcm_tasks, config)
garciadeblasbc96f382025-01-22 16:02:18 +01002061 self._workflows = {
2062 "create_ksus": {
2063 "check_resource_function": self.check_create_ksus,
2064 },
2065 "delete_ksus": {
2066 "check_resource_function": self.check_delete_ksus,
2067 },
2068 }
2069
2070 def get_dbclusters_from_profile(self, profile_id, profile_type):
2071 cluster_list = []
2072 db_clusters = self.db.get_list("clusters")
2073 self.logger.info(f"Getting list of clusters for {profile_type} {profile_id}")
2074 for db_cluster in db_clusters:
2075 if profile_id in db_cluster.get(profile_type, []):
2076 self.logger.info(
2077 f"Profile {profile_id} found in cluster {db_cluster['name']}"
2078 )
2079 cluster_list.append(db_cluster)
2080 return cluster_list
yshah771dea82024-07-05 15:11:49 +00002081
yshah564ec9c2024-11-29 07:33:32 +00002082 async def create(self, params, order_id):
garciadeblas96b94f52024-07-08 16:18:21 +02002083 self.logger.info("ksu Create Enter")
yshah564ec9c2024-11-29 07:33:32 +00002084 db_content = []
2085 op_params = []
2086 op_id = params["operation_id"]
2087 for ksu_id in params["ksus_list"]:
2088 self.logger.info("Ksu ID: {}".format(ksu_id))
2089 self.initialize_operation(ksu_id, op_id)
2090 db_ksu = self.db.get_one(self.db_collection, {"_id": ksu_id})
2091 self.logger.info("Db KSU: {}".format(db_ksu))
2092 db_content.append(db_ksu)
2093 ksu_params = {}
2094 ksu_params = self.get_operation_params(db_ksu, op_id)
2095 self.logger.info("Operation Params: {}".format(ksu_params))
2096 # Update ksu_params["profile"] with profile name and age-pubkey
2097 profile_type = ksu_params["profile"]["profile_type"]
2098 profile_id = ksu_params["profile"]["_id"]
2099 profile_collection = self.profile_collection_mapping[profile_type]
2100 db_profile = self.db.get_one(profile_collection, {"_id": profile_id})
garciadeblase4479af2025-03-11 15:44:25 +01002101 # db_profile is decrypted inline
2102 # No need to use decrypted_copy because db_profile won't be updated.
2103 self.decrypt_age_keys(db_profile)
yshah564ec9c2024-11-29 07:33:32 +00002104 ksu_params["profile"]["name"] = db_profile["name"]
2105 ksu_params["profile"]["age_pubkey"] = db_profile.get("age_pubkey", "")
2106 # Update ksu_params["oka"] with sw_catalog_path (when missing)
garciadeblas8c9c5442025-01-17 01:06:05 +01002107 # TODO: remove this in favor of doing it in ODU workflow
yshah564ec9c2024-11-29 07:33:32 +00002108 for oka in ksu_params["oka"]:
2109 if "sw_catalog_path" not in oka:
2110 oka_id = oka["_id"]
2111 db_oka = self.db.get_one("okas", {"_id": oka_id})
yshah2f39b8a2024-12-19 11:06:24 +00002112 oka_type = MAP_PROFILE[
2113 db_oka.get("profile_type", "infra_controller_profiles")
2114 ]
garciadeblas8c9c5442025-01-17 01:06:05 +01002115 oka[
2116 "sw_catalog_path"
garciadeblas1ad4e882025-01-24 14:24:41 +01002117 ] = f"{oka_type}/{db_oka['git_name'].lower()}/templates"
yshah564ec9c2024-11-29 07:33:32 +00002118 op_params.append(ksu_params)
yshah771dea82024-07-05 15:11:49 +00002119
garciadeblasbc96f382025-01-22 16:02:18 +01002120 # A single workflow is launched for all KSUs
garciadeblasdc805482025-02-04 16:08:51 +01002121 workflow_res, workflow_name = await self.odu.launch_workflow(
yshah564ec9c2024-11-29 07:33:32 +00002122 "create_ksus", op_id, op_params, db_content
garciadeblas96b94f52024-07-08 16:18:21 +02002123 )
garciadeblasbc96f382025-01-22 16:02:18 +01002124 # Update workflow status in all KSUs
2125 wf_status_list = []
yshah564ec9c2024-11-29 07:33:32 +00002126 for db_ksu, ksu_params in zip(db_content, op_params):
garciadeblas713e1962025-01-17 12:49:19 +01002127 workflow_status = await self.check_workflow_and_update_db(
2128 op_id, workflow_name, db_ksu
2129 )
garciadeblasbc96f382025-01-22 16:02:18 +01002130 wf_status_list.append(workflow_status)
2131 # Update resource status in all KSUs
2132 # TODO: Is an operation correct if n KSUs are right and 1 is not OK?
2133 res_status_list = []
2134 for db_ksu, ksu_params, wf_status in zip(db_content, op_params, wf_status_list):
2135 if wf_status:
garciadeblas713e1962025-01-17 12:49:19 +01002136 resource_status, db_ksu = await self.check_resource_and_update_db(
yshah564ec9c2024-11-29 07:33:32 +00002137 "create_ksus", op_id, ksu_params, db_ksu
2138 )
garciadeblasbc96f382025-01-22 16:02:18 +01002139 else:
2140 resource_status = False
2141 res_status_list.append(resource_status)
garciadeblas96b94f52024-07-08 16:18:21 +02002142 self.db.set_one(self.db_collection, {"_id": db_ksu["_id"]}, db_ksu)
2143
garciadeblasd8429852024-10-17 15:30:30 +02002144 # Clean items used in the workflow, no matter if the workflow succeeded
2145 clean_status, clean_msg = await self.odu.clean_items_workflow(
yshah564ec9c2024-11-29 07:33:32 +00002146 "create_ksus", op_id, op_params, db_content
garciadeblasd8429852024-10-17 15:30:30 +02002147 )
2148 self.logger.info(
2149 f"clean_status is :{clean_status} and clean_msg is :{clean_msg}"
2150 )
garciadeblasbc96f382025-01-22 16:02:18 +01002151 self.logger.info(f"KSU Create EXIT with Resource Status {res_status_list}")
yshah771dea82024-07-05 15:11:49 +00002152 return
2153
yshah564ec9c2024-11-29 07:33:32 +00002154 async def edit(self, params, order_id):
garciadeblas96b94f52024-07-08 16:18:21 +02002155 self.logger.info("ksu edit Enter")
yshah564ec9c2024-11-29 07:33:32 +00002156 db_content = []
2157 op_params = []
2158 op_id = params["operation_id"]
2159 for ksu_id in params["ksus_list"]:
2160 self.initialize_operation(ksu_id, op_id)
2161 db_ksu = self.db.get_one("ksus", {"_id": ksu_id})
2162 db_content.append(db_ksu)
2163 ksu_params = {}
2164 ksu_params = self.get_operation_params(db_ksu, op_id)
2165 # Update ksu_params["profile"] with profile name and age-pubkey
2166 profile_type = ksu_params["profile"]["profile_type"]
2167 profile_id = ksu_params["profile"]["_id"]
2168 profile_collection = self.profile_collection_mapping[profile_type]
2169 db_profile = self.db.get_one(profile_collection, {"_id": profile_id})
garciadeblase4479af2025-03-11 15:44:25 +01002170 # db_profile is decrypted inline
2171 # No need to use decrypted_copy because db_profile won't be updated.
2172 self.decrypt_age_keys(db_profile)
yshah564ec9c2024-11-29 07:33:32 +00002173 ksu_params["profile"]["name"] = db_profile["name"]
2174 ksu_params["profile"]["age_pubkey"] = db_profile.get("age_pubkey", "")
2175 # Update ksu_params["oka"] with sw_catalog_path (when missing)
garciadeblas8c9c5442025-01-17 01:06:05 +01002176 # TODO: remove this in favor of doing it in ODU workflow
yshah564ec9c2024-11-29 07:33:32 +00002177 for oka in ksu_params["oka"]:
2178 if "sw_catalog_path" not in oka:
2179 oka_id = oka["_id"]
2180 db_oka = self.db.get_one("okas", {"_id": oka_id})
yshah2f39b8a2024-12-19 11:06:24 +00002181 oka_type = MAP_PROFILE[
2182 db_oka.get("profile_type", "infra_controller_profiles")
2183 ]
garciadeblas8c9c5442025-01-17 01:06:05 +01002184 oka[
2185 "sw_catalog_path"
2186 ] = f"{oka_type}/{db_oka['git_name']}/templates"
yshah564ec9c2024-11-29 07:33:32 +00002187 op_params.append(ksu_params)
yshah771dea82024-07-05 15:11:49 +00002188
garciadeblasdc805482025-02-04 16:08:51 +01002189 workflow_res, workflow_name = await self.odu.launch_workflow(
yshah564ec9c2024-11-29 07:33:32 +00002190 "update_ksus", op_id, op_params, db_content
garciadeblas96b94f52024-07-08 16:18:21 +02002191 )
yshah771dea82024-07-05 15:11:49 +00002192
yshah564ec9c2024-11-29 07:33:32 +00002193 for db_ksu, ksu_params in zip(db_content, op_params):
garciadeblas713e1962025-01-17 12:49:19 +01002194 workflow_status = await self.check_workflow_and_update_db(
2195 op_id, workflow_name, db_ksu
2196 )
yshah564ec9c2024-11-29 07:33:32 +00002197
garciadeblas96b94f52024-07-08 16:18:21 +02002198 if workflow_status:
garciadeblas713e1962025-01-17 12:49:19 +01002199 resource_status, db_ksu = await self.check_resource_and_update_db(
yshah564ec9c2024-11-29 07:33:32 +00002200 "update_ksus", op_id, ksu_params, db_ksu
garciadeblas96b94f52024-07-08 16:18:21 +02002201 )
garciadeblas96b94f52024-07-08 16:18:21 +02002202 db_ksu["name"] = ksu_params["name"]
2203 db_ksu["description"] = ksu_params["description"]
2204 db_ksu["profile"]["profile_type"] = ksu_params["profile"][
2205 "profile_type"
2206 ]
2207 db_ksu["profile"]["_id"] = ksu_params["profile"]["_id"]
2208 db_ksu["oka"] = ksu_params["oka"]
2209 self.db.set_one(self.db_collection, {"_id": db_ksu["_id"]}, db_ksu)
2210
yshah564ec9c2024-11-29 07:33:32 +00002211 # Clean items used in the workflow, no matter if the workflow succeeded
2212 clean_status, clean_msg = await self.odu.clean_items_workflow(
2213 "create_ksus", op_id, op_params, db_content
garciadeblas96b94f52024-07-08 16:18:21 +02002214 )
2215 self.logger.info(
yshah564ec9c2024-11-29 07:33:32 +00002216 f"clean_status is :{clean_status} and clean_msg is :{clean_msg}"
garciadeblas96b94f52024-07-08 16:18:21 +02002217 )
yshah564ec9c2024-11-29 07:33:32 +00002218 self.logger.info(f"KSU Update EXIT with Resource Status {resource_status}")
yshah771dea82024-07-05 15:11:49 +00002219 return
2220
yshah564ec9c2024-11-29 07:33:32 +00002221 async def delete(self, params, order_id):
2222 self.logger.info("ksu delete Enter")
2223 db_content = []
2224 op_params = []
2225 op_id = params["operation_id"]
2226 for ksu_id in params["ksus_list"]:
2227 self.initialize_operation(ksu_id, op_id)
2228 db_ksu = self.db.get_one("ksus", {"_id": ksu_id})
2229 db_content.append(db_ksu)
2230 ksu_params = {}
2231 ksu_params["profile"] = {}
2232 ksu_params["profile"]["profile_type"] = db_ksu["profile"]["profile_type"]
2233 ksu_params["profile"]["_id"] = db_ksu["profile"]["_id"]
garciadeblase4479af2025-03-11 15:44:25 +01002234 # Update ksu_params["profile"] with profile name
yshah564ec9c2024-11-29 07:33:32 +00002235 profile_type = ksu_params["profile"]["profile_type"]
2236 profile_id = ksu_params["profile"]["_id"]
2237 profile_collection = self.profile_collection_mapping[profile_type]
2238 db_profile = self.db.get_one(profile_collection, {"_id": profile_id})
2239 ksu_params["profile"]["name"] = db_profile["name"]
yshah564ec9c2024-11-29 07:33:32 +00002240 op_params.append(ksu_params)
yshah771dea82024-07-05 15:11:49 +00002241
garciadeblasdc805482025-02-04 16:08:51 +01002242 workflow_res, workflow_name = await self.odu.launch_workflow(
yshah564ec9c2024-11-29 07:33:32 +00002243 "delete_ksus", op_id, op_params, db_content
2244 )
2245
2246 for db_ksu, ksu_params in zip(db_content, op_params):
garciadeblas713e1962025-01-17 12:49:19 +01002247 workflow_status = await self.check_workflow_and_update_db(
2248 op_id, workflow_name, db_ksu
2249 )
yshah564ec9c2024-11-29 07:33:32 +00002250
2251 if workflow_status:
garciadeblas713e1962025-01-17 12:49:19 +01002252 resource_status, db_ksu = await self.check_resource_and_update_db(
yshah564ec9c2024-11-29 07:33:32 +00002253 "delete_ksus", op_id, ksu_params, db_ksu
2254 )
2255
yshah408de812025-02-28 09:01:51 +00002256 force = params.get("force", False)
2257 if force:
2258 force_delete_status = self.check_force_delete_and_delete_from_db(
2259 db_ksu["_id"], workflow_status, resource_status, force
2260 )
2261 if force_delete_status:
2262 return
2263
yshah564ec9c2024-11-29 07:33:32 +00002264 if resource_status:
2265 db_ksu["state"] == "DELETED"
yshah6441de12025-05-19 12:29:01 +00002266 self.delete_ksu_dependency(db_ksu["_id"], db_ksu)
yshah564ec9c2024-11-29 07:33:32 +00002267 self.db.set_one(self.db_collection, {"_id": db_ksu["_id"]}, db_ksu)
2268 self.db.del_one(self.db_collection, {"_id": db_ksu["_id"]})
2269
2270 self.logger.info(f"KSU Delete Exit with resource status: {resource_status}")
2271 return
2272
2273 async def clone(self, params, order_id):
2274 self.logger.info("ksu clone Enter")
2275 op_id = params["operation_id"]
2276 ksus_id = params["ksus_list"][0]
2277 self.initialize_operation(ksus_id, op_id)
2278 db_content = self.db.get_one(self.db_collection, {"_id": ksus_id})
2279 op_params = self.get_operation_params(db_content, op_id)
garciadeblasdc805482025-02-04 16:08:51 +01002280 workflow_res, workflow_name = await self.odu.launch_workflow(
garciadeblas96b94f52024-07-08 16:18:21 +02002281 "clone_ksus", op_id, op_params, db_content
2282 )
yshah564ec9c2024-11-29 07:33:32 +00002283
garciadeblas713e1962025-01-17 12:49:19 +01002284 workflow_status = await self.check_workflow_and_update_db(
2285 op_id, workflow_name, db_content
2286 )
yshah771dea82024-07-05 15:11:49 +00002287
2288 if workflow_status:
garciadeblas713e1962025-01-17 12:49:19 +01002289 resource_status, db_content = await self.check_resource_and_update_db(
garciadeblas96b94f52024-07-08 16:18:21 +02002290 "clone_ksus", op_id, op_params, db_content
yshah771dea82024-07-05 15:11:49 +00002291 )
garciadeblas96b94f52024-07-08 16:18:21 +02002292 self.db.set_one(self.db_collection, {"_id": db_content["_id"]}, db_content)
yshah564ec9c2024-11-29 07:33:32 +00002293
2294 self.logger.info(f"KSU Clone Exit with resource status: {resource_status}")
yshah771dea82024-07-05 15:11:49 +00002295 return
2296
yshah564ec9c2024-11-29 07:33:32 +00002297 async def move(self, params, order_id):
garciadeblas96b94f52024-07-08 16:18:21 +02002298 self.logger.info("ksu move Enter")
yshah564ec9c2024-11-29 07:33:32 +00002299 op_id = params["operation_id"]
2300 ksus_id = params["ksus_list"][0]
2301 self.initialize_operation(ksus_id, op_id)
2302 db_content = self.db.get_one(self.db_collection, {"_id": ksus_id})
2303 op_params = self.get_operation_params(db_content, op_id)
garciadeblasdc805482025-02-04 16:08:51 +01002304 workflow_res, workflow_name = await self.odu.launch_workflow(
garciadeblas96b94f52024-07-08 16:18:21 +02002305 "move_ksus", op_id, op_params, db_content
2306 )
yshah564ec9c2024-11-29 07:33:32 +00002307
garciadeblas713e1962025-01-17 12:49:19 +01002308 workflow_status = await self.check_workflow_and_update_db(
2309 op_id, workflow_name, db_content
2310 )
yshah771dea82024-07-05 15:11:49 +00002311
2312 if workflow_status:
garciadeblas713e1962025-01-17 12:49:19 +01002313 resource_status, db_content = await self.check_resource_and_update_db(
garciadeblas96b94f52024-07-08 16:18:21 +02002314 "move_ksus", op_id, op_params, db_content
yshah771dea82024-07-05 15:11:49 +00002315 )
garciadeblas96b94f52024-07-08 16:18:21 +02002316 self.db.set_one(self.db_collection, {"_id": db_content["_id"]}, db_content)
yshah564ec9c2024-11-29 07:33:32 +00002317
2318 self.logger.info(f"KSU Move Exit with resource status: {resource_status}")
yshah771dea82024-07-05 15:11:49 +00002319 return
garciadeblasbc96f382025-01-22 16:02:18 +01002320
2321 async def check_create_ksus(self, op_id, op_params, content):
2322 self.logger.info(f"check_create_ksus Operation {op_id}. Params: {op_params}.")
2323 self.logger.debug(f"Content: {content}")
2324 db_ksu = content
2325 kustomization_name = db_ksu["git_name"].lower()
2326 oka_list = op_params["oka"]
2327 oka_item = oka_list[0]
2328 oka_params = oka_item.get("transformation", {})
garciadeblas4c9b4ab2025-02-14 00:44:58 +01002329 kustomization_ns = oka_params.get("kustomization_namespace", "flux-system")
garciadeblasbc96f382025-01-22 16:02:18 +01002330 profile_id = op_params.get("profile", {}).get("_id")
2331 profile_type = op_params.get("profile", {}).get("profile_type")
2332 self.logger.info(
2333 f"Checking status of KSU {db_ksu['name']} for profile {profile_id}."
2334 )
2335 dbcluster_list = self.get_dbclusters_from_profile(profile_id, profile_type)
2336 if not dbcluster_list:
2337 self.logger.info(f"No clusters found for profile {profile_id}.")
2338 for db_cluster in dbcluster_list:
2339 try:
2340 self.logger.info(
garciadeblase3462922025-02-03 08:44:19 +01002341 f"Checking status of KSU {db_ksu['name']} in cluster {db_cluster['name']}."
garciadeblasbc96f382025-01-22 16:02:18 +01002342 )
2343 cluster_kubectl = self.cluster_kubectl(db_cluster)
2344 checkings_list = [
2345 {
2346 "item": "kustomization",
2347 "name": kustomization_name,
garciadeblas4c9b4ab2025-02-14 00:44:58 +01002348 "namespace": kustomization_ns,
garciadeblas6c82c352025-01-27 16:53:45 +01002349 "condition": {
2350 "jsonpath_filter": "status.conditions[?(@.type=='Ready')].status",
2351 "value": "True",
2352 },
garciadeblasbc96f382025-01-22 16:02:18 +01002353 "timeout": self._checkloop_kustomization_timeout,
2354 "enable": True,
2355 "resourceState": "IN_PROGRESS.KUSTOMIZATION_READY",
2356 },
2357 ]
2358 self.logger.info(
2359 f"Checking status of KSU {db_ksu['name']} for profile {profile_id}."
2360 )
2361 result, message = await self.common_check_list(
garciadeblas619a0a32025-02-06 13:34:37 +01002362 op_id, checkings_list, "ksus", db_ksu, kubectl_obj=cluster_kubectl
garciadeblasbc96f382025-01-22 16:02:18 +01002363 )
2364 if not result:
2365 return False, message
2366 except Exception as e:
2367 self.logger.error(
2368 f"Error checking KSU in cluster {db_cluster['name']}."
2369 )
2370 self.logger.error(e)
2371 return False, f"Error checking KSU in cluster {db_cluster['name']}."
2372 return True, "OK"
2373
2374 async def check_delete_ksus(self, op_id, op_params, content):
2375 self.logger.info(f"check_delete_ksus Operation {op_id}. Params: {op_params}.")
2376 self.logger.debug(f"Content: {content}")
2377 db_ksu = content
2378 kustomization_name = db_ksu["git_name"].lower()
2379 oka_list = db_ksu["oka"]
2380 oka_item = oka_list[0]
2381 oka_params = oka_item.get("transformation", {})
garciadeblas4c9b4ab2025-02-14 00:44:58 +01002382 kustomization_ns = oka_params.get("kustomization_namespace", "flux-system")
garciadeblasbc96f382025-01-22 16:02:18 +01002383 profile_id = op_params.get("profile", {}).get("_id")
2384 profile_type = op_params.get("profile", {}).get("profile_type")
2385 self.logger.info(
2386 f"Checking status of KSU {db_ksu['name']} for profile {profile_id}."
2387 )
2388 dbcluster_list = self.get_dbclusters_from_profile(profile_id, profile_type)
2389 if not dbcluster_list:
2390 self.logger.info(f"No clusters found for profile {profile_id}.")
2391 for db_cluster in dbcluster_list:
2392 try:
2393 self.logger.info(
2394 f"Checking status of KSU in cluster {db_cluster['name']}."
2395 )
2396 cluster_kubectl = self.cluster_kubectl(db_cluster)
2397 checkings_list = [
2398 {
2399 "item": "kustomization",
2400 "name": kustomization_name,
garciadeblas4c9b4ab2025-02-14 00:44:58 +01002401 "namespace": kustomization_ns,
garciadeblasbc96f382025-01-22 16:02:18 +01002402 "deleted": True,
2403 "timeout": self._checkloop_kustomization_timeout,
2404 "enable": True,
2405 "resourceState": "IN_PROGRESS.KUSTOMIZATION_DELETED",
2406 },
2407 ]
2408 self.logger.info(
2409 f"Checking status of KSU {db_ksu['name']} for profile {profile_id}."
2410 )
2411 result, message = await self.common_check_list(
garciadeblas619a0a32025-02-06 13:34:37 +01002412 op_id, checkings_list, "ksus", db_ksu, kubectl_obj=cluster_kubectl
garciadeblasbc96f382025-01-22 16:02:18 +01002413 )
2414 if not result:
2415 return False, message
2416 except Exception as e:
2417 self.logger.error(
2418 f"Error checking KSU in cluster {db_cluster['name']}."
2419 )
2420 self.logger.error(e)
2421 return False, f"Error checking KSU in cluster {db_cluster['name']}."
2422 return True, "OK"