blob: 730acfeb7e40bf1fe513360e1df0874fe455ce53 [file] [log] [blame]
garciadeblas96b94f52024-07-08 16:18:21 +02001#######################################################################################
2# Licensed under the Apache License, Version 2.0 (the "License");
3# you may not use this file except in compliance with the License.
4# You may obtain a copy of the License at
rshri932105f2024-07-05 15:11:55 +00005#
garciadeblas96b94f52024-07-08 16:18:21 +02006# http://www.apache.org/licenses/LICENSE-2.0
rshri932105f2024-07-05 15:11:55 +00007#
8# Unless required by applicable law or agreed to in writing, software
garciadeblas96b94f52024-07-08 16:18:21 +02009# distributed under the License is distributed on an "AS IS" BASIS,
10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
11# implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14#######################################################################################
rshri932105f2024-07-05 15:11:55 +000015
16
17import logging
18from osm_lcm.lcm_utils import LcmBase
almagiacdd20ae2024-12-13 09:45:45 +010019from osm_lcm.n2vc import kubectl
garciadeblasc8d217d2025-05-26 15:14:47 +020020from osm_lcm.odu_libs import (
21 vim_mgmt as odu_vim_mgmt,
22 cluster_mgmt as odu_cluster_mgmt,
23 ksu as odu_ksu,
24 oka as odu_oka,
25 profiles as odu_profiles,
26 workflows,
27 render as odu_render,
28 common as odu_common,
29)
garciadeblas96b94f52024-07-08 16:18:21 +020030
rshri932105f2024-07-05 15:11:55 +000031
32class OduWorkflow(LcmBase):
garciadeblasc8d217d2025-05-26 15:14:47 +020033 """
34 Class to manage the workflows for the OSM Deployment Unit (ODU).
35 This class is responsible for executing various workflows related to
36 cluster management, profile management, and other operations.
37 """
38
rshri932105f2024-07-05 15:11:55 +000039 def __init__(self, msg, lcm_tasks, config):
40 """
41 Init, Connect to database, filesystem storage, and messaging
42 :param config: two level dictionary with configuration. Top level should contain 'database', 'storage',
43 :return: None
44 """
45
garciadeblas40539872024-09-11 14:28:38 +020046 self.logger = logging.getLogger("lcm.gitops")
rshri932105f2024-07-05 15:11:55 +000047 self.lcm_tasks = lcm_tasks
48 self.logger.info("Msg: {} lcm_tasks: {} ".format(msg, lcm_tasks))
49
garciadeblas96b94f52024-07-08 16:18:21 +020050 # self._kubeconfig = kubeconfig # TODO: get it from config
garciadeblas3364c472024-09-11 14:30:26 +020051 self.gitops_config = config["gitops"]
garciadeblase98a9182025-07-08 13:10:21 +020052 self.logger.debug(f"Gitops Config: {self.gitops_config}")
garciadeblasb8976952024-10-18 11:36:15 +020053 self._odu_checkloop_retry_time = 15
garciadeblas121a3432025-07-08 10:44:07 +020054 self._kubeconfig = self.gitops_config.get("mgmtcluster_kubeconfig")
garciadeblas96b94f52024-07-08 16:18:21 +020055 self._kubectl = kubectl.Kubectl(config_file=self._kubeconfig)
garciadeblas121a3432025-07-08 10:44:07 +020056 self._repo_base_url = self.gitops_config.get("git_base_url")
57 self._repo_user = self.gitops_config.get("user")
garciadeblas56c3aa82025-05-26 15:29:46 +020058 self._repo_fleet_url = self.gitops_config.get(
59 "fleet_repo_url", f"{self._repo_base_url}/{self._repo_user}/fleet-osm.git"
60 )
61 self._repo_sw_catalogs_url = self.gitops_config.get(
62 "sw_catalogs_repo_url",
63 f"{self._repo_base_url}/{self._repo_user}/sw-catalogs-osm.git",
64 )
garciadeblas3364c472024-09-11 14:30:26 +020065 self._pubkey = self.gitops_config["pubkey"]
garciadeblas326144e2025-01-27 11:16:27 +010066 self._workflow_debug = str(self.gitops_config["workflow_debug"]).lower()
67 self._workflow_dry_run = str(self.gitops_config["workflow_dry_run"]).lower()
garciadeblas96b94f52024-07-08 16:18:21 +020068 self._workflows = {
69 "create_cluster": {
70 "workflow_function": self.create_cluster,
garciadeblas28bff0f2024-09-16 12:53:07 +020071 "clean_function": self.clean_items_cluster_create,
garciadeblas96b94f52024-07-08 16:18:21 +020072 },
73 "update_cluster": {
74 "workflow_function": self.update_cluster,
garciadeblas28bff0f2024-09-16 12:53:07 +020075 "clean_function": self.clean_items_cluster_update,
garciadeblas96b94f52024-07-08 16:18:21 +020076 },
77 "delete_cluster": {
78 "workflow_function": self.delete_cluster,
garciadeblas96b94f52024-07-08 16:18:21 +020079 },
80 "register_cluster": {
81 "workflow_function": self.register_cluster,
garciadeblasdde3a312024-09-17 13:25:06 +020082 "clean_function": self.clean_items_cluster_register,
garciadeblas96b94f52024-07-08 16:18:21 +020083 },
84 "deregister_cluster": {
85 "workflow_function": self.deregister_cluster,
garciadeblas91bb2c42024-11-12 11:17:12 +010086 "clean_function": self.clean_items_cluster_deregister,
garciadeblas96b94f52024-07-08 16:18:21 +020087 },
88 "create_profile": {
89 "workflow_function": self.create_profile,
garciadeblas96b94f52024-07-08 16:18:21 +020090 },
91 "delete_profile": {
92 "workflow_function": self.delete_profile,
garciadeblas96b94f52024-07-08 16:18:21 +020093 },
94 "attach_profile_to_cluster": {
95 "workflow_function": self.attach_profile_to_cluster,
garciadeblas96b94f52024-07-08 16:18:21 +020096 },
97 "detach_profile_from_cluster": {
98 "workflow_function": self.detach_profile_from_cluster,
garciadeblas96b94f52024-07-08 16:18:21 +020099 },
100 "create_oka": {
101 "workflow_function": self.create_oka,
garciadeblasb23d2dc2025-02-21 10:15:49 +0100102 "clean_function": self.clean_items_oka_create,
garciadeblas96b94f52024-07-08 16:18:21 +0200103 },
104 "update_oka": {
105 "workflow_function": self.update_oka,
garciadeblasb23d2dc2025-02-21 10:15:49 +0100106 "clean_function": self.clean_items_oka_update,
garciadeblas96b94f52024-07-08 16:18:21 +0200107 },
108 "delete_oka": {
109 "workflow_function": self.delete_oka,
garciadeblasb23d2dc2025-02-21 10:15:49 +0100110 "clean_function": self.clean_items_oka_delete,
garciadeblas96b94f52024-07-08 16:18:21 +0200111 },
112 "create_ksus": {
113 "workflow_function": self.create_ksus,
garciadeblasd8429852024-10-17 15:30:30 +0200114 "clean_function": self.clean_items_ksu_create,
garciadeblas96b94f52024-07-08 16:18:21 +0200115 },
116 "update_ksus": {
117 "workflow_function": self.update_ksus,
garciadeblasd8429852024-10-17 15:30:30 +0200118 "clean_function": self.clean_items_ksu_update,
garciadeblas96b94f52024-07-08 16:18:21 +0200119 },
120 "delete_ksus": {
121 "workflow_function": self.delete_ksus,
garciadeblas96b94f52024-07-08 16:18:21 +0200122 },
123 "clone_ksu": {
124 "workflow_function": self.clone_ksu,
garciadeblas96b94f52024-07-08 16:18:21 +0200125 },
126 "move_ksu": {
127 "workflow_function": self.move_ksu,
garciadeblas96b94f52024-07-08 16:18:21 +0200128 },
129 "create_cloud_credentials": {
130 "workflow_function": self.create_cloud_credentials,
garciadeblas28bff0f2024-09-16 12:53:07 +0200131 "clean_function": self.clean_items_cloud_credentials_create,
garciadeblas96b94f52024-07-08 16:18:21 +0200132 },
133 "update_cloud_credentials": {
134 "workflow_function": self.update_cloud_credentials,
garciadeblas28bff0f2024-09-16 12:53:07 +0200135 "clean_function": self.clean_items_cloud_credentials_update,
garciadeblas96b94f52024-07-08 16:18:21 +0200136 },
137 "delete_cloud_credentials": {
138 "workflow_function": self.delete_cloud_credentials,
garciadeblas96b94f52024-07-08 16:18:21 +0200139 },
140 "dummy_operation": {
141 "workflow_function": self.dummy_operation,
garciadeblas96b94f52024-07-08 16:18:21 +0200142 },
143 }
144
rshri932105f2024-07-05 15:11:55 +0000145 super().__init__(msg, self.logger)
146
garciadeblas96b94f52024-07-08 16:18:21 +0200147 @property
148 def kubeconfig(self):
149 return self._kubeconfig
150
151 # Imported methods
garciadeblasc8d217d2025-05-26 15:14:47 +0200152 create_cloud_credentials = odu_vim_mgmt.create_cloud_credentials
153 update_cloud_credentials = odu_vim_mgmt.update_cloud_credentials
154 delete_cloud_credentials = odu_vim_mgmt.delete_cloud_credentials
155 clean_items_cloud_credentials_create = (
156 odu_vim_mgmt.clean_items_cloud_credentials_create
garciadeblas96b94f52024-07-08 16:18:21 +0200157 )
garciadeblasc8d217d2025-05-26 15:14:47 +0200158 clean_items_cloud_credentials_update = (
159 odu_vim_mgmt.clean_items_cloud_credentials_update
garciadeblas96b94f52024-07-08 16:18:21 +0200160 )
garciadeblasc8d217d2025-05-26 15:14:47 +0200161 create_cluster = odu_cluster_mgmt.create_cluster
162 update_cluster = odu_cluster_mgmt.update_cluster
163 delete_cluster = odu_cluster_mgmt.delete_cluster
164 register_cluster = odu_cluster_mgmt.register_cluster
165 deregister_cluster = odu_cluster_mgmt.deregister_cluster
166 clean_items_cluster_create = odu_cluster_mgmt.clean_items_cluster_create
167 clean_items_cluster_update = odu_cluster_mgmt.clean_items_cluster_update
168 clean_items_cluster_register = odu_cluster_mgmt.clean_items_cluster_register
169 clean_items_cluster_deregister = odu_cluster_mgmt.clean_items_cluster_deregister
170 get_cluster_credentials = odu_cluster_mgmt.get_cluster_credentials
171 create_ksus = odu_ksu.create_ksus
172 update_ksus = odu_ksu.update_ksus
173 delete_ksus = odu_ksu.delete_ksus
174 clone_ksu = odu_ksu.clone_ksu
175 move_ksu = odu_ksu.move_ksu
176 clean_items_ksu_create = odu_ksu.clean_items_ksu_create
177 clean_items_ksu_update = odu_ksu.clean_items_ksu_update
178 clean_items_ksu_delete = odu_ksu.clean_items_ksu_delete
179 create_oka = odu_oka.create_oka
180 update_oka = odu_oka.update_oka
181 delete_oka = odu_oka.delete_oka
182 clean_items_oka_create = odu_oka.clean_items_oka_create
183 clean_items_oka_update = odu_oka.clean_items_oka_update
184 clean_items_oka_delete = odu_oka.clean_items_oka_delete
185 create_profile = odu_profiles.create_profile
186 delete_profile = odu_profiles.delete_profile
187 attach_profile_to_cluster = odu_profiles.attach_profile_to_cluster
188 detach_profile_from_cluster = odu_profiles.detach_profile_from_cluster
189 check_workflow_status = workflows.check_workflow_status
190 readiness_loop = workflows.readiness_loop
191 render_jinja_template = odu_render.render_jinja_template
192 render_yaml_template = odu_render.render_yaml_template
193 create_secret = odu_common.create_secret
194 delete_secret = odu_common.delete_secret
rshrif8911b92025-06-11 18:19:07 +0000195 create_configmap = odu_common.create_configmap
196 delete_configmap = odu_common.delete_configmap
garciadeblas96b94f52024-07-08 16:18:21 +0200197
198 async def launch_workflow(self, key, op_id, op_params, content):
rshri932105f2024-07-05 15:11:55 +0000199 self.logger.info(
garciadeblas96b94f52024-07-08 16:18:21 +0200200 f"Workflow is getting into launch. Key: {key}. Operation: {op_id}. Params: {op_params}. Content: {content}"
rshri932105f2024-07-05 15:11:55 +0000201 )
garciadeblas96b94f52024-07-08 16:18:21 +0200202 workflow_function = self._workflows[key]["workflow_function"]
203 self.logger.info("workflow function : {}".format(workflow_function))
garciadeblas41859ce2025-02-04 16:08:51 +0100204 try:
205 result, workflow_name = await workflow_function(op_id, op_params, content)
206 return result, workflow_name
207 except Exception as e:
208 self.logger.error(f"Error launching workflow: {e}")
209 return False, str(e)
rshri932105f2024-07-05 15:11:55 +0000210
garciadeblas5359e992024-12-13 11:09:04 +0100211 async def dummy_clean_items(self, op_id, op_params, content):
garciadeblas98f9a3d2024-12-10 13:42:47 +0100212 self.logger.info(
garciadeblas5359e992024-12-13 11:09:04 +0100213 f"dummy_clean_items Enter. Operation {op_id}. Params: {op_params}"
garciadeblas98f9a3d2024-12-10 13:42:47 +0100214 )
garciadeblas5359e992024-12-13 11:09:04 +0100215 self.logger.debug(f"Content: {content}")
garciadeblas98f9a3d2024-12-10 13:42:47 +0100216 return True, "OK"
217
garciadeblas28bff0f2024-09-16 12:53:07 +0200218 async def clean_items_workflow(self, key, op_id, op_params, content):
219 self.logger.info(
220 f"Cleaning items created during workflow launch. Key: {key}. Operation: {op_id}. Params: {op_params}. Content: {content}"
221 )
garciadeblas98f9a3d2024-12-10 13:42:47 +0100222 clean_items_function = self._workflows[key].get(
223 "clean_function", self.dummy_clean_items
224 )
garciadeblas28bff0f2024-09-16 12:53:07 +0200225 self.logger.info("clean items function : {}".format(clean_items_function))
226 return await clean_items_function(op_id, op_params, content)
227
garciadeblas96b94f52024-07-08 16:18:21 +0200228 async def dummy_operation(self, op_id, op_params, content):
229 self.logger.info("Empty operation status Enter")
230 self.logger.info(f"Operation {op_id}. Params: {op_params}. Content: {content}")
231 return content["workflow_name"]
rshri932105f2024-07-05 15:11:55 +0000232
garciadeblas28bff0f2024-09-16 12:53:07 +0200233 async def clean_items(self, items):
garciadeblasb23d2dc2025-02-21 10:15:49 +0100234 # Delete pods
235 for pod in items.get("pods", []):
236 name = pod["name"]
237 namespace = pod["namespace"]
238 self.logger.info(f"Deleting pod {name} in namespace {namespace}")
239 self.logger.debug(f"Testing kubectl: {self._kubectl}")
240 self.logger.debug(
241 f"Testing kubectl configuration: {self._kubectl.configuration}"
242 )
243 self.logger.debug(
244 f"Testing kubectl configuration Host: {self._kubectl.configuration.host}"
245 )
246 await self._kubectl.delete_pod(name, namespace)
garciadeblas28bff0f2024-09-16 12:53:07 +0200247 # Delete secrets
248 for secret in items.get("secrets", []):
249 name = secret["name"]
250 namespace = secret["namespace"]
251 self.logger.info(f"Deleting secret {name} in namespace {namespace}")
garciadeblas6d8acf32025-02-06 13:34:37 +0100252 self.logger.debug(f"Testing kubectl: {self._kubectl}")
253 self.logger.debug(
254 f"Testing kubectl configuration: {self._kubectl.configuration}"
255 )
256 self.logger.debug(
257 f"Testing kubectl configuration Host: {self._kubectl.configuration.host}"
258 )
garciadeblas28bff0f2024-09-16 12:53:07 +0200259 self.delete_secret(name, namespace)
260 # Delete pvcs
261 for pvc in items.get("pvcs", []):
262 name = pvc["name"]
263 namespace = pvc["namespace"]
264 self.logger.info(f"Deleting pvc {name} in namespace {namespace}")
garciadeblas6d8acf32025-02-06 13:34:37 +0100265 self.logger.debug(f"Testing kubectl: {self._kubectl}")
266 self.logger.debug(
267 f"Testing kubectl configuration: {self._kubectl.configuration}"
268 )
269 self.logger.debug(
270 f"Testing kubectl configuration Host: {self._kubectl.configuration.host}"
271 )
garciadeblas28bff0f2024-09-16 12:53:07 +0200272 await self._kubectl.delete_pvc(name, namespace)
rshrif8911b92025-06-11 18:19:07 +0000273 # Delete configmaps
274 for configmap in items.get("configmaps", []):
275 name = configmap["name"]
276 namespace = configmap["namespace"]
277 self.logger.info(f"Deleting configmap {name} in namespace {namespace}")
278 self.logger.debug(f"Testing kubectl: {self._kubectl}")
279 self.logger.debug(
280 f"Testing kubectl configuration: {self._kubectl.configuration}"
281 )
282 self.logger.debug(
283 f"Testing kubectl configuration Host: {self._kubectl.configuration.host}"
284 )
285 self.delete_configmap(name, namespace)
286
287 async def list_object(self, api_group, api_plural, api_version):
288 self.logger.info(
289 f"Api group: {api_group} Api plural: {api_plural} Api version: {api_version}"
290 )
291 generic_object = await self._kubectl.list_generic_object(
292 api_group=api_group,
293 api_plural=api_plural,
294 api_version=api_version,
295 namespace="",
296 )
297 return generic_object