TIMEOUT_VIM_OPERATION = TIMEOUT_GENERIC_OPERATION
TIMEOUT_WIM_OPERATION = TIMEOUT_GENERIC_OPERATION
TIMEOUT_NS_OPERATION = 3600
-
POLLING_TIME_INTERVAL = 1
-
MAX_DELETE_ATTEMPTS = 3
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']
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)
# 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:
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))
# 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:
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