2 # Copyright 2020 Telefonica Investigacion y Desarrollo, S.A.U.
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
8 # http://www.apache.org/licenses/LICENSE-2.0
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
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
25 from grpclib
.client
import Channel
27 from osm_lcm
.data_utils
.lcm_config
import VcaConfig
28 from osm_lcm
.frontend_pb2
import PrimitiveRequest
29 from osm_lcm
.frontend_pb2
import SshKeyRequest
, SshKeyReply
30 from osm_lcm
.frontend_grpc
import FrontendExecutorStub
31 from osm_lcm
.lcm_utils
import LcmBase
, get_ee_id_parts
33 from osm_lcm
.data_utils
.database
.database
import Database
34 from osm_lcm
.data_utils
.filesystem
.filesystem
import Filesystem
36 from n2vc
.n2vc_conn
import N2VCConnector
37 from n2vc
.k8s_helm_conn
import K8sHelmConnector
38 from n2vc
.k8s_helm3_conn
import K8sHelm3Connector
39 from n2vc
.exceptions
import (
40 N2VCBadArgumentsException
,
42 N2VCExecutionException
,
45 from osm_lcm
.lcm_utils
import deep_get
48 def retryer(max_wait_time_var
="_initial_retry_time", delay_time_var
="_retry_delay"):
50 retry_exceptions
= (ConnectionRefusedError
, TimeoutError
)
52 @functools.wraps(func
)
53 async def wrapped(*args
, **kwargs
):
54 # default values for wait time and delay_time
58 # obtain arguments from variable names
60 if self
.__dict
__.get(max_wait_time_var
):
61 max_wait_time
= self
.__dict
__.get(max_wait_time_var
)
62 if self
.__dict
__.get(delay_time_var
):
63 delay_time
= self
.__dict
__.get(delay_time_var
)
65 wait_time
= max_wait_time
68 return await func(*args
, **kwargs
)
69 except retry_exceptions
:
70 wait_time
= wait_time
- delay_time
71 await asyncio
.sleep(delay_time
)
74 return ConnectionRefusedError
81 def create_secure_context(
84 ctx
= ssl
.SSLContext(ssl
.PROTOCOL_TLS_CLIENT
)
85 ctx
.verify_mode
= ssl
.CERT_REQUIRED
86 ctx
.check_hostname
= True
87 ctx
.minimum_version
= ssl
.TLSVersion
.TLSv1_2
89 # ctx.load_cert_chain(str(client_cert), str(client_key))
90 ctx
.load_verify_locations(trusted
)
91 ctx
.set_ciphers("ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20")
92 ctx
.set_alpn_protocols(["h2"])
94 ctx
.set_npn_protocols(["h2"])
95 except NotImplementedError:
100 class LCMHelmConn(N2VCConnector
, LcmBase
):
105 vca_config
: VcaConfig
= None,
109 Initialize EE helm connector.
112 self
.db
= Database().instance
.db
113 self
.fs
= Filesystem().instance
.fs
115 # parent class constructor
116 N2VCConnector
.__init
__(
117 self
, log
=log
, loop
=loop
, on_update_db
=on_update_db
, db
=self
.db
, fs
=self
.fs
120 self
.vca_config
= vca_config
121 self
.log
.debug("Initialize helm N2VC connector")
122 self
.log
.debug("initial vca_config: {}".format(vca_config
.to_dict()))
124 self
._retry
_delay
= self
.vca_config
.helm_ee_retry_delay
126 self
._initial
_retry
_time
= self
.vca_config
.helm_max_initial_retry_time
127 self
.log
.debug("Initial retry time: {}".format(self
._initial
_retry
_time
))
129 self
._max
_retry
_time
= self
.vca_config
.helm_max_retry_time
130 self
.log
.debug("Retry time: {}".format(self
._max
_retry
_time
))
132 # initialize helm connector for helmv2 and helmv3
133 self
._k
8sclusterhelm
2 = K8sHelmConnector(
134 kubectl_command
=self
.vca_config
.kubectlpath
,
135 helm_command
=self
.vca_config
.helmpath
,
142 self
._k
8sclusterhelm
3 = K8sHelm3Connector(
143 kubectl_command
=self
.vca_config
.kubectlpath
,
144 helm_command
=self
.vca_config
.helm3path
,
151 self
._system
_cluster
_id
= None
152 self
.log
.info("Helm N2VC connector initialized")
154 # TODO - ¿reuse_ee_id?
155 async def create_execution_environment(
159 reuse_ee_id
: str = None,
160 progress_timeout
: float = None,
161 total_timeout
: float = None,
163 artifact_path
: str = None,
164 chart_model
: str = None,
165 vca_type
: str = None,
170 Creates a new helm execution environment deploying the helm-chat indicated in the
172 :param str namespace: This param is not used, all helm charts are deployed in the osm
174 :param dict db_dict: where to write to database when the status changes.
175 It contains a dictionary with {collection: str, filter: {}, path: str},
176 e.g. {collection: "nsrs", filter: {_id: <nsd-id>, path:
177 "_admin.deployed.VCA.3"}
178 :param str reuse_ee_id: ee id from an older execution. TODO - right now this param is not used
179 :param float progress_timeout:
180 :param float total_timeout:
181 :param dict config: General variables to instantiate KDU
182 :param str artifact_path: path of package content
183 :param str chart_model: helm chart/reference (string), which can be either
185 - a name of chart available via the repos known by OSM
186 (e.g. stable/openldap, stable/openldap:1.2.4)
187 - a path to a packaged chart (e.g. mychart.tgz)
188 - a path to an unpacked chart directory or a URL (e.g. mychart)
189 :param str vca_type: Type of vca, must be type helm or helm-v3
190 :returns str, dict: id of the new execution environment including namespace.helm_id
191 and credentials object set to None as all credentials should be osm kubernetes .kubeconfig
195 "create_execution_environment: namespace: {}, artifact_path: {}, "
196 "chart_model: {}, db_dict: {}, reuse_ee_id: {}".format(
197 namespace
, artifact_path
, db_dict
, chart_model
, reuse_ee_id
201 # Validate artifact-path is provided
202 if artifact_path
is None or len(artifact_path
) == 0:
203 raise N2VCBadArgumentsException(
204 message
="artifact_path is mandatory", bad_args
=["artifact_path"]
207 # Validate artifact-path exists and sync path
208 from_path
= os
.path
.split(artifact_path
)[0]
209 self
.fs
.sync(from_path
)
211 # remove / in charm path
212 while artifact_path
.find("//") >= 0:
213 artifact_path
= artifact_path
.replace("//", "/")
216 if self
.fs
.file_exists(artifact_path
):
217 helm_chart_path
= artifact_path
219 msg
= "artifact path does not exist: {}".format(artifact_path
)
220 raise N2VCBadArgumentsException(message
=msg
, bad_args
=["artifact_path"])
222 if artifact_path
.startswith("/"):
223 full_path
= self
.fs
.path
+ helm_chart_path
225 full_path
= self
.fs
.path
+ "/" + helm_chart_path
227 while full_path
.find("//") >= 0:
228 full_path
= full_path
.replace("//", "/")
230 # By default, the KDU is expected to be a file
231 kdu_model
= full_path
232 # If the chart_model includes a "/", then it is a reference:
233 # e.g. (stable/openldap; stable/openldap:1.2.4)
234 if chart_model
.find("/") >= 0:
235 kdu_model
= chart_model
238 # Call helm conn install
239 # Obtain system cluster id from database
240 system_cluster_uuid
= await self
._get
_system
_cluster
_id
()
241 # Add parameter osm if exist to global
242 if config
and config
.get("osm"):
243 if not config
.get("global"):
244 config
["global"] = {}
245 config
["global"]["osm"] = config
.get("osm")
247 self
.log
.debug("install helm chart: {}".format(full_path
))
248 if vca_type
== "helm":
249 helm_id
= self
._k
8sclusterhelm
2.generate_kdu_instance_name(
253 await self
._k
8sclusterhelm
2.install(
256 kdu_instance
=helm_id
,
257 namespace
=self
.vca_config
.kubectl_osm_namespace
,
260 timeout
=progress_timeout
,
263 helm_id
= self
._k
8sclusterhelm
2.generate_kdu_instance_name(
267 await self
._k
8sclusterhelm
3.install(
270 kdu_instance
=helm_id
,
271 namespace
=self
.vca_config
.kubectl_osm_namespace
,
274 timeout
=progress_timeout
,
277 ee_id
= "{}:{}.{}".format(
278 vca_type
, self
.vca_config
.kubectl_osm_namespace
, helm_id
281 except N2VCException
:
283 except Exception as e
:
284 self
.log
.error("Error deploying chart ee: {}".format(e
), exc_info
=True)
285 raise N2VCException("Error deploying chart ee: {}".format(e
))
287 async def upgrade_execution_environment(
292 progress_timeout
: float = None,
293 total_timeout
: float = None,
295 artifact_path
: str = None,
296 vca_type
: str = None,
301 Creates a new helm execution environment deploying the helm-chat indicated in the
303 :param str namespace: This param is not used, all helm charts are deployed in the osm
305 :param dict db_dict: where to write to database when the status changes.
306 It contains a dictionary with {collection: str, filter: {}, path: str},
307 e.g. {collection: "nsrs", filter: {_id: <nsd-id>, path:
308 "_admin.deployed.VCA.3"}
309 :param helm_id: unique name of the Helm release to upgrade
310 :param float progress_timeout:
311 :param float total_timeout:
312 :param dict config: General variables to instantiate KDU
313 :param str artifact_path: path of package content
314 :param str vca_type: Type of vca, must be type helm or helm-v3
315 :returns str, dict: id of the new execution environment including namespace.helm_id
316 and credentials object set to None as all credentials should be osm kubernetes .kubeconfig
320 "upgrade_execution_environment: namespace: {}, artifact_path: {}, db_dict: {}, "
323 # Validate helm_id is provided
324 if helm_id
is None or len(helm_id
) == 0:
325 raise N2VCBadArgumentsException(
326 message
="helm_id is mandatory", bad_args
=["helm_id"]
329 # Validate artifact-path is provided
330 if artifact_path
is None or len(artifact_path
) == 0:
331 raise N2VCBadArgumentsException(
332 message
="artifact_path is mandatory", bad_args
=["artifact_path"]
335 # Validate artifact-path exists and sync path
336 from_path
= os
.path
.split(artifact_path
)[0]
337 self
.fs
.sync(from_path
)
339 # remove / in charm path
340 while artifact_path
.find("//") >= 0:
341 artifact_path
= artifact_path
.replace("//", "/")
344 if self
.fs
.file_exists(artifact_path
):
345 helm_chart_path
= artifact_path
347 msg
= "artifact path does not exist: {}".format(artifact_path
)
348 raise N2VCBadArgumentsException(message
=msg
, bad_args
=["artifact_path"])
350 if artifact_path
.startswith("/"):
351 full_path
= self
.fs
.path
+ helm_chart_path
353 full_path
= self
.fs
.path
+ "/" + helm_chart_path
355 while full_path
.find("//") >= 0:
356 full_path
= full_path
.replace("//", "/")
359 # Call helm conn upgrade
360 # Obtain system cluster id from database
361 system_cluster_uuid
= await self
._get
_system
_cluster
_id
()
362 # Add parameter osm if exist to global
363 if config
and config
.get("osm"):
364 if not config
.get("global"):
365 config
["global"] = {}
366 config
["global"]["osm"] = config
.get("osm")
368 self
.log
.debug("Ugrade helm chart: {}".format(full_path
))
369 if vca_type
== "helm":
370 await self
._k
8sclusterhelm
2.upgrade(
373 kdu_instance
=helm_id
,
377 timeout
=progress_timeout
,
381 await self
._k
8sclusterhelm
3.upgrade(
384 kdu_instance
=helm_id
,
388 timeout
=progress_timeout
,
392 except N2VCException
:
394 except Exception as e
:
395 self
.log
.error("Error upgrading chart ee: {}".format(e
), exc_info
=True)
396 raise N2VCException("Error upgrading chart ee: {}".format(e
))
398 async def create_tls_certificate(
404 namespace
: str = None,
406 # Obtain system cluster id from database
407 system_cluster_uuid
= await self
._get
_system
_cluster
_id
()
408 # use helm-v3 as certificates don't depend on helm version
409 await self
._k
8sclusterhelm
3.create_certificate(
410 cluster_uuid
=system_cluster_uuid
,
411 namespace
=namespace
or self
.vca_config
.kubectl_osm_namespace
,
412 dns_prefix
=dns_prefix
,
414 secret_name
=secret_name
,
418 async def delete_tls_certificate(
420 certificate_name
: str = None,
421 namespace
: str = None,
423 # Obtain system cluster id from database
424 system_cluster_uuid
= await self
._get
_system
_cluster
_id
()
425 await self
._k
8sclusterhelm
3.delete_certificate(
426 cluster_uuid
=system_cluster_uuid
,
427 namespace
=namespace
or self
.vca_config
.kubectl_osm_namespace
,
428 certificate_name
=certificate_name
,
431 async def register_execution_environment(
436 progress_timeout
: float = None,
437 total_timeout
: float = None,
444 async def install_configuration_sw(self
, *args
, **kwargs
):
448 async def add_relation(self
, *args
, **kwargs
):
452 async def remove_relation(self
):
456 async def get_status(self
, *args
, **kwargs
):
457 # not used for this connector
460 async def get_ee_ssh_public__key(
464 progress_timeout
: float = None,
465 total_timeout
: float = None,
469 Obtains ssh-public key from ee executing GetSShKey method from the ee.
471 :param str ee_id: the id of the execution environment returned by
472 create_execution_environment or register_execution_environment
474 :param float progress_timeout:
475 :param float total_timeout:
476 :returns: public key of the execution environment
480 "get_ee_ssh_public_key: ee_id: {}, db_dict: {}".format(ee_id
, db_dict
)
484 if ee_id
is None or len(ee_id
) == 0:
485 raise N2VCBadArgumentsException(
486 message
="ee_id is mandatory", bad_args
=["ee_id"]
490 # Obtain ip_addr for the ee service, it is resolved by dns from the ee name by kubernetes
491 version
, namespace
, helm_id
= get_ee_id_parts(ee_id
)
492 ip_addr
= "{}.{}.svc".format(helm_id
, namespace
)
493 # Obtain ssh_key from the ee, this method will implement retries to allow the ee
494 # install libraries and start successfully
495 ssh_key
= await self
._get
_ssh
_key
(ip_addr
)
497 except Exception as e
:
498 self
.log
.error("Error obtaining ee ssh_key: {}".format(e
), exc_info
=True)
499 raise N2VCException("Error obtaining ee ssh_ke: {}".format(e
))
501 async def upgrade_charm(
505 charm_id
: str = None,
506 charm_type
: str = None,
507 timeout
: float = None,
509 """This method upgrade charms in VNFs
511 This method does not support KDU's deployed with Helm.
514 ee_id: Execution environment id
515 path: Local path to the charm
517 charm_type: Charm type can be lxc-proxy-charm, native-charm or k8s-proxy-charm
518 timeout: (Float) Timeout for the ns update operation
521 the output of the update operation if status equals to "completed"
524 raise N2VCException("KDUs deployed with Helm do not support charm upgrade")
526 async def exec_primitive(
531 db_dict
: dict = None,
532 progress_timeout
: float = None,
533 total_timeout
: float = None,
537 Execute a primitive in the execution environment
539 :param str ee_id: the one returned by create_execution_environment or
540 register_execution_environment with the format namespace.helm_id
541 :param str primitive_name: must be one defined in the software. There is one
542 called 'config', where, for the proxy case, the 'credentials' of VM are
544 :param dict params_dict: parameters of the action
545 :param dict db_dict: where to write into database when the status changes.
546 It contains a dict with
547 {collection: <str>, filter: {}, path: <str>},
548 e.g. {collection: "nslcmops", filter:
549 {_id: <nslcmop_id>, path: "_admin.VCA"}
550 It will be used to store information about intermediate notifications
551 :param float progress_timeout:
552 :param float total_timeout:
553 :returns str: primitive result, if ok. It raises exceptions in case of fail
557 "exec primitive for ee_id : {}, primitive_name: {}, params_dict: {}, db_dict: {}".format(
558 ee_id
, primitive_name
, params_dict
, db_dict
563 if ee_id
is None or len(ee_id
) == 0:
564 raise N2VCBadArgumentsException(
565 message
="ee_id is mandatory", bad_args
=["ee_id"]
567 if primitive_name
is None or len(primitive_name
) == 0:
568 raise N2VCBadArgumentsException(
569 message
="action_name is mandatory", bad_args
=["action_name"]
571 if params_dict
is None:
575 version
, namespace
, helm_id
= get_ee_id_parts(ee_id
)
576 ip_addr
= "{}.{}.svc".format(helm_id
, namespace
)
577 except Exception as e
:
578 self
.log
.error("Error getting ee ip ee: {}".format(e
))
579 raise N2VCException("Error getting ee ip ee: {}".format(e
))
581 if primitive_name
== "config":
583 # Execute config primitive, higher timeout to check the case ee is starting
584 status
, detailed_message
= await self
._execute
_config
_primitive
(
585 ip_addr
, params_dict
, db_dict
=db_dict
588 "Executed config primitive ee_id_ {}, status: {}, message: {}".format(
589 ee_id
, status
, detailed_message
594 "Error configuring helm ee, status: {}, message: {}".format(
595 status
, detailed_message
598 raise N2VCExecutionException(
599 message
="Error configuring helm ee_id: {}, status: {}, message: {}: ".format(
600 ee_id
, status
, detailed_message
602 primitive_name
=primitive_name
,
604 except Exception as e
:
605 self
.log
.error("Error configuring helm ee: {}".format(e
))
606 raise N2VCExecutionException(
607 message
="Error configuring helm ee_id: {}, {}".format(ee_id
, e
),
608 primitive_name
=primitive_name
,
614 status
, detailed_message
= await self
._execute
_primitive
(
615 ip_addr
, primitive_name
, params_dict
, db_dict
=db_dict
618 "Executed primitive {} ee_id_ {}, status: {}, message: {}".format(
619 primitive_name
, ee_id
, status
, detailed_message
622 if status
!= "OK" and status
!= "PROCESSING":
624 "Execute primitive {} returned not ok status: {}, message: {}".format(
625 primitive_name
, status
, detailed_message
628 raise N2VCExecutionException(
629 message
="Execute primitive {} returned not ok status: {}, message: {}".format(
630 primitive_name
, status
, detailed_message
632 primitive_name
=primitive_name
,
634 except Exception as e
:
636 "Error executing primitive {}: {}".format(primitive_name
, e
)
638 raise N2VCExecutionException(
639 message
="Error executing primitive {} into ee={} : {}".format(
640 primitive_name
, ee_id
, e
642 primitive_name
=primitive_name
,
644 return detailed_message
646 async def deregister_execution_environments(self
):
650 async def delete_execution_environment(
653 db_dict
: dict = None,
654 total_timeout
: float = None,
658 Delete an execution environment
659 :param str ee_id: id of the execution environment to delete, included namespace.helm_id
660 :param dict db_dict: where to write into database when the status changes.
661 It contains a dict with
662 {collection: <str>, filter: {}, path: <str>},
663 e.g. {collection: "nsrs", filter:
664 {_id: <nsd-id>, path: "_admin.deployed.VCA.3"}
665 :param float total_timeout:
668 self
.log
.info("ee_id: {}".format(ee_id
))
672 raise N2VCBadArgumentsException(
673 message
="ee_id is mandatory", bad_args
=["ee_id"]
677 # Obtain cluster_uuid
678 system_cluster_uuid
= await self
._get
_system
_cluster
_id
()
681 version
, namespace
, helm_id
= get_ee_id_parts(ee_id
)
683 # Uninstall chart, for backward compatibility we must assume that if there is no
684 # version it is helm-v2
685 if version
== "helm-v3":
686 await self
._k
8sclusterhelm
3.uninstall(system_cluster_uuid
, helm_id
)
688 await self
._k
8sclusterhelm
2.uninstall(system_cluster_uuid
, helm_id
)
689 self
.log
.info("ee_id: {} deleted".format(ee_id
))
690 except N2VCException
:
692 except Exception as e
:
694 "Error deleting ee id: {}: {}".format(ee_id
, e
), exc_info
=True
696 raise N2VCException("Error deleting ee id {}: {}".format(ee_id
, e
))
698 async def delete_namespace(
699 self
, namespace
: str, db_dict
: dict = None, total_timeout
: float = None
701 # method not implemented for this connector, execution environments must be deleted individually
704 async def install_k8s_proxy_charm(
710 progress_timeout
: float = None,
711 total_timeout
: float = None,
718 @retryer(max_wait_time_var
="_initial_retry_time", delay_time_var
="_retry_delay")
719 async def _get_ssh_key(self
, ip_addr
):
720 return await self
._execute
_primitive
_internal
(
726 @retryer(max_wait_time_var
="_initial_retry_time", delay_time_var
="_retry_delay")
727 async def _execute_config_primitive(self
, ip_addr
, params
, db_dict
=None):
728 return await self
._execute
_primitive
_internal
(
729 ip_addr
, "config", params
, db_dict
=db_dict
732 @retryer(max_wait_time_var
="_max_retry_time", delay_time_var
="_retry_delay")
733 async def _execute_primitive(self
, ip_addr
, primitive_name
, params
, db_dict
=None):
734 return await self
._execute
_primitive
_internal
(
735 ip_addr
, primitive_name
, params
, db_dict
=db_dict
738 async def _execute_primitive_internal(
739 self
, ip_addr
, primitive_name
, params
, db_dict
=None
742 stub
= FrontendExecutorStub(channel
)
743 if primitive_name
== "_get_ssh_key":
744 self
.log
.debug("get ssh key, ip_addr: {}".format(ip_addr
))
745 reply
: SshKeyReply
= await stub
.GetSshKey(SshKeyRequest())
747 # For any other primitives
748 async with stub
.RunPrimitive
.open() as stream
:
749 primitive_id
= str(uuid
.uuid1())
752 "Execute primitive internal: id:{}, name:{}, params: {}".format(
753 primitive_id
, primitive_name
, params
756 await stream
.send_message(
758 id=primitive_id
, name
=primitive_name
, params
=yaml
.dump(params
)
762 async for reply
in stream
:
763 self
.log
.debug("Received reply: {}".format(reply
))
765 # If db_dict provided write notifs in database
767 self
._write
_op
_detailed
_status
(
768 db_dict
, reply
.status
, reply
.detailed_message
771 return reply
.status
, reply
.detailed_message
773 return "ERROR", "No result received"
775 ssl_context
= create_secure_context(self
.vca_config
.ca_store
)
777 ip_addr
, self
.vca_config
.helm_ee_service_port
, ssl
=ssl_context
780 return await execute()
781 except ssl
.SSLError
as ssl_error
: # fallback to insecure gRPC
783 ssl_error
.reason
== "WRONG_VERSION_NUMBER"
784 and not self
.vca_config
.eegrpc_tls_enforce
787 "Execution environment doesn't support TLS, falling back to unsecure gRPC"
789 channel
= Channel(ip_addr
, self
.vca_config
.helm_ee_service_port
)
790 return await execute()
791 elif ssl_error
.reason
== "WRONG_VERSION_NUMBER":
793 "Execution environment doesn't support TLS, primitives cannot be executed"
800 def _write_op_detailed_status(self
, db_dict
, status
, detailed_message
):
801 # write ee_id to database: _admin.deployed.VCA.x
803 the_table
= db_dict
["collection"]
804 the_filter
= db_dict
["filter"]
805 update_dict
= {"detailed-status": "{}: {}".format(status
, detailed_message
)}
806 # self.log.debug('Writing ee_id to database: {}'.format(the_path))
810 update_dict
=update_dict
,
813 except asyncio
.CancelledError
:
815 except Exception as e
:
816 self
.log
.error("Error writing detailedStatus to database: {}".format(e
))
818 async def _get_system_cluster_id(self
):
819 if not self
._system
_cluster
_id
:
820 db_k8cluster
= self
.db
.get_one(
821 "k8sclusters", {"name": self
.vca_config
.kubectl_osm_cluster_name
}
823 k8s_hc_id
= deep_get(db_k8cluster
, ("_admin", "helm-chart-v3", "id"))
826 # backward compatibility for existing clusters that have not been initialized for helm v3
827 cluster_id
= db_k8cluster
.get("_id")
828 k8s_credentials
= yaml
.safe_dump(db_k8cluster
.get("credentials"))
829 k8s_hc_id
, uninstall_sw
= await self
._k
8sclusterhelm
3.init_env(
830 k8s_credentials
, reuse_cluster_uuid
=cluster_id
832 db_k8scluster_update
= {
833 "_admin.helm-chart-v3.error_msg": None,
834 "_admin.helm-chart-v3.id": k8s_hc_id
,
835 "_admin.helm-chart-v3}.created": uninstall_sw
,
836 "_admin.helm-chart-v3.operationalState": "ENABLED",
838 self
.update_db_2("k8sclusters", cluster_id
, db_k8scluster_update
)
839 except Exception as e
:
841 "error initializing helm-v3 cluster: {}".format(str(e
))
844 "K8s system cluster '{}' has not been initialized for helm-chart-v3".format(
848 self
._system
_cluster
_id
= k8s_hc_id
849 return self
._system
_cluster
_id