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