def resolve_entity(self, entity_id: str, entity_type_id: str = None) -> DefEntity: # noqa: E501 """Resolve the entity. Validates the entity against the schema. Based on the result, entity state will be either changed to "RESOLVED" (or) "RESOLUTION ERROR". :param str entity_id: Id of the entity :return: Defined entity with its state updated. :rtype: DefEntity """ if not entity_type_id: rde: DefEntity = self.get_entity(entity_id) entity_type_id = rde.entityType response_body = self._cloudapi_client.do_request( method=RequestMethod.POST, cloudapi_version=CloudApiVersion.VERSION_1_0_0, resource_url_relative_path=f"{CloudApiResource.ENTITIES}/" f"{entity_id}/{CloudApiResource.ENTITY_RESOLVE}") # noqa: E501 msg = response_body[def_constants.DEF_ERROR_MESSAGE_KEY] del response_body[def_constants.DEF_ERROR_MESSAGE_KEY] entity = DefEntity(entityType=entity_type_id, **response_body) # TODO: Just record the error message; revisit after HTTP response code # is good enough to decide if exception should be thrown or not if entity.state != def_constants.DEF_RESOLVED_STATE: LOGGER.error(msg) return entity
def process_behavior_request(msg_json, mqtt_publisher: MQTTPublisher): # Extracting contents from headers task_id: str = msg_json['headers']['taskId'] entity_id: str = msg_json['headers']['entityId'] behavior_id: str = msg_json['headers']['behaviorId'] usr_ctx: BehaviorUserContext = BehaviorUserContext(**msg_json['headers']['context']) # noqa: E501 # Extracting contents from the input payload payload: dict = json.loads(msg_json['payload']) entity: dict = payload['entity'] entity_type_id: str = payload['typeId'] api_version: str = payload['_metadata']['apiVersion'] # This is needed to enable unified API endpoint workflows. Unified API # endpoint is currently exposed at 37.0.0-alpha (VCD 10.3 Andromeda). if api_version == API_VERSION_37_ALPHA: api_version = ApiVersion.VERSION_36.value auth_token: str = payload['_metadata']['actAsToken'] request_id: str = payload['_metadata']['requestId'] arguments: dict = payload['arguments'] # Initializing Behavior operation context op_ctx = OperationContext(auth_token=auth_token, request_id=request_id) # noqa: E501 behavior_ctx = RequestContext( behavior_id=behavior_id, task_id=task_id, entity_id=entity_id, payload=payload, api_version=float(api_version), entity=entity, user_context=usr_ctx, entity_type_id=entity_type_id, request_id=request_id, op_ctx=op_ctx, mqtt_publisher=mqtt_publisher, arguments=arguments ) # Invoke the handler method and return the response in the string format. try: return MAP_BEHAVIOR_ID_TO_HANDLER_METHOD[behavior_id](behavior_ctx) except CseRequestError as e: error_details = asdict(BehaviorError(majorErrorCode=e.status_code, minorErrorCode=e.minor_error_code, message=e.error_message)) payload = mqtt_publisher. \ construct_behavior_payload(status=BehaviorTaskStatus.ERROR.value, error_details=error_details) LOGGER.error(f"Error while executing handler: {error_details}", exc_info=True) # noqa: E501 return payload except Exception as e: error_details = asdict(BehaviorError(majorErrorCode='500', message=str(e))) payload = mqtt_publisher. \ construct_behavior_payload(status=BehaviorTaskStatus.ERROR.value, error_details=error_details) LOGGER.error(f"Error while executing handler: {error_details}", exc_info=True) # noqa: E501 return payload
def get_request_id(request_msg, fsencoding): """.""" request_id = None try: msg_json = json.loads(request_msg.decode(fsencoding))[0] request_id = msg_json['id'] except Exception: LOGGER.error(traceback.format_exc()) return request_id
def exception_handler_wrapper(*args, **kwargs): try: result = func(*args, **kwargs) except (KeyError, TypeError, ValueError) as error: LOGGER.error(error) raise cse_exception.BadRequestError(error_message=str(error)) except Exception as error: LOGGER.error(error) raise error return result
def exception_handler_wrapper(*args, **kwargs): try: result = func(*args, **kwargs) except (KeyError, TypeError, ValueError) as error: LOGGER.error(error) raise cse_exception.BadRequestError(error_message=str(error)) except Exception as error: LOGGER.error(error) if not isinstance(error, cse_exception.CseRequestError): raise cse_exception.InternalServerRequestError( error_message=str(error)) # noqa: E501 raise error return result
def connect(self): def on_connect(mqtt_client, userdata, flags, rc): LOGGER.info(f'MQTT client connected with result code {rc} and ' f'flags {flags}') mqtt_client.subscribe(self.listen_topic, qos=constants.QOS_LEVEL) def on_message(mqtt_client, userdata, msg): # No longer processing messages if server is closing if self._is_closing: return msg_json = json.loads(msg.payload.decode(self.fsencoding)) if msg_json['type'] == 'BEHAVIOR_INVOCATION': if self._behavior_tpe.max_threads_busy(): # TODO Find out from Extensibility on what is recommended. self.send_too_many_requests_response(msg) else: self._behavior_tpe.submit( lambda: self.process_behavior_message(msg_json=msg_json )) # noqa: E501 elif self._ctpe.max_threads_busy(): self.send_too_many_requests_response(msg) else: self._ctpe.submit(lambda: self.process_mqtt_message(msg)) def on_subscribe(mqtt_client, userdata, msg_id, given_qos): LOGGER.info(f'MQTT client subscribed with given_qos: {given_qos}') def on_disconnect(mqtt_client, userdata, rc): LOGGER.info(f'MQTT disconnect with reason: {rc}') self._mqtt_client = mqtt.Client(client_id=constants.MQTT_CLIENT_ID, transport=constants.TRANSPORT_WSS) self._mqtt_client.username_pw_set(username=self.client_username, password=self.token) cert_req = ssl.CERT_REQUIRED if self.verify_ssl else ssl.CERT_NONE self._mqtt_client.tls_set(cert_reqs=cert_req) self._mqtt_client.ws_set_options(path=constants.MQTT_BROKER_PATH) # Setup callbacks self._mqtt_client.on_connect = on_connect self._mqtt_client.on_message = on_message self._mqtt_client.on_disconnect = on_disconnect self._mqtt_client.on_subscribe = on_subscribe try: self._mqtt_client.connect(self.url, port=constants.MQTT_CONNECT_PORT) except Exception as e: LOGGER.error(f'MQTT client connection error: {e}') raise self._mqtt_client.loop_forever()
def exception_handler_wrapper(*args, **kwargs): try: result = func(*args, **kwargs) except HTTPError as error: response_dict = json.loads(error.response.text) error_message = response_dict.get('message') LOGGER.error(error_message) raise cse_exception.DefEntityServiceError( error_message=error_message, minor_error_code=MinorErrorCode.DEFAULT_ERROR_CODE) except Exception as error: LOGGER.error(error) raise error return result
def connect(self): def on_connect(mqtt_client, userdata, flags, rc): LOGGER.info(f'MQTT client connected with result code {rc} and ' f'flags {flags}') mqtt_client.subscribe(self.listen_topic, qos=constants.QOS_LEVEL) def on_message(mqtt_client, userdata, msg): # No longer processing messages if server is closing if self._is_closing: return if self._ctpe.max_threads_busy(): self.send_too_many_requests_response(msg) else: self._ctpe.submit(lambda: self.process_mqtt_message(msg)) def on_subscribe(mqtt_client, userdata, msg_id, given_qos): LOGGER.info(f'MQTT client subscribed with given_qos: {given_qos}') def on_disconnect(mqtt_client, userdata, rc): LOGGER.info(f'MQTT disconnect with reason: {rc}') self._mqtt_client = mqtt.Client(client_id=constants.MQTT_CLIENT_ID, transport=constants.TRANSPORT_WSS) self._mqtt_client.username_pw_set(username=self.client_username, password=self.token) cert_req = ssl.CERT_REQUIRED if self.verify_ssl else ssl.CERT_NONE self._mqtt_client.tls_set(cert_reqs=cert_req) self._mqtt_client.ws_set_options(path=constants.MQTT_BROKER_PATH) # Setup callbacks self._mqtt_client.on_connect = on_connect self._mqtt_client.on_message = on_message self._mqtt_client.on_disconnect = on_disconnect self._mqtt_client.on_subscribe = on_subscribe # Set the mqtt publisher self._mqtt_publisher = MQTTPublisher(mqtt_client=self._mqtt_client, respond_topic=self.respond_topic, fsencoding=self.fsencoding) try: self._mqtt_client.connect(self.url, port=constants.MQTT_CONNECT_PORT) except Exception as e: LOGGER.error(f'MQTT client connection error: {e}') raise self._mqtt_client.loop_forever()
def _form_updated_entity(self, entity_id: str, changes: dict): entity = self.get_entity(entity_id) # get entity call updates _cloudapi_client headers to get etag etag = self._cloudapi_client.get_last_response_etag() # form updated RDE for attr_str, value in changes.items(): curr_obj = entity attrs: list = attr_str.split('.') last_attr: str = attrs.pop() for attr in attrs: try: curr_obj = getattr(curr_obj, attr) except AttributeError as err: LOGGER.error( f"missing attribute [{attr}] in [{attr_str}] when updating RDE: {err}" ) # noqa: E501 raise setattr(curr_obj, last_attr, value) return entity, etag
def get_response_fields(request_msg, fsencoding, is_mqtt): """Get the msg json and response fields request message.""" msg_json, request_id = None, None try: # Parse the message if is_mqtt: payload_json = json.loads(request_msg.payload.decode(fsencoding)) http_req_json = json.loads( base64.b64decode(payload_json['httpRequest'])) request_id = payload_json["headers"]["requestId"] msg_json = http_req_json['message'] # Use api access token as authorization token -- this may involve # overwriting the current authorization token msg_json['headers']['Authorization'] = \ 'Bearer ' + http_req_json['securityContext']['apiAccessToken'] else: msg_json = json.loads(request_msg.decode(fsencoding))[0] request_id = msg_json['id'] thread_local_data.set_thread_local_data(ThreadLocalData.REQUEST_ID, request_id) # noqa: E501 thread_local_data.set_thread_local_data( ThreadLocalData.USER_AGENT, msg_json['headers'].get('User-Agent')) # noqa: E501 result = request_dispatcher.process_request(msg_json) status_code = result['status_code'] reply_body = result['body'] except Exception as e: if isinstance(e, CseRequestError): status_code = e.status_code else: status_code = requests.codes.internal_server_error reply_body = {RESPONSE_MESSAGE_KEY: str(e)} tb = traceback.format_exc() LOGGER.error(tb) return msg_json, reply_body, status_code, request_id
def _get_cluster_and_broker(request_data, op_ctx, **kwargs): cluster_name = request_data[RequestKey.CLUSTER_NAME] pks_ctx_list = create_pks_context_for_all_accounts_in_org(op_ctx) for pks_ctx in pks_ctx_list: debug_msg = f"Get cluster info for cluster '{cluster_name}' " \ f"failed on host '{pks_ctx['host']}' with error: " pks_broker = PksBroker(pks_ctx, op_ctx) try: return pks_broker.get_cluster_info( data=request_data, **kwargs), pks_broker # noqa: E501 except (PksClusterNotFoundError, PksServerError) as err: # continue searching using other PksBrokers LOGGER.debug(f"{debug_msg}{err}") except PksDuplicateClusterError as err: # fail because multiple clusters with same name exist LOGGER.debug(f"{debug_msg}{err}") raise except Exception as err: LOGGER.error(f"Unknown error: {err}", exc_info=True) raise # raised if cluster was not found in PksBrokers raise ClusterNotFoundError(f"Cluster '{cluster_name}' not found.")