blob: ff40f9c8c0d8043487e503887f9e3828b08c4cf4 [file] [log] [blame]
yshah83a30572025-06-13 08:38:49 +00001#######################################################################################
2# Copyright ETSI Contributors and Others.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13# implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#######################################################################################
17
18
19import yaml
yshah37d6ac92025-09-23 10:09:58 +000020import json
yshah83a30572025-06-13 08:38:49 +000021
22
23def gather_age_key(cluster):
24 pubkey = cluster.get("age_pubkey")
25 privkey = cluster.get("age_privkey")
26 # return both public and private key
27 return pubkey, privkey
28
29
30async def add_nodegroup(self, op_id, op_params, content):
31 self.logger.info(f"Add Nodegroup Enter. Operation {op_id}. Params: {op_params}")
32
33 db_nodegroup = content["nodegroup"]
34 db_cluster = content["cluster"]
35 db_vim_account = content["vim_account"]
36
37 workflow_template = "launcher-add-nodegroup.j2"
38 workflow_name = f"add-nodegroup-{db_nodegroup['_id']}"
39 nodegroup_name = db_nodegroup["git_name"].lower()
40 cluster_name = db_cluster["git_name"].lower()
41 configmap_name = f"{nodegroup_name}-subnet-parameters"
42
43 # Get age key
44 public_key_new_cluster, private_key_new_cluster = gather_age_key(db_cluster)
45
46 # Test kubectl connection
47 self.logger.debug(self._kubectl._get_kubectl_version())
48
49 # Create temporal secret with agekey
50 secret_name = f"secret-age-{nodegroup_name}"
51 secret_namespace = "osm-workflows"
52 secret_key = "agekey"
53 secret_value = private_key_new_cluster
54 try:
55 await self.create_secret(
56 secret_name,
57 secret_namespace,
58 secret_key,
59 secret_value,
60 )
61 except Exception as e:
62 self.logger.info(f"Cannot create secret {secret_name}: {e}")
63 return False, f"Cannot create secret {secret_name}: {e}"
64
65 private_subnet = op_params.get("private_subnet", [])
66 public_subnet = op_params.get("public_subnet", [])
67 subnet = private_subnet + public_subnet
68 self.logger.info(f"Subnets: {subnet}")
yshah37d6ac92025-09-23 10:09:58 +000069 formatted_subnet = f"{json.dumps(subnet)}"
yshah83a30572025-06-13 08:38:49 +000070 # self.logger.info(f"Formatted Subnet: {formatted_subnet}")
71 # Create the ConfigMap for the subnets
72 # TODO: this should be done in a declarative way, not imperative
73 try:
74 await self.create_configmap(
75 configmap_name,
76 "managed-resources",
yshah37d6ac92025-09-23 10:09:58 +000077 {"subnet": formatted_subnet},
yshah83a30572025-06-13 08:38:49 +000078 )
79 except Exception as e:
80 self.logger.info(f"Cannot create configmap {configmap_name}: {e}")
81 return False, f"Cannot create configmap {configmap_name}: {e}"
82
83 # Additional params for the workflow
84 nodegroup_kustomization_name = nodegroup_name
85 osm_project_name = "osm_admin" # TODO: get project name from content
86 vim_account_id = db_cluster["vim_account"]
87 providerconfig_name = f"{vim_account_id}-config"
88 vim_type = db_vim_account["vim_type"]
89 if db_cluster.get("bootstrap", True):
90 skip_bootstrap = "false"
91 else:
92 skip_bootstrap = "true"
93 if vim_type == "azure":
94 cluster_type = "aks"
95 elif vim_type == "aws":
96 cluster_type = "eks"
97 elif vim_type == "gcp":
98 cluster_type = "gke"
99 else:
100 raise Exception("Not suitable VIM account to register cluster")
101
102 manifest = self.render_jinja_template(
103 workflow_template,
104 output_file=None,
105 workflow_name=workflow_name,
106 git_fleet_url=f"{self._repo_base_url}/{self._repo_user}/fleet-osm.git",
107 git_sw_catalogs_url=f"{self._repo_base_url}/{self._repo_user}/sw-catalogs-osm.git",
108 nodegroup_name=nodegroup_name,
109 nodegroup_kustomization_name=nodegroup_kustomization_name,
110 cluster_name=cluster_name,
111 cluster_type=cluster_type,
112 role=db_nodegroup.get("iam_role", "default"),
113 providerconfig_name=providerconfig_name,
114 public_key_mgmt=self._pubkey,
115 public_key_new_cluster=public_key_new_cluster,
116 secret_name_private_key_new_cluster=secret_name,
117 configmap_name=configmap_name,
118 vm_size=db_nodegroup["node_size"],
119 node_count=db_nodegroup["node_count"],
120 cluster_location=db_cluster["region_name"],
121 osm_project_name=osm_project_name,
122 rg_name=db_cluster.get("resource_group", "''"),
123 preemptible_nodes=db_cluster.get("preemptible_nodes", "false"),
124 skip_bootstrap=skip_bootstrap,
125 workflow_debug=self._workflow_debug,
126 workflow_dry_run=self._workflow_dry_run,
127 )
128 self.logger.debug(f"Workflow manifest: {manifest}")
129
130 # Submit workflow
131 self._kubectl.create_generic_object(
132 namespace="osm-workflows",
133 manifest_dict=yaml.safe_load(manifest),
134 api_group="argoproj.io",
135 api_plural="workflows",
136 api_version="v1alpha1",
137 )
138 return True, workflow_name
139
140
141async def scale_nodegroup(self, op_id, op_params, content):
142 self.logger.info(f"Scale nodegroup Enter. Operation {op_id}. Params: {op_params}")
143
144 db_nodegroup = content["nodegroup"]
145 db_cluster = content["cluster"]
146 db_vim_account = content["vim_account"]
147
148 workflow_template = "launcher-scale-nodegroup.j2"
149 workflow_name = f"scale-nodegroup-{db_nodegroup['_id']}"
150 nodegroup_name = db_nodegroup["git_name"].lower()
151 cluster_name = db_cluster["git_name"].lower()
152
153 # Get age key
154 public_key_new_cluster, private_key_new_cluster = gather_age_key(db_cluster)
155
156 # Test kubectl connection
157 self.logger.debug(self._kubectl._get_kubectl_version())
158
159 # Create temporal secret with agekey
160 secret_name = f"secret-age-{nodegroup_name}"
161 secret_namespace = "osm-workflows"
162 secret_key = "agekey"
163 secret_value = private_key_new_cluster
164 try:
165 await self.create_secret(
166 secret_name,
167 secret_namespace,
168 secret_key,
169 secret_value,
170 )
171 except Exception as e:
172 self.logger.info(f"Cannot create secret {secret_name}: {e}")
173 return False, f"Cannot create secret {secret_name}: {e}"
174
175 # Additional params for the workflow
176 nodegroup_kustomization_name = nodegroup_name
177 osm_project_name = "osm_admin" # TODO: get project name from content
178 vim_type = db_vim_account["vim_type"]
179 if vim_type == "azure":
180 cluster_type = "aks"
181 elif vim_type == "aws":
182 cluster_type = "eks"
183 elif vim_type == "gcp":
184 cluster_type = "gke"
185 else:
186 raise Exception("Not suitable VIM account to register cluster")
187
188 manifest = self.render_jinja_template(
189 workflow_template,
190 output_file=None,
191 workflow_name=workflow_name,
192 git_fleet_url=f"{self._repo_base_url}/{self._repo_user}/fleet-osm.git",
193 git_sw_catalogs_url=f"{self._repo_base_url}/{self._repo_user}/sw-catalogs-osm.git",
194 nodegroup_name=nodegroup_name,
195 nodegroup_kustomization_name=nodegroup_kustomization_name,
196 cluster_name=cluster_name,
197 cluster_type=cluster_type,
198 node_count=op_params["node_count"],
199 public_key_mgmt=self._pubkey,
200 public_key_new_cluster=public_key_new_cluster,
201 secret_name_private_key_new_cluster=secret_name,
202 osm_project_name=osm_project_name,
203 workflow_debug=self._workflow_debug,
204 workflow_dry_run=self._workflow_dry_run,
205 )
206 self.logger.debug(f"Workflow manifest: {manifest}")
207
208 # Submit workflow
209 self._kubectl.create_generic_object(
210 namespace="osm-workflows",
211 manifest_dict=yaml.safe_load(manifest),
212 api_group="argoproj.io",
213 api_plural="workflows",
214 api_version="v1alpha1",
215 )
216 return True, workflow_name
217
218
219async def delete_nodegroup(self, op_id, op_params, content):
220 self.logger.info(f"Delete nodegroup Enter. Operation {op_id}. Params: {op_params}")
221
222 db_nodegroup = content["nodegroup"]
223 db_cluster = content["cluster"]
224
225 workflow_template = "launcher-delete-nodegroup.j2"
226 workflow_name = f"delete-nodegroup-{db_nodegroup['_id']}"
227 nodegroup_name = db_nodegroup["git_name"].lower()
228
229 # Additional params for the workflow
230 nodegroup_kustomization_name = nodegroup_name
231 osm_project_name = "osm_admin" # TODO: get project name from DB
232
233 # Render workflow
234 manifest = self.render_jinja_template(
235 workflow_template,
236 output_file=None,
237 workflow_name=workflow_name,
238 git_fleet_url=f"{self._repo_base_url}/{self._repo_user}/fleet-osm.git",
239 git_sw_catalogs_url=f"{self._repo_base_url}/{self._repo_user}/sw-catalogs-osm.git",
240 nodegroup_name=nodegroup_name,
241 cluster_name=db_cluster["name"],
242 nodegroup_kustomization_name=nodegroup_kustomization_name,
243 osm_project_name=osm_project_name,
244 workflow_debug=self._workflow_debug,
245 workflow_dry_run=self._workflow_dry_run,
246 )
247 self.logger.info(f"Workflow Manifest: {manifest}")
248
249 # Submit workflow
250 self._kubectl.create_generic_object(
251 namespace="osm-workflows",
252 manifest_dict=yaml.safe_load(manifest),
253 api_group="argoproj.io",
254 api_plural="workflows",
255 api_version="v1alpha1",
256 )
257 return True, workflow_name
258
259
260async def clean_items_nodegroup_add(self, op_id, op_params, content):
261 self.logger.info(
262 f"clean_items_nodegroup_add Enter. Operation {op_id}. Params: {op_params}"
263 )
264 items = {
265 "secrets": [
266 {
267 "name": f"secret-age-{content['nodegroup']['git_name'].lower()}",
268 "namespace": "osm-workflows",
269 }
270 ],
271 }
272 try:
273 await self.clean_items(items)
274 return True, "OK"
275 except Exception as e:
276 return False, f"Error while cleaning items: {e}"
277
278
279async def clean_items_nodegroup_delete(self, op_id, op_params, content):
280 self.logger.info(
281 f"clean_items_nodegroup_delete Enter. Operation {op_id}. Params: {op_params}"
282 )
283 self.logger.info(
284 f"clean_items_nodegroup_delete Enter. Operation {op_id}. Params: {op_params}"
285 )
286 self.logger.debug(f"Content: {content}")
287 items = {
288 "configmaps": [
289 {
290 "name": f"{content['nodegroup']['git_name'].lower()}-subnet-parameters",
291 "namespace": "managed-resources",
292 }
293 ],
294 }
295 try:
296 await self.clean_items(items)
297 return True, "OK"
298 except Exception as e:
299 return False, f"Error while cleaning items: {e}"