def validate_channel(channel_id): try: header = { "Authorization": f"Bearer {settings.block['access_token']}", "Accept": "application/json", } if not channel_id: logger.warning( f"[validate_channel] Invalid channel_id: {channel_id}") return {} url = f"{settings.api_server_full}/channels/{channel_id}" resp = requests.get(url, headers=header) if int(resp.status_code) == 200: return resp.json() else: logger.verbose( f"[validate_channel] Received response code [{resp.status_code}]" ) raise ChannelTemplateNotFound( f"Failed to retrieve channel_template_id for {channel_id}") except (OSError, ChannelTemplateNotFound) as e: logger.warning( f'[validate_channel] Error while making request to platform: {e}') except Exception: logger.alert( f"[validate_channel] Unexpected error get_channel_template: {traceback.format_exc(limit=5)}" ) return {}
def patch_endpoints(self): try: full_host = "{}://{}/{}".format(settings.schema_pub, settings.host_pub, settings.api_version) data = { "authorize": "{}/authorize".format(full_host), "receive_token": "{}/receive-token".format(full_host), "devices_list": "{}/devices-list".format(full_host), "select_device": "{}/select-device".format(full_host) } url = settings.webhook_url logger.debug("Initiated PATCH - {} {}".format( url, self.session.headers)) logger.verbose(format_str(data, is_json=True)) resp = requests.patch(url, data=json.dumps(data), headers=self.session.headers) logger.verbose( "[patch_endpoints] Received response code[{}]".format( resp.status_code)) logger.verbose(format_str(resp.json(), is_json=True)) self.set_confirmation_hash() except Exception: logger.alert("Failed at patch endpoints! {}".format( traceback.format_exc(limit=5))) raise
def validate_quote(quote_id): try: header = { "Authorization": f"Bearer {settings.block['access_token']}", "Accept": "application/json", } if not quote_id: logger.warning(f"[validate_quote] Invalid quote_id") return False url = f"{settings.api_server_full}/applications/{settings.client_id}/quotes/{quote_id}" resp = requests.get(url, headers=header) if int(resp.status_code) == 200: return resp.json() else: logger.verbose( f"[validate_quote] Received response code [{resp.status_code}]" ) raise InvalidRequestException( f"Failed to retrieve quote for {quote_id}") except (OSError, InvalidRequestException) as e: logger.warning( f'[validate_quote] Error while making request to platform: {e}') except Exception: logger.alert( f"[validate_quote] Unexpected error: {traceback.format_exc(limit=5)}" ) return False
def get_access(): """ To send authorization request with 0Auth2.0 to Muzzley platform """ logger.verbose("Trying to authorize with Muzzley...") data = { "client_id": settings.client_id, "client_secret": settings.client_secret, "response_type": settings.grant_type, "scope": settings.scope, "state": "active" } url = settings.auth_url try: logger.debug("Initiated POST - {}".format(url)) resp = requests.post(url, data=data) if resp.status_code == 200: logger.notice("Manager succesfully Authorized with Muzzley") store_info(resp.json()) start_refresher() else: error_msg = format_response(resp) raise Exception(error_msg) except Exception: logger.alert("Unexpected error during authorization {}".format( traceback.format_exc(limit=5))) raise
def start(self): """ If polling is enabled in config file, retrieves conf for polling in implementor """ try: if settings.config_polling.get('enabled') is True: logger.info('[Polling] **** starting polling ****') conf_data = self.implementer.get_polling_conf() if type(conf_data) is not list: conf_data = [conf_data] n_processes = settings.config_polling.get( 'requests_pool', DEFAULT_THREAD_MAX_WORKERS) self.pool_requests = ThreadPool(processes=n_processes) self.thread = threading.Thread(target=self.worker, args=[conf_data], name="Polling") self.thread.daemon = True self.thread.start() else: logger.info('[Polling] **** polling is not enabled ****') except NotImplementedError as e: logger.error("[Polling] NotImplementedError: {}".format(e)) except Exception: logger.alert( f"[Polling] Unexpected exception: {traceback.format_exc(limit=5)}" )
def patch_custom_endpoints(self): try: custom_endpoints = settings.custom_endpoints url = settings.webhook_url data = {'quote_actions': {}} for endpoint in custom_endpoints: data['quote_actions'].update({ endpoint['namespace']: f"{settings.schema_pub}://{settings.host_pub}/" f"{settings.api_version}{endpoint['uri']}" }) if data['quote_actions']: logger.debug(f"[patch_custom_endpoints] Initiated PATCH - {url}") logger.verbose("\n{}\n".format(json.dumps(data, indent=4, sort_keys=True))) resp = requests.patch(url, data=json.dumps(data), headers=self.session.headers) logger.verbose("[patch_{}] Received response code[{}]".format(endpoint['namespace'], resp.status_code)) logger.verbose("\n{}\n".format(json.dumps(resp.json(), indent=4, sort_keys=True))) if int(resp.status_code) == 200: logger.notice(f"[patch_custom_endpoints] {endpoint['namespace']} setup successful!") else: raise Exception(f"[patch_custom_endpoints] {endpoint['namespace']} setup not successful!") except Exception: logger.alert("Failed at patch endpoint! {}".format(traceback.format_exc(limit=5))) raise
def send_notification(self): try: from systemd.daemon import notify event = threading.Event() # send first notification on init logger.debug('[Watchdog]... everything is ok') notify('WATCHDOG=1') while not event.wait(self.interval - 1): main_thread_alive = threading.main_thread().is_alive() logger.debug( '[Watchdog] is alive {}'.format(main_thread_alive)) if main_thread_alive: logger.debug('[Watchdog]...') url = settings.config_http['bind'] resp = requests.get(url) if resp.status_code == 200: logger.debug('[Watchdog] everything is ok') notify('WATCHDOG=1') else: logger.warning( f'[Watchdog] Watchdog not sent. Response status: {resp.status_code}; ' f'Response: {resp.__dict__}') else: logger.critical(f'[Watchdog] Main thread is not alive.') except (KeyError, TypeError, ValueError): logger.info('[Watchdog] not enabled, keep_alive missing') except ImportError: logger.warn('[Watchdog] systemd not imported {}'.format( traceback.format_exc(limit=5))) except: logger.alert('[Watchdog] Unexpected exception {}'.format( traceback.format_exc(limit=5)))
def webhook_registration(self): try: if self.watchdog_monitor: self.watchdog_monitor.start() if self.watchdog_monitor.thread is None else \ logger.notice("Watchdog thread alive? : {}".format(self.watchdog_monitor.thread.is_alive())) self.implementer.start() except Exception: logger.alert("Unexpected exception {}".format(traceback.format_exc(limit=5))) os._exit(1)
def start(self): if self.interval is not None and self.interval > 0: try: self.thread = threading.Thread(target=self.send_notification, name="watchdog") self.thread.daemon = True self.thread.start() except: logger.alert('[Watchdog] Unexpected exception {}'.format( traceback.format_exc(limit=5))) else: logger.info('[Watchdog] not enabled, keep_alive missing or 0')
def get_application(self): try: logger.debug(f"[get_application] Trying to get application data - {settings.webhook_url}") resp = requests.get(settings.webhook_url, headers=self.session.headers) logger.verbose("[get_application] Received response code[{}]".format(resp.status_code)) if int(resp.status_code) == 200: logger.notice("[get_application] Get application successful!") return resp.json() else: raise Exception('[get_application] Error getting application!') except Exception: logger.alert("Failed while get application! {}".format(traceback.format_exc(limit=5))) raise
def launch_server(self): logger.notice('Starting TCP server') tcp_settings = settings.config_tcp if 'ip_address' not in self.tcp_settings or 'port' not in self.tcp_settings: raise TCPServerNotFoundException( "TCP server address or port not found in config file") # Create a TCP/IP socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Bind the socket to the port server_address = (self.tcp_settings['ip_address'], int(self.tcp_settings['port'])) logger.info( f'starting up on {server_address[0]} port {server_address[1]}') try: sock.bind(server_address) # Listen for incoming connections sock.listen(1) thread_list = [] while True: if len(thread_list) >= self.tcp_settings.get( 'thread_pool_limit', DEFAULT_TCP_POOL_LIMIT): self._clear_threads(thread_list) # Wait for a connection logger.info('Waiting for connection') connection, client_address = sock.accept() thread_ = threading.Thread(target=self.handle_connection, args=(connection, client_address)) thread_.start() thread_list.append(thread_) self._clear_threads(thread_list) except OSError as e: logger.critical( f"Error connecting TCP. Probably because address already in use. " f"Will try to reconnect in {self.retry_wait}; Error: {e}") except Exception as e: logger.alert( f"Unexpected error while open TCP socket: {e}; {traceback.format_exc(limit=5)}" ) finally: time.sleep(self.retry_wait) logger.warning("Recreating TCP server") self.kickoff()
def start(self): """ If refreshing token is enabled in config file, retrieves conf for refresh in implementor :return: """ try: if settings.config_refresh.get('enabled') is True: logger.info('[TokenRefresher] **** starting token refresher ****') self.thread = threading.Thread(target=self.worker, args=[self.implementer.get_refresh_token_conf()], name="TokenRefresh") self.thread.daemon = True self.thread.start() else: logger.info('[TokenRefresher] **** token refresher is not enabled ****') except NotImplementedError as e: logger.error("[TokenRefresher] NotImplementedError: {}".format(e)) except Exception: logger.alert("[TokenRefresher] Unexpected exception: {} {}".format(traceback.format_exc(limit=5)))
def patch_endpoints(self): try: _data = settings.services for _service in _data: try: if settings.config_boot.get('patch_services', True) is True: data = { 'activation_uri': '{}://{}/{}/services/{}/authorize'.format(settings.schema_pub, settings.host_pub, settings.api_version, _service['id']) } logger.debug("[patch_endpoints] Initiated PATCH - {}".format(_service.get('url'))) logger.verbose("\n{}\n".format(json.dumps(data, indent=4, sort_keys=True))) resp = requests.patch('{}/services/{}'.format(settings.api_server_full, _service['id']), data=json.dumps(data), headers=self.session.headers) logger.verbose("[patch_endpoints] Received response code[{}]".format(resp.status_code)) logger.verbose("\n{}\n".format(json.dumps(resp.json(), indent=4, sort_keys=True))) if int(resp.status_code) == 200: logger.notice("[patch_endpoints] Service setup successful!") else: raise Exception('Service setup not successful!') except Exception as e: logger.alert("[patch_endpoints] Failed to set service!\n{}".format(e)) os._exit(1) self.patch_custom_endpoints() self.set_confirmation_hash() except Exception: logger.alert("[patch_endpoints] Failed at patch endpoints! {}".format(traceback.format_exc(limit=5))) raise
def handle_connection(self, connection, client_address): logger.debug("[TCP] HANDLE_CONNECTION") try: conn_timeout = self.tcp_settings.get('connection_timeout', DEFAULT_CONNECTION_TIMEOUT) data_length = self.tcp_settings.get('data_length', DEFAULT_DATA_LENGTH) logger.debug(f'Connection from: {client_address}') # Receive the data in small chunks and retransmit it while True: connection.settimeout(int(conn_timeout)) data = connection.recv(data_length) logger.debug(f'TCP DATA received "{data}"') if data: result = self.handle_data(data) for res_ in result: logger.debug('Sending data back to the client') connection.sendall(res_.encode()) logger.debug(f'Data sent: {res_}') else: logger.debug(f'no more data from: {client_address}') break except socket.timeout: logger.debug( f'No response from {client_address}. Connection will close') connection.sendall('Closing connection due to inactivity'.encode()) except TCPWrongMessageException as e: connection.sendall(e.__str__().encode()) except Exception: logger.alert( f'Unexpected error from {connection}; address: {client_address}; ' f'{traceback.format_exc(limit=5)}') finally: logger.debug("Closing connection") # Clean up the connection connection.close()
def renew_token(): logger.verbose("Trying to refresh Tokens...") url = settings.renew_url header = {"Content-Type": "application/json"} data = { "client_id": settings.client_id, "refresh_token": settings.block['refresh_token'], "grant_type": settings.grant_type } try: logger.debug("Initiated POST - {}".format(url)) resp = requests.get(url, params=data, headers=header) if resp.status_code == 200: logger.notice("Manager succesfully performed Token refresh") store_info(resp.json()) start_refresher() else: error_msg = format_response(resp) raise Exception(error_msg) except Exception: logger.alert("Unexpected error during token renewal: {}".format( traceback.format_exc(limit=5))) os._exit(1)
def mqtt_config(self): logger.info("Setting up Mqtt connection") try: parts = settings.block["mqtt_ep"].split(":") schema_mqtt = parts[0] host = parts[1].replace("//", "") port = int(parts[2]) self.mqtt_client.username_pw_set(username=self.client_id, password=self.access_token) try: logger.debug("mqtt_client._ssl = {}".format( self.mqtt_client._ssl)) if not self.mqtt_client._ssl and schema_mqtt == "mqtts": logger.debug("Will set tls") self.mqtt_client.tls_set(ca_certs=settings.cert_path) except Exception: logger.alert( "Mqtt - Failed to authenticate SSL certificate, {}".format( traceback.format_exc(limit=5))) raise self.mqtt_client.connect(host, port) logger.debug( "Mqtt - Did start connect w/ host:{} and port:{}".format( host, port)) except Exception: logger.emergency("Unexpected error: {}".format( traceback.format_exc(limit=5))) raise
(rc, mid) = self.mqtt_client.publish(topic=topic, payload=json.dumps(payload)) if rc == 0: logger.info( "Mqtt - Published successfully, result code({}) and mid({}) to topic: {} with payload:{}" .format(rc, mid, topic, format_str(payload, is_json=True))) else: raise Exception( "Mqtt - Failed to publish , result code({})".format(rc)) except Exception as e: logger.alert("Mqtt - Failed to publish , ex {}".format(e)) def mqtt_decongif(self): try: self.mqtt_client.unsubscribe( "/{api_version}/managers/{client_id}/channels/#".format( api_version=settings.api_version, client_id=settings.client_id)) self.mqtt_client.loop_stop() self.mqtt_client.disconnect() self.mqtt_client.disable_logger() except Exception: logger.error("Mqtt - Failed to de-configure connection {}".format( traceback.format_exc(limit=5))) os._exit(1)