def get_node_config(self): """ Get node configuration. :raises NetworkError: If there is a network connection issue while getting node configuration :raises Exception: If there is an HTTP issue while getting node config :return: Configuration of node on Success :rtype: dict """ log.info("Getting node config for node : " + self.__nodeid) path = 'user/nodes/config' query_parameters = 'nodeid=' + self.__nodeid getnodeconfig_url = serverconfig.HOST + path + '?' + query_parameters try: log.debug("Get node config request url : " + getnodeconfig_url) response = requests.get(url=getnodeconfig_url, headers=self.__request_header, verify=configmanager.CERT_FILE) log.debug("Get node config response : " + response.text) response.raise_for_status() except requests.exceptions.SSLError: raise SSLError except requests.exceptions.ConnectionError: raise NetworkError except Exception: raise Exception(response.text) log.info("Received node config successfully.") return response.json()
def claim_verify(claim_verify_data, header): claim_verify_url = CLAIM_VERIFY_URL user_whitelist_err_msg = ('User is not allowed to claim esp32 device.' ' please contact administrator') claim_verify_enc_data = str(claim_verify_data).replace("'", '"') log.debug("Claim Verify POST Request: url: " + claim_verify_url + "data: " + str(claim_verify_enc_data) + "headers: " + str(header) + "verify: " + CERT_FILE) claim_verify_response = requests.post(url=claim_verify_url, data=claim_verify_enc_data, headers=header, verify=CERT_FILE) if claim_verify_response.status_code != 200: claim_verify_response_json = json.loads( claim_verify_response.text.lower()) if (claim_verify_response_json["description"] in user_whitelist_err_msg): log.error('Claim verification failed.\n' + claim_verify_response.text) print('\nYour account isn\'t whitelisted for ESP32.' ' Please send your registered email address to' ' [email protected] for whitelisting') else: log.error('Claim verification failed.\n' + claim_verify_response.text) exit(0) print("Claim verify done") log.debug("Claim Verify POST Response: status code: " + str(claim_verify_response.status_code) + " and response text: " + claim_verify_response.text) log.info("Claim verify done") return claim_verify_response
def create_files_of_claim_info(dest_filedir, node_id, private_key, node_cert, endpointinfo, node_info_csv): """ Create files with claiming details :param dest_filedir: Destination File Directory :type port: str :param node_id: Node Id (data) to write to `node.info` file :type port: str :param private_key: Private Key (data) to write to `node.key` file :type port: bytes :param node_cert: Node Certificate (data) to write to `node.crt` file :type port: str :param endpointinfo: MQTT endpoint (data) to write to `endpoint.info` file :type port: str :param node_info_csv: List of output csv file details (node information) to write to `node_info.csv` file :type port: list :raises Exception: If there is any issue when writing to file :return: None on Success :rtype: None """ try: log.debug("Writing node info at location: " + dest_filedir + 'node.info') # Create files for each claim data - node info, node key, # node cert, endpoint info with open(dest_filedir + 'node.info', 'w+') as info_file: info_file.write(node_id) log.debug("Writing node info at location: " + dest_filedir + 'node.key') with open(dest_filedir + 'node.key', 'wb+') as info_file: info_file.write(private_key) log.debug("Writing node info at location: " + dest_filedir + 'node.crt') with open(dest_filedir + 'node.crt', 'w+') as info_file: info_file.write(node_cert) log.debug("Writing node info at location: " + dest_filedir + 'endpoint.info') with open(dest_filedir + 'endpoint.info', 'w+') as info_file: info_file.write(endpointinfo) log.debug("Writing node info at location: " + dest_filedir + 'node_info.csv') with open(dest_filedir + 'node_info.csv', 'w+') as info_file: for input_line in node_info_csv: info_file.write(input_line) info_file.write("\n") except Exception as file_error: raise file_error
def claim_initiate(claim_init_data, header): print("Claim initiate started") claim_initiate_url = CLAIM_INITIATE_URL try: # Claim Initiate Request log.info("Claim initiate started. Sending claim/initiate POST request") log.debug("Claim Initiate POST Request: url: " + claim_initiate_url + "data: " + str(claim_init_data) + "headers: " + str(header) + "verify: " + CERT_FILE) claim_initiate_response = requests.post(url=claim_initiate_url, data=claim_init_data, headers=header, verify=CERT_FILE) if claim_initiate_response.status_code != 200: log.error("Claim initiate failed.\n" + claim_initiate_response.text) exit(0) print("Claim initiate done") log.debug("Claim Initiate POST Response: status code: " + str(claim_initiate_response.status_code) + " and response text: " + claim_initiate_response.text) log.info("Claim initiate done") return claim_initiate_response except requests.exceptions.SSLError: raise SSLError except requests.ConnectionError: log.error("Please check the Internet connection.") exit(0)
def get_node_platform_and_mac(port): """ Get Node Platform and Mac Addres from device :param port: Serial Port :type port: str :return: Node Platform and MAC Address on Success :rtype: str """ if not port: sys.exit( "<port> argument not provided. Cannot read MAC address from node.") sys.stdout = mystdout = StringIO() command = ['--port', port, 'chip_id'] log.info("Running esptool command to get node\ platform and mac from device") esptool.main(command) sys.stdout = sys.__stdout__ # Finding chip type from output. node_platform = next( filter(lambda line: 'Detecting chip type' in line, mystdout.getvalue().splitlines())) # Finds the first occurence of the line # with the MAC Address from the output. mac = next( filter(lambda line: 'MAC: ' in line, mystdout.getvalue().splitlines())) mac_addr = mac.split('MAC: ')[1].replace(':', '').upper() platform = node_platform.split()[-1].lower().replace('-', '') print("Node platform detected is: ", platform) print("MAC address is: ", mac_addr) log.debug("MAC address received: " + mac_addr) log.debug("Node platform is: " + platform) return platform, mac_addr
def do_GET(self): """ Handle a GET request and writes the ESP Rainmaker Welcome HTML page(response) back to HTTP Client :raises Exception: If there is any File Handling Issue :return: None on Success and Failure :rtype: None """ log.debug('Loading the welcome page after successful login.') self.send_response(http_client.OK) self.send_header('Content-type', 'text/html') self.send_header('Access-Control-Allow-Origin', '*') self.end_headers() parts = urllib.parse.urlparse(self.path) query = _helpers.parse_unique_urlencoded(parts.query) self.server.query_params = query index_file = os.path.join(os.path.expanduser('.'), 'html/welcome.html') try: with open(index_file, 'rb') as home_page: self.wfile.write(home_page.read()) except Exception as file_err: log.error(file_err) sys.exit(1)
def check_status(node_object, request_id): status = None while True: log.debug('Checking user-node association status.') try: status = node_object.get_mapping_status(request_id) except Exception as mapping_status_err: log.error(mapping_status_err) return else: log.debug('User-node association status ' + status) if status == 'requested': print('Checking User Node association status - Requested\n' 'Retrying...') elif status == 'confirmed': print('Checking User Node association status - Confirmed') return elif status == 'timedout': print('Checking User Node association status - Timeout') return elif status == 'discarded': print('Checking User Node association status - Discarded') return time.sleep(5) return
def save_random_hex_str(dest_filedir, hex_str): """ Create file for random hex string and update node_info.csv :param dest_filedir: Destination File Directory :type dest_filedir: str :param hex_str: Random hex string to write :type hex_str: str :raises Exception: If there is any issue when writing to file :return: None on Success :rtype: None """ try: log.debug("Writing random hex string at location: " + dest_filedir + 'random.info') with open(dest_filedir + 'random.info', 'w+') as info_file: info_file.write(hex_str) with open(dest_filedir + 'node_info.csv', 'a') as info_file: info_file.write('random,file,hex2bin,' + dest_filedir + 'random.info') info_file.write('\n') except Exception as err: log.error(err)
def remove_node(vars=None): """ Removes the user node mapping. :param vars: `nodeid` as key - Node ID for the node, defaults to `None` :type vars: dict | None :raises NetworkError: If there is a network connection issue during HTTP request for removing node :raises Exception: If there is an HTTP issue while removing node or JSON format issue in HTTP response :return: None on Success :rtype: None """ log.info('Removing user node mapping for node ' + vars['nodeid']) try: n = node.Node(vars['nodeid'], session.Session()) params = n.remove_user_node_mapping() except Exception as remove_node_err: log.error(remove_node_err) else: log.debug('Removed the user node mapping successfully.') print('Removed node ' + vars['nodeid'] + ' successfully.') return
def get_password(): """ Get Password as input and perform basic password validation checks. :raises SystemExit: If there is an issue in getting password :return: Password for User on Success :rtype: str """ log.info('Doing basic password confirmation checks.') password_policy = '8 characters, 1 digit, 1 uppercase and 1 lowercase.' password_change_attempt = 0 print('Choose a password') while password_change_attempt < MAX_PASSWORD_CHANGE_ATTEMPTS: log.debug('Password change attempt number ' + str(password_change_attempt + 1)) password = getpass.getpass('Password : '******'Password should contain at least', password_policy) password_change_attempt += 1 continue confirm_password = getpass.getpass('Confirm Password : '******'Passwords do not match!\n' 'Please enter the password again ..') password_change_attempt += 1 log.error('Maximum attempts to change password over. Please try again.') sys.exit(1)
def signup(self, code): """ Sign up of new User for ESP Rainmaker. :param code: Verification code received in signup request for user :type code: int :raises NetworkError: If there is a network connection issue during signup :raises Exception: If there is an HTTP issue during signup :return: True on Success :rtype: bool """ log.info("Confirming user with username : "******"verification_code": code} signup_url = serverconfig.HOST + path try: log.debug("Confirm user request url : " + signup_url) response = requests.post(url=signup_url, data=json.dumps(signup_info), headers=self.__request_header, verify=configmanager.CERT_FILE) log.debug("Confirm user response : " + response.text) response.raise_for_status() except requests.exceptions.SSLError: raise SSLError except requests.exceptions.ConnectionError: raise NetworkError except Exception: raise Exception(response.text) log.info("Signup successful.") return True
def signup_request(self, password): """ Sign up request of new User for ESP Rainmaker. :param password: Password to set for new user :type password: str :raises NetworkError: If there is a network connection issue during signup request :raises Exception: If there is an HTTP issue during signup request :return: True on Success :rtype: bool """ log.info("Creating new user with username : "******"password": password} signup_url = serverconfig.HOST + path try: log.debug("Signup request url : " + signup_url) response = requests.post(url=signup_url, data=json.dumps(signup_info), headers=self.__request_header, verify=configmanager.CERT_FILE) log.debug("Signup request response : " + response.text) response.raise_for_status() except requests.exceptions.SSLError: raise SSLError except requests.exceptions.ConnectionError: raise NetworkError except Exception: raise Exception(response.text) log.info("Signup request sent successfully.") return True
def get_token_attribute(self, attribute_name, is_access_token=False): """ Get access token attributes. :params attribute_name: Attribute Name :type attribute_name: str :params is_access_token: Is Access Token :type is_access_token: bool :raises InvalidConfigError: If there is an error in the config :raises Exception: If there is a File Handling error while reading from/writing config to file :return: Attribute Value on Success, None on Failure :rtype: int | str | None """ if is_access_token: log.debug('Getting access token for attribute ' + attribute_name) _, _, token = self.get_config() else: log.debug('Getting idtoken for attribute ' + attribute_name) token, _, _ = self.get_config() token_payload = token.split('.')[1] if len(token_payload) % 4: token_payload += '=' * (4 - len(token_payload) % 4) try: str_token_payload = base64.b64decode(token_payload).decode("utf-8") attribute_value = json.loads(str_token_payload)[attribute_name] except Exception: raise InvalidConfigError if attribute_value is None: raise InvalidConfigError return attribute_value
def get_nodes(self): """ Get list of all nodes associated with the user. :raises NetworkError: If there is a network connection issue while getting nodes associated with user :raises Exception: If there is an HTTP issue while getting nodes :return: Nodes associated with user on Success :rtype: dict """ log.info("Getting nodes associated with the user.") path = 'user/nodes' getnodes_url = serverconfig.HOST + path try: log.debug("Get nodes request url : " + getnodes_url) response = requests.get(url=getnodes_url, headers=self.request_header, verify=configmanager.CERT_FILE) log.debug("Get nodes request response : " + response.text) response.raise_for_status() except requests.exceptions.SSLError: raise SSLError except requests.exceptions.ConnectionError: raise NetworkError except Exception: raise Exception(response.text) node_map = {} for nodeid in json.loads(response.text)['nodes']: node_map[nodeid] = node.Node(nodeid, self) log.info("Received nodes for user successfully.") return node_map
def get_service_params(self, service_config): """ Get params from service config to be used to check for the status of the service :param service_config: Service config of node :type service_config: dict :return: read params and write params on Success :type: dict,dict """ read_params = {} write_params = {} config_params = service_config["params"] log.debug( "Getting read and write properties params from service config: " + str(config_params)) for i in range(len(config_params)): cfg_type = config_params[i]["type"] cfg_props = config_params[i]["properties"] cfg_name = config_params[i]["name"] if 'read' in cfg_props: read_params[cfg_type] = cfg_name elif 'write' in cfg_props: write_params[cfg_type] = cfg_name return read_params, write_params
def create_mac_dir(creds_dir, mac_addr): # Create MAC directory mac_dir = Path(path.expanduser(str(creds_dir) + '/' + mac_addr)) os.makedirs(path.expanduser(mac_dir)) log.debug("Creating new directory " + str(mac_dir)) output_bin_filename = mac_addr + '.bin' dest_filedir = str(mac_dir) + '/' return dest_filedir, output_bin_filename
def get_mqtt_endpoint(): # Set node claim data sys.stdout = StringIO() log.info("Getting MQTT Host") endpointinfo = node.get_mqtt_host(None) log.debug("Endpoint info received: " + endpointinfo) sys.stdout = sys.__stdout__ return endpointinfo
def _check_user_input(node_ids_str): log.debug("Check user input....") # Check user input format input_pattern = re.compile("^[0-9A-Za-z]+(,[0-9A-Za-z]+)*$") result = input_pattern.match(node_ids_str) log.debug("User input result: {}".format(result)) if result is None: sys.exit("Invalid format. Expected: <nodeid>,<nodeid>,...") return True
def login(self, password=None): """ User login to the ESP Rainmaker. :param password: Password of user, defaults to `None` :type password: str :raises NetworkError: If there is a network connection issue during login :raises Exception: If there is an HTTP issue during login or JSON format issue in HTTP response :raises AuthenticationError: If login failed with the given parameters :return: :class:`rmaker_lib.session.Session` on Success :rtype: object """ log.info("User login with username : "******"Login request url : " + login_url) response = requests.post(url=login_url, data=json.dumps(login_info), headers=self.__request_header, verify=configmanager.CERT_FILE) log.debug("Login response : " + response.text) response.raise_for_status() except requests.exceptions.SSLError: raise SSLError except requests.exceptions.ConnectionError: raise NetworkError except Exception: raise Exception(response.text) try: result = json.loads(response.text) except Exception as json_decode_err: raise json_decode_err if 'status' in result and result['status'] == 'success': log.info("Login successful.") config_data = {} config_data['idtoken'] = result['idtoken'] config_data['refreshtoken'] = result['refreshtoken'] config_data['accesstoken'] = result['accesstoken'] configmanager.Config().set_config(config_data) return session.Session() raise AuthenticationError
def gen_nvs_partition_bin(dest_filedir, output_bin_filename): # Generate nvs args to be sent to NVS Partition Utility nvs_args = SimpleNamespace(input=dest_filedir + 'node_info.csv', output=output_bin_filename, size='0x6000', outdir=dest_filedir, version=2) # Run NVS Partition Utility to create binary of node info data print("\nGenerating NVS Partition Binary from claiming data: " + dest_filedir + output_bin_filename) log.debug("Generating NVS Partition Binary from claiming data: " + dest_filedir + output_bin_filename) nvs_partition_gen.generate(nvs_args)
def create_config_dir(): config = configmanager.Config() userid = config.get_user_id() creds_dir = Path( path.expanduser( str(Path(path.expanduser(configmanager.HOME_DIRECTORY))) + '/' + str(Path(path.expanduser(configmanager.CONFIG_DIRECTORY))) + '/claim_data/' + userid)) if not creds_dir.exists(): os.makedirs(path.expanduser(creds_dir)) log.debug("Creating new directory " + str(creds_dir)) return userid, creds_dir
def _display_status(json_resp): log.debug("Displaying status....") resp_keys = json_resp.keys() log.debug("Response keys: {}".format(resp_keys)) # Print status if 'status' in resp_keys: print("Status:", json_resp['status']) # Print error code if 'error_code' in resp_keys: print("Error", json_resp['error_code'], ": ", end='') # Print description if 'description' in resp_keys: print(json_resp['description'])
def login(vars=None): """ First time login of the user. :param vars: `email` as key - Email address of the user, defaults to `None` :type vars: dict :raises Exception: If there is any issue in login for user :return: None on Success and Failure :rtype: None """ log.info('Signing in the user. Username ' + str(vars['email'])) config = configmanager.Config() # Set email-id email_id = vars['email'] log.info('Logging in user: {}'.format(email_id)) # Check user current creds exist resp_filename = config.check_user_creds_exists() # If current creds exist, ask user for ending current session if resp_filename: # Get email-id of current logged-in user curr_email_id = config.get_token_attribute('email') log.info('Logging out user: {}'.format(curr_email_id)) # Get user input input_resp = config.get_input_to_end_session(curr_email_id) if not input_resp: return # Remove current login creds ret_val = config.remove_curr_login_creds(curr_creds_file=resp_filename) if ret_val is None: print("Failed to end previous login session. Exiting.") return else: log.debug("Current login creds not found at path: {}".format(resp_filename)) if vars['email'] is None: browser_login() return try: u = user.User(vars['email']) u.login() print('Login Successful') except Exception as login_err: log.error(login_err)
def start_ota(self, node_obj, node_params, service_name, service_write_params, url_to_set): """ Start OTA Service Set new url as node params :param node_obj: Node Object :type node_obj: object :param node_params: Node Params :type node_params: dict :param service_name: Service Name :type service_name: str :param url_to_set: New URL to set in node params :type url_to_set: str :return: True on Success, False on Failure :type: bool """ global start_time start_time = None ota_url_key = service_write_params[OTA_PARAMS['url']] log.debug("OTA URL Key : " + str(ota_url_key)) log.debug("Setting new url: " + str(url_to_set)) params_to_set = {service_name: {ota_url_key: url_to_set}} log.debug("New node params after setting url: " + json.dumps(params_to_set)) set_node_status = node_obj.set_node_params(params_to_set) if not set_node_status: return False start_time = time.time() log.debug("Start time set to: " + str(start_time)) print("OTA Upgrade Started. This may take time.") log.info("OTA Upgrade Started. This may take time.") return True
def get_user_details(self): """ Get details of current logged-in user :raises SSLError: If there is an SSL issue :raises HTTPError: If the HTTP response is an HTTPError :raises NetworkError: If there is a network connection issue :raises Timeout: If there is a timeout issue :raises RequestException: If there is an issue during the HTTP request :raises Exception: If there is an HTTP issue while getting user details or JSON format issue in HTTP response :return: HTTP response on Success :rtype: dict """ socket.setdefaulttimeout(10) log.info('Getting details of current logged-in user') version = serverconfig.VERSION path = '/user' getdetails_url = serverconfig.HOST.rstrip('/') + path try: log.debug("Get user details request url : " + getdetails_url) response = requests.get(url=getdetails_url, headers=self.request_header, verify=configmanager.CERT_FILE, timeout=(5.0, 5.0)) log.debug("Get user details request response : " + response.text) except requests.exceptions.HTTPError as http_err: log.debug(http_err) return json.loads(http_err.response.text) except requests.exceptions.SSLError: raise SSLError except requests.exceptions.ConnectionError: raise NetworkError except requests.exceptions.Timeout as time_err: log.debug(time_err) raise RequestTimeoutError except requests.exceptions.RequestException as req_err: log.debug(req_err) raise req_err except Exception: raise Exception(response.text) log.info("Received user details successfully.") try: return json.loads(response.text) except Exception as resp_err: raise resp_err
def __is_valid_version(self): """ Check if API Version is valid :raises NetworkError: If there is a network connection issue during HTTP request for getting version :raises Exception: If there is an HTTP issue or JSON format issue in HTTP response :return: True on Success, False on Failure :rtype: bool """ socket.setdefaulttimeout(10) log.info("Checking for supported version.") path = 'apiversions' request_url = serverconfig.HOST.split(serverconfig.VERSION)[0] + path try: log.debug("Version check request url : " + request_url) response = requests.get(url=request_url, verify=CERT_FILE, timeout=(5.0, 5.0)) log.debug("Version check response : " + response.text) response.raise_for_status() except requests.exceptions.SSLError: raise SSLError except requests.exceptions.Timeout: raise RequestTimeoutError except requests.exceptions.ConnectionError: raise NetworkError except Exception as ver_err: raise ver_err try: response = json.loads(response.text) except Exception as json_decode_err: raise json_decode_err if 'supported_versions' in response: supported_versions = response['supported_versions'] if serverconfig.VERSION in supported_versions: supported_versions.sort() latest_version = supported_versions[len(supported_versions) - 1] if serverconfig.VERSION < latest_version: print('Please check the updates on GitHub for newer' 'functionality enabled by ' + latest_version + ' APIs.') return True return False
def __get_new_token(self, username, refresh_token): """ Get new token for User Login Session :raises NetworkError: If there is a network connection issue during HTTP request for getting token :raises Exception: If there is an HTTP issue or JSON format issue in HTTP response :return: accesstoken and idtoken on Success, None on Failure :rtype: str | None """ socket.setdefaulttimeout(10) log.info("Extending user login session.") path = 'login' request_payload = { 'user_name': username, 'refreshtoken': refresh_token } request_url = serverconfig.HOST + path try: log.debug("Extend session url : " + request_url) response = requests.post(url=request_url, data=json.dumps(request_payload), verify=CERT_FILE, timeout=(5.0, 5.0)) response.raise_for_status() log.debug("Extend session response : " + response.text) except requests.exceptions.SSLError: raise SSLError except requests.exceptions.ConnectionError: raise NetworkError except requests.exceptions.Timeout: raise RequestTimeoutError except Exception: raise ExpiredSessionError try: response = json.loads(response.text) except Exception: raise ExpiredSessionError if 'accesstoken' in response and 'idtoken' in response: log.info("User session extended successfully.") return response['accesstoken'], response['idtoken'] return None
def set_params(vars=None): """ Set parameters of the node. :param vars: `nodeid` as key - Node ID for the node,\n `data` as key - JSON data containing parameters to be set `or`\n `filepath` as key - Path of the JSON file containing parameters to be set,\n defaults to `None` :type vars: dict | None :raises Exception: If there is an HTTP issue while setting params or JSON format issue in HTTP response :return: None on Success :rtype: None """ log.info('Setting params of the node with nodeid : ' + vars['nodeid']) data = vars['data'] filepath = vars['filepath'] if data is not None: log.debug('Setting node parameters using JSON data.') # Trimming white spaces except the ones between two strings data = re.sub( r"(?<![a-z]|[A-Z])\s(?![a-z]|[A-Z])|\ (?<=[a-z]|[A-Z])\s(?![a-z]|[A-Z])|\ (?<![a-z]|[A-Z])\s(?=[a-z]|[A-Z])", "", data) try: log.debug('JSON data : ' + data) data = json.loads(data) except Exception: raise InvalidJSONError return elif filepath is not None: log.debug('Setting node parameters using JSON file.') file = Path(filepath) if not file.exists(): log.error('File %s does not exist!' % file.name) return with open(file) as fh: try: data = json.load(fh) log.debug('JSON filename :' + file.name) except Exception: raise InvalidJSONError return try: n = node.Node(vars['nodeid'], session.Session()) status = n.set_node_params(data) except Exception as set_params_err: log.error(set_params_err) else: print('Node state updated successfully.') return
def get_mapping_status(self, request_id): """ Check status of user node mapping request. :param requestId: Request Id :type requestId: str :raises NetworkError: If there is a network connection issue while getting user node mapping status :raises Exception: If there is an HTTP issue while getting user node mapping status or JSON format issue in HTTP response :return: Request Status on Success, None on Failure :type: str | None """ log.info("Checking status of user node mapping with request_id : " + request_id) path = 'user/nodes/mapping' query_parameters = "&request_id=" + request_id request_url = serverconfig.HOST + path + '?' + query_parameters try: log.debug("Check user node mapping status request url : " + request_url) response = requests.get(url=request_url, headers=self.__request_header, verify=configmanager.CERT_FILE) log.debug("Check user node mapping status response : " + response.text) response.raise_for_status() except requests.exceptions.SSLError: raise SSLError except requests.exceptions.ConnectionError: raise NetworkError except Exception as mapping_status_err: raise mapping_status_err try: response = json.loads(response.text) except Exception as mapping_status_err: raise mapping_status_err if 'request_status' in response: return response['request_status'] return None
def remove_curr_login_creds(self, curr_creds_file=None): ''' Remove current login creds ''' log.info("Removing current login creds") if not curr_creds_file: curr_creds_file = os.path.expanduser(HOME_DIRECTORY + CONFIG_FILE) try: os.remove(curr_creds_file) log.info( "Previous login session ended. Removing current login creds...Success..." ) return True except Exception as e: log.debug( "Removing current login creds from path {}. Failed: {}".format( curr_creds_file, e)) return None