From c4d4027967ad2ddf39e464f9711b77516002a6b8 Mon Sep 17 00:00:00 2001 From: Antonio Marsico Date: Wed, 30 Jun 2021 16:49:53 +0200 Subject: [PATCH] Improved Kubernetes management * Implementing wait option * Fixing cluster update Change-Id: I9e234518df18e7736e573bdd613240e9342cda10 Signed-off-by: Antonio Marsico --- osmclient/scripts/osm.py | 39 +++++++++++---- osmclient/sol005/k8scluster.py | 86 +++++++++++++++++++++++++--------- 2 files changed, 94 insertions(+), 31 deletions(-) diff --git a/osmclient/scripts/osm.py b/osmclient/scripts/osm.py index 9ca159f..df638a0 100755 --- a/osmclient/scripts/osm.py +++ b/osmclient/scripts/osm.py @@ -3826,6 +3826,14 @@ def sdnc_show(ctx, name): default="kube-system", help="namespace to be used for its operation, defaults to `kube-system`", ) +@click.option( + "--wait", + required=False, + default=False, + is_flag=True, + help="do not return the control immediately, but keep it " + "until the operation is completed, or timeout", +) @click.option( "--cni", default=None, @@ -3839,7 +3847,7 @@ def sdnc_show(ctx, name): # help='do not return the control immediately, but keep it until the operation is completed, or timeout') @click.pass_context def k8scluster_add( - ctx, name, creds, version, vim, k8s_nets, description, namespace, cni + ctx, name, creds, version, vim, k8s_nets, description, namespace, wait, cni ): """adds a K8s cluster to OSM @@ -3860,7 +3868,7 @@ def k8scluster_add( cluster["namespace"] = namespace if cni: cluster["cni"] = yaml.safe_load(cni) - ctx.obj.k8scluster.create(name, cluster) + ctx.obj.k8scluster.create(name, cluster, wait) # except ClientException as e: # print(str(e)) # exit(1) @@ -3882,12 +3890,20 @@ def k8scluster_add( "--namespace", help="namespace to be used for its operation, defaults to `kube-system`", ) +@click.option( + "--wait", + required=False, + default=False, + is_flag=True, + help="do not return the control immediately, but keep it " + "until the operation is completed, or timeout", +) @click.option( "--cni", help="list of CNI plugins, in JSON inline format, used in the cluster" ) @click.pass_context def k8scluster_update( - ctx, name, newname, creds, version, vim, k8s_nets, description, namespace, cni + ctx, name, newname, creds, version, vim, k8s_nets, description, namespace, wait, cni ): """updates a K8s cluster @@ -3913,7 +3929,7 @@ def k8scluster_update( cluster["namespace"] = namespace if cni: cluster["cni"] = yaml.safe_load(cni) - ctx.obj.k8scluster.update(name, cluster) + ctx.obj.k8scluster.update(name, cluster, wait) # except ClientException as e: # print(str(e)) # exit(1) @@ -3924,18 +3940,23 @@ def k8scluster_update( @click.option( "--force", is_flag=True, help="forces the deletion from the DB (not recommended)" ) -# @click.option('--wait', -# is_flag=True, -# help='do not return the control immediately, but keep it until the operation is completed, or timeout') +@click.option( + "--wait", + required=False, + default=False, + is_flag=True, + help="do not return the control immediately, but keep it " + "until the operation is completed, or timeout", +) @click.pass_context -def k8scluster_delete(ctx, name, force): +def k8scluster_delete(ctx, name, force, wait): """deletes a K8s cluster NAME: name or ID of the K8s cluster to be deleted """ # try: check_client_version(ctx.obj, ctx.command.name) - ctx.obj.k8scluster.delete(name, force=force) + ctx.obj.k8scluster.delete(name, force, wait) # except ClientException as e: # print(str(e)) # exit(1) diff --git a/osmclient/sol005/k8scluster.py b/osmclient/sol005/k8scluster.py index 92ef49e..a0b95e0 100644 --- a/osmclient/sol005/k8scluster.py +++ b/osmclient/sol005/k8scluster.py @@ -17,15 +17,18 @@ OSM K8s cluster API handling """ from osmclient.common import utils +from osmclient.common import wait as WaitForStatus from osmclient.common.exceptions import NotFound from osmclient.common.exceptions import ClientException import json +import logging class K8scluster(object): def __init__(self, http=None, client=None): self._http = http self._client = client + self._logger = logging.getLogger("osmclient.k8scluster") self._apiName = "/admin" self._apiVersion = "/v1" self._apiResource = "/k8sclusters" @@ -39,7 +42,25 @@ class K8scluster(object): raise NotFound("cannot find vim account '{}'".format(vim_account)) return vim - def create(self, name, k8s_cluster): + # K8S '--wait' option + def _wait(self, id, wait_time, deleteFlag=False): + self._logger.debug("") + self._client.get_token() + # Endpoint to get operation status + apiUrlStatus = "{}{}{}".format(self._apiName, self._apiVersion, self._apiResource) + # Wait for status for VIM instance creation/deletion + if isinstance(wait_time, bool): + wait_time = WaitForStatus.TIMEOUT_VIM_OPERATION + WaitForStatus.wait_for_status( + "K8S", + str(id), + wait_time, + apiUrlStatus, + self._http.get2_cmd, + deleteFlag=deleteFlag, + ) + + def create(self, name, k8s_cluster, wait=False): self._client.get_token() vim_account = self._get_vim_account(k8s_cluster["vim_account"]) k8s_cluster["vim_account"] = vim_account["_id"] @@ -48,13 +69,17 @@ class K8scluster(object): http_code, resp = self._http.post_cmd( endpoint=self._apiBase, postfields_dict=k8s_cluster ) - # print 'HTTP CODE: {}'.format(http_code) - # print 'RESP: {}'.format(resp) - # if http_code in (200, 201, 202, 204): + + self._logger.debug('HTTP CODE: {}'.format(http_code)) + self._logger.debug('RESP: {}'.format(resp)) + if resp: resp = json.loads(resp) if not resp or "id" not in resp: raise ClientException("unexpected response from server - {}".format(resp)) + if wait: + # Wait for status for VIM instance creation + self._wait(resp.get("id"), wait) print(resp["id"]) # else: # msg = "" @@ -65,7 +90,7 @@ class K8scluster(object): # msg = resp # raise ClientException("failed to add K8s cluster {} - {}".format(name, msg)) - def update(self, name, k8s_cluster): + def update(self, name, k8s_cluster, wait=False): self._client.get_token() cluster = self.get(name) if "vim_account" in k8s_cluster: @@ -73,22 +98,28 @@ class K8scluster(object): k8s_cluster["vim_account"] = vim_account["_id"] if "vca" in vim_account: k8s_cluster["vca_id"] = vim_account["vca"] - http_code, resp = self._http.put_cmd( + http_code, resp = self._http.patch_cmd( endpoint="{}/{}".format(self._apiBase, cluster["_id"]), postfields_dict=k8s_cluster, ) - # print 'HTTP CODE: {}'.format(http_code) - # print 'RESP: {}'.format(resp) - # if http_code in (200, 201, 202, 204): - # pass - # else: - # msg = "" - # if resp: - # try: - # msg = json.loads(resp) - # except ValueError: - # msg = resp - # raise ClientException("failed to update K8s cluster {} - {}".format(name, msg)) + + if wait: + wait_id = cluster["_id"] + self._wait(wait_id, wait) + + self._logger.debug('HTTP CODE: {}'.format(http_code)) + self._logger.debug('RESP: {}'.format(resp)) + + if http_code in (200, 201, 202, 204): + print("Updated") + else: + msg = "" + if resp: + try: + msg = json.loads(resp) + except ValueError: + msg = resp + raise ClientException("failed to update K8s cluster {} - {}".format(name, msg)) def get_id(self, name): """Returns a K8s cluster id from a K8s cluster name""" @@ -97,7 +128,7 @@ class K8scluster(object): return cluster["_id"] raise NotFound("K8s cluster {} not found".format(name)) - def delete(self, name, force=False): + def delete(self, name, force=False, wait=False): self._client.get_token() cluster_id = name if not utils.validate_uuid4(name): @@ -108,10 +139,21 @@ class K8scluster(object): http_code, resp = self._http.delete_cmd( "{}/{}{}".format(self._apiBase, cluster_id, querystring) ) - # print 'HTTP CODE: {}'.format(http_code) - # print 'RESP: {}'.format(resp) + + self._logger.debug('HTTP CODE: {}'.format(http_code)) + self._logger.debug('RESP: {}'.format(resp)) + if http_code == 202: - print("Deletion in progress") + if wait: + wait_id = cluster_id + + if resp: + resp = json.loads(resp) + wait_id = resp.get("id") + + self._wait(wait_id, wait, deleteFlag=True) + else: + print("Deletion in progress") elif http_code == 204: print("Deleted") else: -- 2.17.1