mirror of
https://github.com/espressif/esp-rainmaker.git
synced 2026-01-19 09:45:35 +00:00
cli-provisioning: Fixed connectivity and import checks
Added checks and fixed error handling for poor internet connectivity Fixed error handling checks while importing modules Fixed mock imports in docs
This commit is contained in:
@@ -14,22 +14,22 @@
|
||||
|
||||
import uuid
|
||||
import time
|
||||
from packaging import version
|
||||
import sys
|
||||
|
||||
try:
|
||||
from rmaker_lib.logger import log
|
||||
from rmaker_lib import session, configmanager, node
|
||||
from rmaker_lib.exceptions import NetworkError, SSLError
|
||||
except ImportError as err:
|
||||
print("Failed to import ESP Rainmaker library. " + str(err))
|
||||
raise err
|
||||
|
||||
MINIMUM_PROTOBUF_VERSION = '3.10.0'
|
||||
TRANSPORT_MODE_SOFTAP = 'softap'
|
||||
MAX_HTTP_CONNECTION_RETRIES = 5
|
||||
PROVISION_FAILURE_MSG = 'Provisioning Failed. Reset your board to factory'
|
||||
'defaults and retry.'
|
||||
PROVISION_FAILURE_MSG = ('Provisioning Failed. Reset your board to factory '
|
||||
'defaults and retry.')
|
||||
|
||||
try:
|
||||
from rmaker_tools.rmaker_prov.esp_rainmaker_prov import provision_device
|
||||
from rmaker_lib.logger import log
|
||||
from rmaker_lib import session, configmanager, node
|
||||
from rmaker_lib.exceptions import NetworkError, SSLError,\
|
||||
RequestTimeoutError
|
||||
except ImportError as err:
|
||||
print("Failed to import ESP Rainmaker library.\n" + str(err))
|
||||
raise err
|
||||
|
||||
|
||||
def provision(vars=None):
|
||||
@@ -46,19 +46,6 @@ def provision(vars=None):
|
||||
:return: None on Success and Failure
|
||||
:rtype: None
|
||||
"""
|
||||
try:
|
||||
from rmaker_tools.rmaker_prov.esp_rainmaker_prov\
|
||||
import provision_device
|
||||
except ImportError as err:
|
||||
import google.protobuf
|
||||
if version.parse(google.protobuf.__version__)\
|
||||
< version.parse(MINIMUM_PROTOBUF_VERSION):
|
||||
log.warn('Package protobuf does not satisfy\
|
||||
the minimum required version.\n'
|
||||
'Minimum required version is ' + MINIMUM_PROTOBUF_VERSION)
|
||||
else:
|
||||
log.error('Provisioning failed due to import error.', err)
|
||||
raise err
|
||||
log.info('Provisioning the node.')
|
||||
secret_key = str(uuid.uuid4())
|
||||
pop = vars['pop']
|
||||
@@ -78,14 +65,14 @@ def provision(vars=None):
|
||||
|
||||
node_id = provision_device(TRANSPORT_MODE_SOFTAP, pop, userid, secret_key)
|
||||
if node_id is None:
|
||||
print(PROVISION_FAILURE_MSG)
|
||||
log.error(PROVISION_FAILURE_MSG)
|
||||
return
|
||||
log.debug('Node ' + node_id + ' provisioned successfully.')
|
||||
|
||||
print('------------------------------------------')
|
||||
input('Please ensure host machine is connected to internet and'
|
||||
input('Please ensure host machine is connected to internet and '
|
||||
'Press Enter to continue...')
|
||||
print('Adding User-Node association...')
|
||||
|
||||
retries = MAX_HTTP_CONNECTION_RETRIES
|
||||
node_object = None
|
||||
while retries > 0:
|
||||
@@ -95,90 +82,120 @@ def provision(vars=None):
|
||||
node_object = node.Node(node_id, session.Session())
|
||||
except SSLError:
|
||||
log.error(SSLError())
|
||||
print(PROVISION_FAILURE_MSG)
|
||||
return
|
||||
except NetworkError:
|
||||
time.sleep(5)
|
||||
log.warn("Session is expired. Initialising new session.")
|
||||
pass
|
||||
break
|
||||
except (NetworkError, RequestTimeoutError) as conn_err:
|
||||
print(conn_err)
|
||||
log.warn(conn_err)
|
||||
except Exception as node_init_err:
|
||||
log.error(node_init_err)
|
||||
print(PROVISION_FAILURE_MSG)
|
||||
return
|
||||
break
|
||||
else:
|
||||
break
|
||||
time.sleep(5)
|
||||
retries -= 1
|
||||
if retries:
|
||||
print("Retries left:", retries)
|
||||
log.info("Retries left: " + str(retries))
|
||||
|
||||
if node_object is None:
|
||||
print('Please check the internet connectivity.')
|
||||
print(PROVISION_FAILURE_MSG)
|
||||
log.error('Initialising new session...Failed\n' +
|
||||
'\n' + PROVISION_FAILURE_MSG)
|
||||
return
|
||||
|
||||
print('\nAdding User-Node association')
|
||||
log.info("Adding User-Node association")
|
||||
|
||||
retries = MAX_HTTP_CONNECTION_RETRIES
|
||||
request_id = None
|
||||
log.info('Sending User-Node Association Request...')
|
||||
while retries > 0:
|
||||
print('Sending User-Node Association Request...')
|
||||
try:
|
||||
log.debug('Adding user-node association.')
|
||||
request_id = node_object.add_user_node_mapping(secret_key)
|
||||
except SSLError:
|
||||
log.error(SSLError())
|
||||
print(PROVISION_FAILURE_MSG)
|
||||
return
|
||||
except Exception as user_node_mapping_err:
|
||||
print('Sending User-Node association request to '
|
||||
'ESP RainMaker Cloud - Failed\nRetrying...')
|
||||
log.warn(user_node_mapping_err)
|
||||
pass
|
||||
break
|
||||
except (NetworkError, RequestTimeoutError) as conn_err:
|
||||
print(conn_err)
|
||||
log.warn(conn_err)
|
||||
except Exception as mapping_err:
|
||||
print(mapping_err)
|
||||
log.warn(mapping_err)
|
||||
break
|
||||
else:
|
||||
if request_id is not None:
|
||||
log.debug('User-node mapping added successfully'
|
||||
'with request_id'
|
||||
log.debug('User-Node mapping added successfully '
|
||||
'with request_id '
|
||||
+ request_id)
|
||||
break
|
||||
time.sleep(5)
|
||||
|
||||
retries -= 1
|
||||
if retries:
|
||||
print("Retries left:", retries)
|
||||
log.info("Retries left: " + str(retries))
|
||||
time.sleep(5)
|
||||
|
||||
if request_id is None:
|
||||
print('Sending User-Node association request to'
|
||||
'ESP RainMaker Cloud - Failed')
|
||||
print(PROVISION_FAILURE_MSG)
|
||||
log.error('User-Node Association Request...Failed\n' +
|
||||
'\n' + PROVISION_FAILURE_MSG)
|
||||
return
|
||||
print('Sending User-Node association request to'
|
||||
'ESP RainMaker Cloud - Successful')
|
||||
|
||||
print('User-Node Association Request...Success')
|
||||
log.info('User-Node Association Request...Success')
|
||||
|
||||
retries = MAX_HTTP_CONNECTION_RETRIES
|
||||
status = None
|
||||
while True:
|
||||
log.debug('Checking user-node association status.')
|
||||
log.info('Checking User-Node Association Status...')
|
||||
while retries > 0:
|
||||
print('Checking User-Node Association Status...')
|
||||
try:
|
||||
status = node_object.get_mapping_status(request_id)
|
||||
except SSLError:
|
||||
log.error(SSLError())
|
||||
print(PROVISION_FAILURE_MSG)
|
||||
return
|
||||
break
|
||||
except (NetworkError, RequestTimeoutError) as conn_err:
|
||||
print(conn_err)
|
||||
log.warn(conn_err)
|
||||
status = None
|
||||
except Exception as mapping_status_err:
|
||||
print(mapping_status_err)
|
||||
log.warn(mapping_status_err)
|
||||
pass
|
||||
break
|
||||
else:
|
||||
log.debug('User-node association status ' + status)
|
||||
if status == 'requested':
|
||||
print('Checking User Node association status -'
|
||||
'Requested\nRetrying...')
|
||||
print('User-Node Association Status - Requested'
|
||||
'\n')
|
||||
log.debug('User-Node Association Status - Requested'
|
||||
'\n')
|
||||
elif status == 'confirmed':
|
||||
print('Checking User Node association status - Confirmed')
|
||||
print('Provisioning was Successful.')
|
||||
return
|
||||
print('User-Node Association Status - Confirmed'
|
||||
'\nProvisioning was Successful.')
|
||||
log.debug('User-Node Association Status - Confirmed'
|
||||
'\nProvisioning was Successful.')
|
||||
break
|
||||
elif status == 'timedout':
|
||||
print('Checking User Node association status - Timeout')
|
||||
print(PROVISION_FAILURE_MSG)
|
||||
return
|
||||
print('User-Node Association Status - Timedout')
|
||||
log.debug('User-Node Association Status - Timedout')
|
||||
break
|
||||
elif status == 'discarded':
|
||||
print('Checking User Node association status - Discarded')
|
||||
print(PROVISION_FAILURE_MSG)
|
||||
return
|
||||
print('User-Node Association Status - Discarded')
|
||||
log.debug('User-Node Association Status - Discarded')
|
||||
break
|
||||
else:
|
||||
log.debug('User-Node Association Status - ' + status)
|
||||
break
|
||||
|
||||
if status not in ["requested"]:
|
||||
retries -= 1
|
||||
if retries:
|
||||
print("Retries left:", retries)
|
||||
log.info("Retries left: " + str(retries))
|
||||
time.sleep(5)
|
||||
|
||||
if status is None:
|
||||
print(PROVISION_FAILURE_MSG)
|
||||
print('Checking User Node association status failed. '
|
||||
'Please check the internet connectivity.')
|
||||
if status not in ["confirmed"]:
|
||||
log.error('Checking User-Node Association Status...Failed.\n'
|
||||
'\nCould not confirm User-Node Association Status. '
|
||||
'\nPlease use cli command '
|
||||
'`python3 rainmaker.py getnodes` to confirm.')
|
||||
return
|
||||
return
|
||||
|
||||
@@ -18,6 +18,7 @@ import os
|
||||
import base64
|
||||
import time
|
||||
import requests
|
||||
import socket
|
||||
from pathlib import Path
|
||||
from os import path
|
||||
|
||||
@@ -27,7 +28,8 @@ from rmaker_lib.exceptions import NetworkError,\
|
||||
InvalidUserError,\
|
||||
InvalidApiVersionError,\
|
||||
ExpiredSessionError,\
|
||||
SSLError
|
||||
SSLError,\
|
||||
RequestTimeoutError
|
||||
from rmaker_lib.logger import log
|
||||
|
||||
CONFIG_DIRECTORY = '.espressif/rainmaker'
|
||||
@@ -227,11 +229,17 @@ class Config:
|
||||
if access_token is None:
|
||||
raise InvalidConfigError
|
||||
if self.__is_valid_token() is False:
|
||||
print('Previous Session expired. Initialising new session...')
|
||||
log.info('Previous Session expired. Initialising new session...')
|
||||
username = self.get_token_attribute('email')
|
||||
refresh_token = self.get_refresh_token()
|
||||
access_token, id_token = self.__get_new_token(username,
|
||||
refresh_token)
|
||||
self.update_config(access_token, id_token)
|
||||
print('Previous Session expired. Initialising new session...'
|
||||
'Success')
|
||||
log.info('Previous Session expired. Initialising new session...'
|
||||
'Success')
|
||||
return access_token
|
||||
|
||||
def get_user_id(self):
|
||||
@@ -270,7 +278,6 @@ class Config:
|
||||
current_timestamp = int(time.time())
|
||||
if exp_timestamp > current_timestamp:
|
||||
return True
|
||||
log.info("Session expired.")
|
||||
return False
|
||||
|
||||
def __is_valid_version(self):
|
||||
@@ -285,16 +292,20 @@ class Config:
|
||||
: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)
|
||||
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:
|
||||
@@ -331,6 +342,7 @@ class Config:
|
||||
:rtype: str | None
|
||||
|
||||
"""
|
||||
socket.setdefaulttimeout(10)
|
||||
log.info("Extending user login session.")
|
||||
path = 'login'
|
||||
request_payload = {
|
||||
@@ -343,13 +355,16 @@ class Config:
|
||||
log.debug("Extend session url : " + request_url)
|
||||
response = requests.post(url=request_url,
|
||||
data=json.dumps(request_payload),
|
||||
verify=CERT_FILE)
|
||||
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
|
||||
|
||||
|
||||
@@ -16,8 +16,15 @@
|
||||
class NetworkError(Exception):
|
||||
""" Raised when internet connection is not available """
|
||||
def __str__(self):
|
||||
return 'Please check the internet connectivity.\
|
||||
No internet connection available.'
|
||||
return ('Could not connect. '
|
||||
'Please check your Internet connection.')
|
||||
|
||||
|
||||
class RequestTimeoutError(Exception):
|
||||
""" Raised when HTTP Request times out """
|
||||
def __str__(self):
|
||||
return ('HTTP Request timed out. '
|
||||
'Please check your Internet connection.')
|
||||
|
||||
|
||||
class InvalidJSONError(Exception):
|
||||
|
||||
@@ -14,8 +14,12 @@
|
||||
|
||||
import requests
|
||||
import json
|
||||
import socket
|
||||
from rmaker_lib import serverconfig, configmanager
|
||||
from rmaker_lib.exceptions import NetworkError, InvalidClassInput, SSLError
|
||||
from requests.exceptions import Timeout, ConnectionError,\
|
||||
RequestException
|
||||
from rmaker_lib.exceptions import NetworkError, InvalidClassInput, SSLError,\
|
||||
RequestTimeoutError
|
||||
from rmaker_lib.logger import log
|
||||
|
||||
|
||||
@@ -213,6 +217,7 @@ class Node:
|
||||
:return: Request Id if Success, None if Failure
|
||||
:rtype: str | None
|
||||
"""
|
||||
socket.setdefaulttimeout(10)
|
||||
path = 'user/nodes/mapping'
|
||||
config = configmanager.Config()
|
||||
userid = config.get_user_id()
|
||||
@@ -231,15 +236,22 @@ class Node:
|
||||
response = requests.put(url=request_url,
|
||||
data=json.dumps(request_payload),
|
||||
headers=self.__request_header,
|
||||
verify=configmanager.CERT_FILE)
|
||||
verify=configmanager.CERT_FILE,
|
||||
timeout=(5.0, 5.0))
|
||||
log.debug("User node mapping response : " + response.text)
|
||||
response.raise_for_status()
|
||||
except requests.exceptions.SSLError:
|
||||
except requests.exceptions.SSLError as ssl_err:
|
||||
log.debug(ssl_err)
|
||||
raise SSLError
|
||||
except requests.exceptions.ConnectionError:
|
||||
except (ConnectionError, socket.timeout) as conn_err:
|
||||
log.debug(conn_err)
|
||||
raise NetworkError
|
||||
except Exception:
|
||||
raise Exception(response.text)
|
||||
except Timeout as time_err:
|
||||
log.debug(time_err)
|
||||
raise RequestTimeoutError
|
||||
except RequestException as mapping_status_err:
|
||||
log.debug(mapping_status_err)
|
||||
raise mapping_status_err
|
||||
|
||||
try:
|
||||
response = json.loads(response.text)
|
||||
@@ -304,8 +316,9 @@ class Node:
|
||||
:return: Request Status on Success, None on Failure
|
||||
:type: str | None
|
||||
"""
|
||||
log.info("Checking status of user node mapping with request_id : " +
|
||||
request_id)
|
||||
socket.setdefaulttimeout(10)
|
||||
log.debug("Checking status of user node mapping with request_id : " +
|
||||
request_id)
|
||||
path = 'user/nodes/mapping'
|
||||
query_parameters = "&request_id=" + request_id
|
||||
|
||||
@@ -315,15 +328,22 @@ class Node:
|
||||
request_url)
|
||||
response = requests.get(url=request_url,
|
||||
headers=self.__request_header,
|
||||
verify=configmanager.CERT_FILE)
|
||||
verify=configmanager.CERT_FILE,
|
||||
timeout=(5.0, 5.0))
|
||||
log.debug("Check user node mapping status response : " +
|
||||
response.text)
|
||||
response.raise_for_status()
|
||||
except requests.exceptions.SSLError:
|
||||
except requests.exceptions.SSLError as ssl_err:
|
||||
log.debug(ssl_err)
|
||||
raise SSLError
|
||||
except requests.exceptions.ConnectionError:
|
||||
except (ConnectionError, socket.timeout) as conn_err:
|
||||
log.debug(conn_err)
|
||||
raise NetworkError
|
||||
except Exception as mapping_status_err:
|
||||
except Timeout as time_err:
|
||||
log.debug(time_err)
|
||||
raise RequestTimeoutError
|
||||
except RequestException as mapping_status_err:
|
||||
log.debug(mapping_status_err)
|
||||
raise mapping_status_err
|
||||
|
||||
try:
|
||||
|
||||
@@ -35,7 +35,8 @@ class Transport_HTTP(Transport):
|
||||
ssl_ctx = ssl.create_default_context(cafile=certfile)
|
||||
self.conn = http.client.HTTPSConnection(hostname, context=ssl_ctx, timeout=30)
|
||||
try:
|
||||
print("Connecting to " + hostname)
|
||||
print("Connecting to " + hostname +
|
||||
" (this may take some time)")
|
||||
self.conn.connect()
|
||||
except Exception as err:
|
||||
raise RuntimeError("Connection Failure : " + str(err))
|
||||
|
||||
@@ -15,7 +15,7 @@ import sys
|
||||
|
||||
sys.path.insert(0, os.path.abspath('.'))
|
||||
sys.path.append(os.path.abspath('../cli/'))
|
||||
autodoc_mock_imports = ["pathlib", "cryptography", "nvs_partition_gen", "oauth2client", "serial", "user_mapping", "rmaker_tools.esp_rainmaker_prov.security","rmaker_tools.esp_rainmaker_prov.prov", "rmaker_tools.esp_rainmaker_prov.prov_util", "rmaker_tools.rmaker_claim.claim"]
|
||||
autodoc_mock_imports = ["pathlib", "cryptography", "nvs_partition_gen", "oauth2client", "serial", "user_mapping", "rmaker_tools.rmaker_prov.esp_rainmaker_prov", "rmaker_tools.rmaker_prov.security", "rmaker_tools.rmaker_prov.prov", "rmaker_tools.rmaker_prov.prov_util", "rmaker_tools.rmaker_claim.claim"]
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user