X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=osm_lcm%2Flcm_helm_conn.py;h=0bd5c0f2aec44df7006ebbd94be0dc12c7216fa4;hb=e539a8d7d65be857fc64afa593893e6e6b0b52c0;hp=6fd33745f68ba0b7c7cf67318512968f6a8e92ab;hpb=a37c6ff4d2afe2ee96f3515406210eed3ab1b30f;p=osm%2FLCM.git diff --git a/osm_lcm/lcm_helm_conn.py b/osm_lcm/lcm_helm_conn.py index 6fd3374..0bd5c0f 100644 --- a/osm_lcm/lcm_helm_conn.py +++ b/osm_lcm/lcm_helm_conn.py @@ -27,7 +27,7 @@ from grpclib.client import Channel from osm_lcm.frontend_pb2 import PrimitiveRequest from osm_lcm.frontend_pb2 import SshKeyRequest, SshKeyReply from osm_lcm.frontend_grpc import FrontendExecutorStub -from osm_lcm.lcm_utils import LcmBase +from osm_lcm.lcm_utils import LcmBase, get_ee_id_parts from osm_lcm.data_utils.database.database import Database from osm_lcm.data_utils.filesystem.filesystem import Filesystem @@ -167,32 +167,41 @@ class LCMHelmConn(N2VCConnector, LcmBase): total_timeout: float = None, config: dict = None, artifact_path: str = None, + chart_model: str = None, vca_type: str = None, *kargs, **kwargs, ) -> (str, dict): """ Creates a new helm execution environment deploying the helm-chat indicated in the - attifact_path + artifact_path :param str namespace: This param is not used, all helm charts are deployed in the osm system namespace :param dict db_dict: where to write to database when the status changes. It contains a dictionary with {collection: str, filter: {}, path: str}, e.g. {collection: "nsrs", filter: {_id: , path: "_admin.deployed.VCA.3"} - :param str reuse_ee_id: ee id from an older execution. TODO - right now this params is not used + :param str reuse_ee_id: ee id from an older execution. TODO - right now this param is not used :param float progress_timeout: :param float total_timeout: :param dict config: General variables to instantiate KDU - :param str artifact_path: path of package content + :param str artifact_path: path of package content + :param str chart_model: helm chart/reference (string), which can be either + of these options: + - a name of chart available via the repos known by OSM + (e.g. stable/openldap, stable/openldap:1.2.4) + - a path to a packaged chart (e.g. mychart.tgz) + - a path to an unpacked chart directory or a URL (e.g. mychart) :param str vca_type: Type of vca, must be type helm or helm-v3 :returns str, dict: id of the new execution environment including namespace.helm_id and credentials object set to None as all credentials should be osm kubernetes .kubeconfig """ self.log.info( - "create_execution_environment: namespace: {}, artifact_path: {}, db_dict: {}, " - "reuse_ee_id: {}".format(namespace, artifact_path, db_dict, reuse_ee_id) + "create_execution_environment: namespace: {}, artifact_path: {}, " + "chart_model: {}, db_dict: {}, reuse_ee_id: {}".format( + namespace, artifact_path, db_dict, chart_model, reuse_ee_id + ) ) # Validate artifact-path is provided @@ -224,6 +233,13 @@ class LCMHelmConn(N2VCConnector, LcmBase): while full_path.find("//") >= 0: full_path = full_path.replace("//", "/") + # By default, the KDU is expected to be a file + kdu_model = full_path + # If the chart_model includes a "/", then it is a reference: + # e.g. (stable/openldap; stable/openldap:1.2.4) + if chart_model.find("/") >= 0: + kdu_model = chart_model + try: # Call helm conn install # Obtain system cluster id from database @@ -238,11 +254,11 @@ class LCMHelmConn(N2VCConnector, LcmBase): if vca_type == "helm": helm_id = self._k8sclusterhelm2.generate_kdu_instance_name( db_dict=db_dict, - kdu_model=full_path, + kdu_model=kdu_model, ) await self._k8sclusterhelm2.install( system_cluster_uuid, - kdu_model=full_path, + kdu_model=kdu_model, kdu_instance=helm_id, namespace=self._KUBECTL_OSM_NAMESPACE, params=config, @@ -252,11 +268,11 @@ class LCMHelmConn(N2VCConnector, LcmBase): else: helm_id = self._k8sclusterhelm2.generate_kdu_instance_name( db_dict=db_dict, - kdu_model=full_path, + kdu_model=kdu_model, ) await self._k8sclusterhelm3.install( system_cluster_uuid, - kdu_model=full_path, + kdu_model=kdu_model, kdu_instance=helm_id, namespace=self._KUBECTL_OSM_NAMESPACE, params=config, @@ -272,6 +288,117 @@ class LCMHelmConn(N2VCConnector, LcmBase): self.log.error("Error deploying chart ee: {}".format(e), exc_info=True) raise N2VCException("Error deploying chart ee: {}".format(e)) + async def upgrade_execution_environment( + self, + namespace: str, + db_dict: dict, + helm_id: str, + progress_timeout: float = None, + total_timeout: float = None, + config: dict = None, + artifact_path: str = None, + vca_type: str = None, + *kargs, + **kwargs, + ) -> (str, dict): + """ + Creates a new helm execution environment deploying the helm-chat indicated in the + attifact_path + :param str namespace: This param is not used, all helm charts are deployed in the osm + system namespace + :param dict db_dict: where to write to database when the status changes. + It contains a dictionary with {collection: str, filter: {}, path: str}, + e.g. {collection: "nsrs", filter: {_id: , path: + "_admin.deployed.VCA.3"} + :param helm_id: unique name of the Helm release to upgrade + :param float progress_timeout: + :param float total_timeout: + :param dict config: General variables to instantiate KDU + :param str artifact_path: path of package content + :param str vca_type: Type of vca, must be type helm or helm-v3 + :returns str, dict: id of the new execution environment including namespace.helm_id + and credentials object set to None as all credentials should be osm kubernetes .kubeconfig + """ + + self.log.info( + "upgrade_execution_environment: namespace: {}, artifact_path: {}, db_dict: {}, " + ) + + # Validate helm_id is provided + if helm_id is None or len(helm_id) == 0: + raise N2VCBadArgumentsException( + message="helm_id is mandatory", bad_args=["helm_id"] + ) + + # Validate artifact-path is provided + if artifact_path is None or len(artifact_path) == 0: + raise N2VCBadArgumentsException( + message="artifact_path is mandatory", bad_args=["artifact_path"] + ) + + # Validate artifact-path exists and sync path + from_path = os.path.split(artifact_path)[0] + self.fs.sync(from_path) + + # remove / in charm path + while artifact_path.find("//") >= 0: + artifact_path = artifact_path.replace("//", "/") + + # check charm path + if self.fs.file_exists(artifact_path): + helm_chart_path = artifact_path + else: + msg = "artifact path does not exist: {}".format(artifact_path) + raise N2VCBadArgumentsException(message=msg, bad_args=["artifact_path"]) + + if artifact_path.startswith("/"): + full_path = self.fs.path + helm_chart_path + else: + full_path = self.fs.path + "/" + helm_chart_path + + while full_path.find("//") >= 0: + full_path = full_path.replace("//", "/") + + try: + # Call helm conn upgrade + # Obtain system cluster id from database + system_cluster_uuid = await self._get_system_cluster_id() + # Add parameter osm if exist to global + if config and config.get("osm"): + if not config.get("global"): + config["global"] = {} + config["global"]["osm"] = config.get("osm") + + self.log.debug("Ugrade helm chart: {}".format(full_path)) + if vca_type == "helm": + await self._k8sclusterhelm2.upgrade( + system_cluster_uuid, + kdu_model=full_path, + kdu_instance=helm_id, + namespace=namespace, + params=config, + db_dict=db_dict, + timeout=progress_timeout, + force=True, + ) + else: + await self._k8sclusterhelm3.upgrade( + system_cluster_uuid, + kdu_model=full_path, + kdu_instance=helm_id, + namespace=namespace, + params=config, + db_dict=db_dict, + timeout=progress_timeout, + force=True, + ) + + except N2VCException: + raise + except Exception as e: + self.log.error("Error upgrading chart ee: {}".format(e), exc_info=True) + raise N2VCException("Error upgrading chart ee: {}".format(e)) + async def register_execution_environment( self, namespace: str, @@ -332,7 +459,7 @@ class LCMHelmConn(N2VCConnector, LcmBase): try: # Obtain ip_addr for the ee service, it is resolved by dns from the ee name by kubernetes - version, namespace, helm_id = self._get_ee_id_parts(ee_id) + version, namespace, helm_id = get_ee_id_parts(ee_id) ip_addr = socket.gethostbyname(helm_id) # Obtain ssh_key from the ee, this method will implement retries to allow the ee @@ -417,7 +544,7 @@ class LCMHelmConn(N2VCConnector, LcmBase): params_dict = dict() try: - version, namespace, helm_id = self._get_ee_id_parts(ee_id) + version, namespace, helm_id = get_ee_id_parts(ee_id) ip_addr = socket.gethostbyname(helm_id) except Exception as e: self.log.error("Error getting ee ip ee: {}".format(e)) @@ -524,7 +651,7 @@ class LCMHelmConn(N2VCConnector, LcmBase): system_cluster_uuid = await self._get_system_cluster_id() # Get helm_id - version, namespace, helm_id = self._get_ee_id_parts(ee_id) + version, namespace, helm_id = get_ee_id_parts(ee_id) # Uninstall chart, for backward compatibility we must assume that if there is no # version it is helm-v2 @@ -671,13 +798,3 @@ class LCMHelmConn(N2VCConnector, LcmBase): ) self._system_cluster_id = k8s_hc_id return self._system_cluster_id - - def _get_ee_id_parts(self, ee_id): - """ - Parses ee_id stored at database that can be either 'version:namespace.helm_id' or only - namespace.helm_id for backward compatibility - If exists helm version can be helm-v3 or helm (helm-v2 old version) - """ - version, _, part_id = ee_id.rpartition(":") - namespace, _, helm_id = part_id.rpartition(".") - return version, namespace, helm_id