def update_local(self, path='.'): """Attempt to resolve all LOCAL dependencies in this IOTile by installing them into build/deps """ tile = IOTile(path) if tile.release: raise ArgumentError( "Cannot update dependencies on a release mode tile that cannot have dependencies" ) depdir = os.path.join(tile.folder, 'build', 'deps') #FIXME: Read resolver_settings.json file resolver_chain = DependencyResolverChain() reg = ComponentRegistry() for dep in tile.dependencies: # Check each dependency to see if it's local try: local_tile = reg.find_component(dep['name']) if local_tile.release: continue if local_tile is not None: result = resolver_chain.update_dependency(tile, dep) except ArgumentError: continue iprint("Resolving %s: %s" % (dep['name'], result))
def _download_ota_script(script_url): """Download the script from the cloud service and store to temporary file location""" try: blob = requests.get(script_url, stream=True) return blob.content except Exception as e: iprint("Failed to download OTA script") iprint(e) return False
def _wait_script(self): """Trigger a script and then synchronously wait for it to finish processing.""" self._trigger_script() status, error = self._query_status() if error != 0: raise HardwareError("Error executing remote script", error_code=error) error_count = 0 iprint("Waiting for script to validate") while status == 3: time.sleep(0.1) try: status, error = self._query_status() if error != 0: raise HardwareError("Error executing remote script", error_code=error) except HardwareError: error_count += 1 if error_count > 2: raise HardwareError("Too many errors waiting for script to finish execution", error=str(HardwareError)) if error != 0: raise HardwareError("Error executing remote script", error_code=error) iprint("Waiting for script to finish executing") while status != 0: if type_system.interactive: sys.stdout.write('.') sys.stdout.flush() # Poll until the script has finished executing. Some scripts # will cause the device to reset, so if that happens, make sure # we don't flag that as an error and cleanly reconnect. time.sleep(0.1) try: status, error = self._query_status() except HardwareError: error_count += 1 if error_count > 10: if type_system.interactive: sys.stdout.write('\n') raise HardwareError("Too many errors waiting for script to finish execution", error=str(HardwareError)) if error != 0: if type_system.interactive: sys.stdout.write('\n') raise HardwareError("Error executing remote script", error_code=error) if type_system.interactive: sys.stdout.write('\n')
def run_script(self, script, force=False, no_reboot=False): """Run a script on the connected IOTile device. The script must an UpdateScript object. If you are looking for an interactive function that will load a script from a file and show update information to a user, you should use load_script. This is a low level function that is meant to be called from a larger program. If this run is called from an interactive session (inside the iotile tool) then it will show a progress bar during download and periodic updates during script execution, otherwise there is no feedback until the script is finished. Args: script (UpdateScript): The script that we wish to run on our attached device. force (bool): If there is already a script loaded but not yet executed, clear that script before proceeding. no_reboot (bool): Do not reboot the device after running the script. You typically want to reboot so this defaults to False. If you know what you are doing, you can set this to True to not do a sanity reboot after running the script. """ raw_data = script.encode() status, _err = self._query_status() if status == self.ReceivedScript and force: self._reset_script() elif status != self.IdleStatus: raise HardwareError( "Cannot run script on a remote_bridge that is not currently idle", status=status) self._begin_script() progress = ProgressBar("Downloading script", 100) progress.start() try: self.push_script(raw_data, progress) finally: progress.end() self._end_script() self._wait_script() if not no_reboot: iprint("Rebooting device") self._reboot()
def update(self, path='.'): """Attempt to resolve all dependencies in this IOTile by installing them into build/deps""" tile = IOTile(path) if tile.release: raise ArgumentError( "Cannot update dependencies on a release mode tile that cannot have dependencies" ) depdir = os.path.join(tile.folder, 'build', 'deps') # FIXME: Read resolver_settings.json file resolver_chain = DependencyResolverChain() for dep in tile.dependencies: result = resolver_chain.update_dependency(tile, dep) iprint("Resolving %s: %s" % (dep['name'], result))
def invoke(self, line): """Invoke a one or more function given a list of arguments. The functions are searched for using the current context on the context stack and its annotated type information is used to convert all of the string parameters passed in line to appropriate python types. Args: line (list): The list of command line arguments. Returns: bool: A boolean specifying if the last function created a new context (False if a new context was created) and a list with the remainder of the command line if this function did not consume all arguments.) """ finished = True while len(line) > 0: val, line, finished = self.invoke_one(line) if val is not None: iprint(val) return finished
def check_and_update(self): """ Checks the cloud for an available OTA update and applies it to the device. Informs the cloud of the attempt afterwards Gives some diagnostic info to the user as process goes """ script = self.check_cloud_for_script() if not script: iprint("no OTA pending") return iprint("Applying deployment " + str(script[0])) iprint("Downloading script") iprint(script[1]) blob = _download_ota_script(script[1]) if not blob: iprint("Download of script failed for some reason") return iprint("Applying script") try: self._apply_ota_update(blob=blob) self._inform_cloud(script[0], self.dev_slug, True) except Exception: self._inform_cloud(script[0], self.dev_slug, False) raise
def _check_criteria(self, criterion): for criteria in criterion: text, opr, value = criteria.split(":") if text == 'os_tag': if self.os_info[0] != int(value): iprint("os_tag doesn't match: " + str(self.os_info[0]) + " != " + value) return False elif text == 'app_tag': if self.app_info[0] != int(value): iprint("app_tag doesn't match: " + str(self.app_info[0]) + " != " + value) return False elif text == 'os_version': ver = SemanticVersion.FromString(value) if op_map[opr](self.os_info[1], ver): iprint("os_version not compatible: " + str(self.os_info[1]) + "not" + opr + value) return False elif text == 'app_version': ver = SemanticVersion.FromString(value) if op_map[opr](self.app_info[1], ver): iprint("app_version not compatible: " + str(self.app_info[1]) + "not" + opr + value) return False elif text == 'controller_hw_tag': # TODO : figure out what the check here should be if opr not in ('eq', '=='): iprint("op needed: eq, op seen: " + opr) return False if self._con.hardware_version() != value: return False else: iprint("Unrecognized selection criteria tag : " + text) return None return True