X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=osmclient%2Fcommon%2Fwait.py;h=e3152af145cbe8cdbd4636d452ae115c46c45b88;hb=refs%2Fchanges%2F87%2F7887%2F3;hp=9610856cc98587cf34b9918d576d2093bf82a2bc;hpb=5da3f209f7595167bf762e71236076a637244c49;p=osm%2Fosmclient.git diff --git a/osmclient/common/wait.py b/osmclient/common/wait.py index 9610856..e3152af 100644 --- a/osmclient/common/wait.py +++ b/osmclient/common/wait.py @@ -28,11 +28,10 @@ TIMEOUT_GENERIC_OPERATION = 600 TIMEOUT_NSI_OPERATION = TIMEOUT_GENERIC_OPERATION TIMEOUT_SDNC_OPERATION = TIMEOUT_GENERIC_OPERATION TIMEOUT_VIM_OPERATION = TIMEOUT_GENERIC_OPERATION +TIMEOUT_K8S_OPERATION = TIMEOUT_GENERIC_OPERATION TIMEOUT_WIM_OPERATION = TIMEOUT_GENERIC_OPERATION TIMEOUT_NS_OPERATION = 3600 - -POLLING_TIME_INTERVAL = 1 - +POLLING_TIME_INTERVAL = 5 MAX_DELETE_ATTEMPTS = 3 def _show_detailed_status(old_detailed_status, new_detailed_status): @@ -44,11 +43,11 @@ def _show_detailed_status(old_detailed_status, new_detailed_status): def _get_finished_states(entity): # Note that the member name is either: - # 'operationState' (NS and NSI) - # '_admin.'operationalState' (other) + # 'operationState' (NS, NSI) + # '_admin.'operationalState' (VIM, WIM, SDN) # For NS and NSI, 'operationState' may be one of: # PROCESSING, COMPLETED,PARTIALLY_COMPLETED, FAILED_TEMP,FAILED,ROLLING_BACK,ROLLED_BACK - # For other entities, '_admin.operationalState' may be one of: + # For VIM, WIM, SDN: '_admin.operationalState' may be one of: # operationalState: ENABLED, DISABLED, ERROR, PROCESSING if entity == 'NS' or entity == 'NSI': return ['COMPLETED', 'PARTIALLY_COMPLETED', 'FAILED_TEMP', 'FAILED'] @@ -66,7 +65,7 @@ def _get_operational_state(resp, entity): return resp.get('_admin', {}).get('operationalState') def _op_has_finished(resp, entity): - # _op_has_finished() returns: + # This function returns: # 0 on success (operation has finished) # 1 on pending (operation has not finished) # -1 on error (bad response) @@ -87,8 +86,24 @@ def _get_detailed_status(resp, entity, detailed_status_deleted): # For NS and NSI, 'detailed-status' is a JSON "root" member: return resp.get('detailed-status') else: - # For other entities, 'detailed-status' a leaf node to '_admin': - return resp.get('_admin', {}).get('detailed-status') + # For VIM, WIM, SDN, 'detailed-status' is either: + # - a leaf node to '_admin' (operations NOT supported) + # - a leaf node of the Nth element in the list '_admin.operations[]' (operations supported by LCM and NBI) + # https://osm.etsi.org/gerrit/#/c/7767 : LCM support for operations + # https://osm.etsi.org/gerrit/#/c/7734 : NBI support for current_operation + ops = resp.get('_admin', {}).get('operations') + op_index = resp.get('_admin', {}).get('current_operation') + if ops and op_index: + # Operations are supported, verify operation index + if isinstance(op_index, (int)) or op_index.isdigit(): + op_index = int(op_index) + if op_index > 0 and op_index < len(ops) and ops[op_index] and ops[op_index]["detailed-status"]: + return ops[op_index]["detailed-status"] + # operation index is either non-numeric or out-of-range + return 'Unexpected error when getting detailed-status!' + else: + # Operations are NOT supported + return resp.get('_admin', {}).get('detailed-status') def _has_delete_error(resp, entity, deleteFlag, delete_attempts_left): if deleteFlag and delete_attempts_left: @@ -113,20 +128,25 @@ def wait_for_status(entity_label, entity_id, timeout, apiUrlStatus, http_cmd, de detailed_status_deleted = None time_to_return = False delete_attempts_left = MAX_DELETE_ATTEMPTS + wait_for_404 = False try: while True: http_code, resp_unicode = http_cmd('{}/{}'.format(apiUrlStatus, entity_id)) resp = '' if resp_unicode: resp = json.loads(resp_unicode) - # print 'HTTP CODE: {}'.format(http_code) - # print 'RESP: {}'.format(resp) - # print 'URL: {}/{}'.format(apiUrlStatus, entity_id) + # print('HTTP CODE: {}'.format(http_code)) + # print('RESP: {}'.format(resp)) + # print('URL: {}/{}'.format(apiUrlStatus, entity_id)) if deleteFlag and http_code == 404: # In case of deletion, '404 Not Found' means successfully deleted # Display 'detailed-status: Deleted' and return time_to_return = True detailed_status_deleted = 'Deleted' + elif deleteFlag and http_code in (200, 201, 202, 204): + # In case of deletion and HTTP Status = 20* OK, deletion may be PROCESSING or COMPLETED + # If this is the case, we should keep on polling until 404 (deleted) is returned. + wait_for_404 = True elif http_code not in (200, 201, 202, 204): raise ClientException(str(resp)) if not time_to_return: @@ -148,12 +168,14 @@ def wait_for_status(entity_label, entity_id, timeout, apiUrlStatus, http_cmd, de else: # Operation has finished, either with success or error if deleteFlag: - if delete_attempts_left < MAX_DELETE_ATTEMPTS: - time_to_return = True delete_attempts_left -= 1 + if not wait_for_404 and delete_attempts_left < MAX_DELETE_ATTEMPTS: + time_to_return = True else: time_to_return = True new_detailed_status = _get_detailed_status(resp, entity_label, detailed_status_deleted) + # print('DETAILED-STATUS: {}'.format(new_detailed_status)) + # print('DELETE-ATTEMPTS-LEFT: {}'.format(delete_attempts_left)) if not new_detailed_status: new_detailed_status = 'In progress' # TODO: Change LCM to provide detailed-status more up to date @@ -172,5 +194,5 @@ def wait_for_status(entity_label, entity_id, timeout, apiUrlStatus, http_cmd, de except ClientException as exc: message="Operation failed for {}:\nerror:\n{}".format( entity_label, - exc.message) + str(exc)) raise ClientException(message)