def DoUpdate(cache_dir, verbose, ignore_space=False, force_trampoline=None): """ Common code to apply an update once it's been downloaded. This will handle all of the exceptions in a common fashion. Raises an exception on error. """ global log try: diffs = Update.PendingUpdatesChanges(cache_dir) except Exceptions.UpdateBusyCacheException: log.error("Cache directory busy, cannot update") raise except Exceptions.UpdateInvalidUpdateException as e: log.error("Unable not permitted: {0}".format(e.value)) raise except BaseException as e: log.error("Unable to update: {0}".format(str(e))) raise if verbose: PrintDifferences(diffs) if not diffs: log.debug("No updates to apply") return False try: if not verbose: with ProgressBar() as progress_bar: handler = UpdateHandler(progress_bar.update) rv = Update.ApplyUpdate( cache_dir, install_handler=handler.install_handler, ignore_space=ignore_space, force_trampoline=force_trampoline, ) if rv is False: progress_bar.update(message="Updates were not applied") else: with ProgressHandler() as pf: rv = Update.ApplyUpdate( cache_dir, progressFunc=pf.update, ignore_space=ignore_space, force_trampoline=force_trampoline, ) except Exceptions.UpdateInsufficientSpace as e: log.error(str(e)) print(e.value if e.value else "Insufficient space for update") sys.exit(1) except BaseException as e: log.error("Unable to apply update: {0}".format(str(e))) raise if rv and verbose: print("System should be rebooted now", file=sys.stderr) return rv
def DoUpdate(cache_dir, verbose): """ Common code to apply an update once it's been downloaded. This will handle all of the exceptions in a common fashion. Raises an exception on error. """ global log try: diffs = Update.PendingUpdatesChanges(cache_dir) except Exceptions.UpdateBusyCacheException: log.error("Cache directory busy, cannot update") raise except Exceptions.UpdateInvalidUpdateException as e: log.error("Unable not permitted: {0}".format(e.value)) raise except BaseException as e: log.error("Unable to update: {0}".format(str(e))) raise if verbose: PrintDifferences(diffs) if not diffs: log.debug("No updates to apply") return try: rv = Update.ApplyUpdate(cache_dir) except BaseException as e: log.error("Unable to apply update: {0}".format(str(e))) raise if rv and verbose: print("System should be rebooted now", file=sys.stderr) return
async def update(self, job, attrs=None): """ Downloads (if not already in cache) and apply an update. """ attrs = attrs or {} train = attrs.get('train') or ( await self.middleware.call('update.get_trains'))['selected'] location = await self.middleware.call('notifier.get_update_location') job.set_progress(0, 'Retrieving update manifest') handler = UpdateHandler(self, job) update = Update.DownloadUpdate( train, location, check_handler=handler.check_handler, get_handler=handler.get_handler, ) if update is False: raise ValueError('No update available') new_manifest = Manifest.Manifest(require_signature=True) new_manifest.LoadPath('{}/MANIFEST'.format(location)) Update.ApplyUpdate( location, install_handler=handler.install_handler, ) await self.middleware.call('cache.put', 'update.applied', True) if attrs.get('reboot'): await self.middleware.call('system.reboot', {'delay': 10}) return True
def update(self, job, attrs=None): """ Downloads (if not already in cache) and apply an update. """ train = (attrs or {}).get('train') or self.get_train() location = self.middleware.call('notifier.get_update_location') handler = UpdateHandler(self, job) update = Update.DownloadUpdate( train, location, check_handler=handler.check_handler, get_handler=handler.get_handler, ) if update is False: raise ValueError('No update available') new_manifest = Manifest.Manifest(require_signature=True) new_manifest.LoadPath('{}/MANIFEST'.format(location)) Update.ApplyUpdate( location, install_handler=handler.install_handler, ) self.middleware.call('cache.put', 'update.applied', True) return True
def main(handler, args): setproctitle('updated') handler.pid = os.getpid() handler.dump() if args.download: log.debug('Starting DownloadUpdate') Update.DownloadUpdate( args.train, args.cache, check_handler=handler.get_handler, get_handler=handler.get_file_handler, ) log.debug('DownloadUpdate finished') new_manifest = Manifest.Manifest(require_signature=True) try: new_manifest.LoadPath(args.cache + '/MANIFEST') except ManifestInvalidSignature as e: log.error("Cached manifest has invalid signature: %s" % str(e)) raise update_version = new_manifest.Version() if args.apply: log.debug('Starting ApplyUpdate') handler.reboot = Update.ApplyUpdate( args.cache, install_handler=handler.install_handler, ) log.debug('ApplyUpdate finished') if handler.reboot: # Create Alert that update is applied and system should now be rebooted create_update_alert(update_version)
def install_impl_job(self, job, job_id, location): job = FakeJob(job_id, self.middleware.client) handler = UpdateHandler(self, job) return Update.ApplyUpdate( location, install_handler=handler.install_handler, )
async def update(self, job, attrs=None): """ Downloads (if not already in cache) and apply an update. """ attrs = attrs or {} trains = await self.middleware.call('update.get_trains') train = attrs.get('train') or trains['selected'] if attrs.get('train'): await self.middleware.run_in_thread(self.__set_train, attrs.get('train'), trains) location = await self.middleware.call('update.get_update_location') job.set_progress(0, 'Retrieving update manifest') handler = UpdateHandler(self, job) update = Update.DownloadUpdate( train, location, check_handler=handler.check_handler, get_handler=handler.get_handler, ) if update is False: raise ValueError('No update available') new_manifest = Manifest.Manifest(require_signature=True) new_manifest.LoadPath('{}/MANIFEST'.format(location)) Update.ApplyUpdate( location, install_handler=handler.install_handler, ) await self.middleware.call('cache.put', 'update.applied', True) if ( await self.middleware.call('system.is_freenas') or ( await self.middleware.call('failover.licensed') and await self.middleware.call('failover.status') != 'BACKUP' ) ): await self.middleware.call('update.take_systemdataset_samba4_snapshot') if attrs.get('reboot'): await self.middleware.call('system.reboot', {'delay': 10}) return True
def main(handler, args): set_proc_name('updated') handler.pid = os.getpid() handler.dump() if args.download: log.debug('Starting DownloadUpdate') Update.DownloadUpdate( args.train, args.cache, check_handler=handler.get_handler, get_handler=handler.get_file_handler, ) log.debug('DownloadUpdate finished') if args.apply: log.debug('Starting ApplyUpdate') Update.ApplyUpdate( args.cache, install_handler=handler.install_handler, ) log.debug('ApplyUpdate finished')
def main(): global log def usage(): print >> sys.stderr, """Usage: %s [-C cache_dir] [-d] [-T train] [-v] <cmd>, where cmd is one of: check\tCheck for updates update\tDo an update""" % sys.argv[0] sys.exit(1) try: opts, args = getopt.getopt(sys.argv[1:], "C:dT:v") except getopt.GetoptError as err: print str(err) usage() verbose = False debug = 0 config = None cache_dir = None train = None for o, a in opts: if o == "-v": verbose = True elif o == "-d": debug += 1 elif o == '-C': cache_dir = a elif o == "-T": train = a elif o == '-c': cachedir = a else: assert False, "unhandled option %s" % o logging.config.dictConfig({ 'version': 1, 'disable_existing_loggers': True, 'formatters': { 'simple': { 'format': '[%(name)s:%(lineno)s] %(message)s', }, }, 'handlers': { 'std': { 'class': 'logging.StreamHandler', 'level': 'DEBUG', 'stream': 'ext://sys.stdout', }, }, 'loggers': { '': { 'handlers': ['std'], 'level': 'DEBUG', 'propagate': True, }, }, }) log = logging.getLogger('freenas-update') sys.path.append("/usr/local/lib") import freenasOS.Configuration as Configuration import freenasOS.Manifest as Manifest import freenasOS.Update as Update config = Configuration.Configuration() if train is None: train = config.SystemManifest().Train() if len(args) != 1: usage() if args[0] == "check": # To see if we have an update available, we # call Update.DownloadUpdate. If we have been # given a cache directory, we pass that in; otherwise, # we make a temporary directory and use that. We # have to clean up afterwards in that case. if cache_dir is None: download_dir = tempfile.mkdtemp(prefix="UpdateCheck-", dir=config.TemporaryDirectory()) if download_dir is None: print >> sys.stderr, "Unable to create temporary directory" sys.exit(1) else: download_dir = cache_dir rv = Update.DownloadUpdate(train, download_dir) if rv is False: if verbose: print "No updates available" if cache_dir is None: Update.RemoveUpdate(download_dir) sys.exit(1) else: if verbose: diffs = Update.PendingUpdates(download_dir) for (pkg, op, old) in diffs: if op == "delete": print >> sys.stderr, "Delete package %s" % pkg.Name() elif op == "install": print >> sys.stderr, "Install package %s-%s" % ( pkg.Name(), pkg.Version()) elif op == "upgrade": print >> sys.stderr, "Upgrade package %s %s->%s" % ( pkg.Name(), old.Version(), pkg.Version()) if cache_dir is None: Update.RemoveUpdate(download_dir) sys.exit(0) elif args[0] == "update": # This will attempt to apply an update. # If cache_dir is given, then we will only check that directory, # not force a download if it is already there. If cache_dir is not # given, however, then it downloads. (The reason is that you would # want to run "freenas-update -c /foo check" to look for an update, # and it will download the latest one as necessary, and then run # "freenas-update -c /foo update" if it said there was an update. if cache_dir is None: download_dir = tempfile.mkdtemp(prefix="UpdateUpdate-", dir=config.TemporaryDirectory()) if download_dir is None: print >> sys.stderr, "Unable to create temporary directory" sys.exit(1) rv = Update.DownloadUpdate(train, download_dir) if rv is False: if verbose or debug: print >> sys.stderr, "DownloadUpdate returned False" sys.exit(1) else: download_dir = cache_dir diffs = Update.PendingUpdates(download_dir) if diffs is None or diffs == {}: if verbose: print >> sys.stderr, "No updates to apply" else: if verbose: for (pkg, op, old) in diffs: if op == "delete": print >> sys.stderr, "Delete package %s" % pkg.Name() elif op == "install": print >> sys.stderr, "Install package %s-%s" % ( pkg.Name(), pkg.Version()) elif op == "upgrade": print >> sys.stderr, "Upgrade package %s %s -> %s" % ( pkg.Name(), old.Version(), pkg.Version()) rv = Update.ApplyUpdate(download_dir) if rv is False: if verbose: print >> sys.stderr, "ApplyUpdates failed" if cache_dir is None: Update.RemoveUpdate(download_dir) sys.exit(1) Update.RemoveUpdate(download_dir) # Change this if/when we can do an update without a reboot. print >> sys.stderr, "System should be rebooted now" sys.exit(0) else: usage()
async def update(self, job, attrs=None): """ Downloads (if not already in cache) and apply an update. """ attrs = attrs or {} trains = await self.middleware.call('update.get_trains') train = attrs.get('train') or trains['selected'] try: result = compare_trains(trains['current'], train) except Exception: self.logger.warning("Failed to compare trains %r and %r", trains['current'], train, exc_info=True) else: errors = { CompareTrainsResult.NIGHTLY_DOWNGRADE: textwrap.dedent("""\ You're not allowed to change away from the nightly train, it is considered a downgrade. If you have an existing boot environment that uses that train, boot into it in order to upgrade that train. """), CompareTrainsResult.MINOR_DOWNGRADE: textwrap.dedent("""\ Changing minor version is considered a downgrade, thus not a supported operation. If you have an existing boot environment that uses that train, boot into it in order to upgrade that train. """), CompareTrainsResult.MAJOR_DOWNGRADE: textwrap.dedent("""\ Changing major version is considered a downgrade, thus not a supported operation. If you have an existing boot environment that uses that train, boot into it in order to upgrade that train. """), } if result in errors: raise CallError(errors[result]) location = await self.middleware.call('update.get_update_location') job.set_progress(0, 'Retrieving update manifest') handler = UpdateHandler(self, job) update = Update.DownloadUpdate( train, location, check_handler=handler.check_handler, get_handler=handler.get_handler, ) if update is False: raise ValueError('No update available') new_manifest = Manifest.Manifest(require_signature=True) new_manifest.LoadPath('{}/MANIFEST'.format(location)) Update.ApplyUpdate( location, install_handler=handler.install_handler, ) await self.middleware.call('cache.put', 'update.applied', True) if attrs.get('reboot'): await self.middleware.call('system.reboot', {'delay': 10}) return True
def main(): global log log_config_dict = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'simple': { 'format': '[%(name)s:%(lineno)s] %(message)s', }, }, 'filters': { 'cleandownload': { '()': StartsWithFilter, 'params': ['TryGetNetworkFile', 'Searching'] } }, 'handlers': { 'std': { 'class': 'logging.StreamHandler', 'level': 'DEBUG', 'stream': 'ext://sys.stderr', }, }, 'loggers': { '': { 'handlers': ['std'], 'level': 'DEBUG', 'propagate': True, }, }, } def usage(): print( """Usage: %s [-C cache_dir] [-d] [-T train] [--no-delta] [-v] <cmd>, where cmd is one of: check\tCheck for updates update\tDo an update""" % sys.argv[0], file=sys.stderr) sys.exit(1) try: short_opts = "C:dT:v" long_opts = ["cache=", "debug", "train=", "verbose", "no-delta", "snl"] opts, args = getopt.getopt(sys.argv[1:], short_opts, long_opts) except getopt.GetoptError as err: print(str(err)) usage() verbose = False debug = 0 config = None # Should I get this from a configuration file somewhere? cache_dir = "/var/db/system/update" train = None pkg_type = None snl = False for o, a in opts: if o in ("-v", "--verbose"): verbose = True elif o in ("-d", "--debug"): debug += 1 elif o in ('-C', "--cache"): cache_dir = a elif o in ("-T", "--train"): train = a elif o in ("--no-delta"): pkg_type = Update.PkgFileFullOnly elif o in ("--snl"): snl = True else: assert False, "unhandled option %s" % o if not verbose: log_config_dict['handlers']['std']['filters'] = ['cleandownload'] logging.config.dictConfig(log_config_dict) log = logging.getLogger('freenas-update') config = Configuration.Configuration() if train is None: train = config.SystemManifest().Train() if len(args) != 1: usage() if args[0] == "check": # To see if we have an update available, we # call Update.DownloadUpdate. If we have been # given a cache directory, we pass that in; otherwise, # we make a temporary directory and use that. We # have to clean up afterwards in that case. rv = DoDownload(train, cache_dir, pkg_type, verbose) if rv is False: if verbose: print("No updates available") Update.RemoveUpdate(cache_dir) sys.exit(1) else: diffs = Update.PendingUpdatesChanges(cache_dir) if diffs is None or len(diffs) == 0: print( "Strangely, DownloadUpdate says there updates, but PendingUpdates says otherwise", file=sys.stderr) sys.exit(1) PrintDifferences(diffs) if snl: print( "I've got a fever, and the only prescription is applying the pending update." ) sys.exit(0) elif args[0] == "update": # This will attempt to apply an update. # If cache_dir is given, then we will only check that directory, # not force a download if it is already there. If cache_dir is not # given, however, then it downloads. (The reason is that you would # want to run "freenas-update -c /foo check" to look for an update, # and it will download the latest one as necessary, and then run # "freenas-update -c /foo update" if it said there was an update. try: update_opts, update_args = getopt.getopt(args[1:], "R", "--reboot") except getopt.GetoptError as err: print(str(err)) usage() force_reboot = False for o, a in update_opts: if o in ("-R", "--reboot"): force_reboot = True else: assert False, "Unhandled option %s" % o # See if the cache directory has an update downloaded already do_download = True try: f = Update.VerifyUpdate(cache_dir) if f: f.close() do_download = False except Exceptions.UpdateBusyCacheException: print("Cache directory busy, cannot update") sys.exit(0) except (Exceptions.UpdateInvalidCacheException, Exceptions.UpdateIncompleteCacheException): pass except: raise if do_download: rv = DoDownload(train, cache_dir, pkg_type, verbose) diffs = Update.PendingUpdatesChanges(cache_dir) if diffs is None or diffs == {}: if verbose: print("No updates to apply", file=sys.stderr) else: if verbose: PrintDifferences(diffs) try: rv = Update.ApplyUpdate(cache_dir, force_reboot=force_reboot) except BaseException as e: print("Unable to apply update: %s" % str(e), file=sys.stderr) sys.exit(1) if rv: print("System should be rebooted now", file=sys.stderr) if snl: print("Really explore the space.") sys.exit(0) elif tarfile.is_tarfile(args[0]): # Frozen tarball. We'll extract it into the cache directory, and # then add a couple of things to make it pass sanity, and then apply it. # For now we just copy the code above. # First, remove the cache directory # Hrm, could overstep a locked file. shutil.rmtree(cache_dir, ignore_errors=True) try: os.makedirs(cache_dir) except BaseException as e: print("Unable to create cache directory %s: %s" % (cache_dir, str(e))) sys.exit(1) try: ExtractFrozenUpdate(args[0], cache_dir, verbose=verbose) except BaseException as e: print("Unable to extract frozen update %s: %s" % (args[0], str(e))) sys.exit(1) # Exciting! Now we need to have a SEQUENCE file, or it will fail verification. with open(os.path.join(cache_dir, "SEQUENCE"), "w") as s: s.write(config.SystemManifest().Sequence()) # And now the SERVER file with open(os.path.join(cache_dir, "SERVER"), "w") as s: s.write(config.UpdateServerName()) try: diffs = Update.PendingUpdatesChanges(cache_dir) except BaseException as e: print("Attempt to verify extracted frozen update failed: %s" % str(e), file=sys.stderr) sys.exit(1) if diffs is None or diffs == {}: if verbose: print("No updates to apply", file=sys.stderr) else: if verbose: PrintDifferences(diffs) try: rv = Update.ApplyUpdate(cache_dir) except BaseException as e: print("Unable to apply update: %s" % str(e), file=sys.stderr) sys.exit(1) if rv: print("System should be rebooted now", file=sys.stderr) if snl: print("Really explore the space.") sys.exit(0) pass else: usage()
def main(): global log logging.config.dictConfig({ 'version': 1, 'disable_existing_loggers': True, 'formatters': { 'simple': { 'format': '[%(name)s:%(lineno)s] %(message)s', }, }, 'handlers': { 'std': { 'class': 'logging.StreamHandler', 'level': 'DEBUG', 'stream': 'ext://sys.stderr', }, }, 'loggers': { '': { 'handlers': ['std'], 'level': 'DEBUG', 'propagate': True, }, }, }) log = logging.getLogger('freenas-update') sys.path.append("/usr/local/lib") import freenasOS.Configuration as Configuration import freenasOS.Manifest as Manifest import freenasOS.Update as Update def usage(): print >> sys.stderr, """Usage: %s [-C cache_dir] [-d] [-T train] [--no-delta] [-v] <cmd>, where cmd is one of: check\tCheck for updates update\tDo an update""" % sys.argv[0] sys.exit(1) try: short_opts = "C:dT:v" long_opts = ["cache=", "debug", "train=", "verbose", "no-delta"] opts, args = getopt.getopt(sys.argv[1:], short_opts, long_opts) except getopt.GetoptError as err: print str(err) usage() verbose = False debug = 0 config = None cache_dir = None train = None pkg_type = None for o, a in opts: if o in ("-v", "--verbose"): verbose = True elif o in ("-d", "--debug"): debug += 1 elif o in ('-C', "--cache"): cache_dir = a elif o in ("-T", "--train"): train = a elif o in ("--no-delta"): pkg_type = Update.PkgFileFullOnly else: assert False, "unhandled option %s" % o config = Configuration.Configuration() if train is None: train = config.SystemManifest().Train() if len(args) != 1: usage() if args[0] == "check": # To see if we have an update available, we # call Update.DownloadUpdate. If we have been # given a cache directory, we pass that in; otherwise, # we make a temporary directory and use that. We # have to clean up afterwards in that case. if cache_dir is None: download_dir = tempfile.mkdtemp(prefix="UpdateCheck-", dir=config.TemporaryDirectory()) if download_dir is None: print >> sys.stderr, "Unable to create temporary directory" sys.exit(1) else: download_dir = cache_dir rv = Update.DownloadUpdate(train, download_dir, pkg_type=pkg_type) if rv is False: if verbose: print "No updates available" if cache_dir is None: Update.RemoveUpdate(download_dir) sys.exit(1) else: diffs = Update.PendingUpdatesChanges(download_dir) if diffs is None or len(diffs) == 0: print >> sys.stderr, "Strangely, DownloadUpdate says there updates, but PendingUpdates says otherwise" sys.exit(1) PrintDifferences(diffs) if cache_dir is None: Update.RemoveUpdate(download_dir) sys.exit(0) elif args[0] == "update": # This will attempt to apply an update. # If cache_dir is given, then we will only check that directory, # not force a download if it is already there. If cache_dir is not # given, however, then it downloads. (The reason is that you would # want to run "freenas-update -c /foo check" to look for an update, # and it will download the latest one as necessary, and then run # "freenas-update -c /foo update" if it said there was an update. try: update_opts, update_args = getopt.getopt(args[1:], "R", "--reboot") except getopt.GetoptError as err: print str(err) usage() force_reboot = False for o, a in update_opts: if o in ("-R", "--reboot"): force_reboot = True else: assert False, "Unhandled option %s" % o if cache_dir is None: download_dir = tempfile.mkdtemp(prefix="UpdateUpdate-", dir=config.TemporaryDirectory()) if download_dir is None: print >> sys.stderr, "Unable to create temporary directory" sys.exit(1) rv = Update.DownloadUpdate(train, download_dir, pkg_type=pkg_type) if rv is False: if verbose or debug: print >> sys.stderr, "DownloadUpdate returned False" sys.exit(1) else: download_dir = cache_dir diffs = Update.PendingUpdatesChanges(download_dir) if diffs is None or diffs == {}: if verbose: print >> sys.stderr, "No updates to apply" else: if verbose: PrintDifferences(diffs) try: rv = Update.ApplyUpdate(download_dir, force_reboot=force_reboot) except BaseException as e: print >> sys.stderr, "Unable to apply update: %s" % str(e) sys.exit(1) if cache_dir is None: Update.RemoveUpdate(download_dir) if rv: print >> sys.stderr, "System should be rebooted now" sys.exit(0) else: usage()
def main(): global log logging.config.dictConfig({ 'version': 1, 'disable_existing_loggers': True, 'formatters': { 'simple': { 'format': '[%(name)s:%(lineno)s] %(message)s', }, }, 'handlers': { 'std': { 'class': 'logging.StreamHandler', 'level': 'DEBUG', 'stream': 'ext://sys.stderr', }, }, 'loggers': { '': { 'handlers': ['std'], 'level': 'DEBUG', 'propagate': True, }, }, }) log = logging.getLogger('freenas-update') sys.path.append("/usr/local/lib") import freenasOS.Configuration as Configuration import freenasOS.Manifest as Manifest import freenasOS.Update as Update import freenasOS.Exceptions as Exceptions def usage(): print( """Usage: %s [-C cache_dir] [-d] [-T train] [--no-delta] [-v] <cmd>, where cmd is one of: check\tCheck for updates update\tDo an update""" % sys.argv[0], file=sys.stderr) sys.exit(1) try: short_opts = "C:dT:v" long_opts = ["cache=", "debug", "train=", "verbose", "no-delta", "snl"] opts, args = getopt.getopt(sys.argv[1:], short_opts, long_opts) except getopt.GetoptError as err: print(str(err)) usage() verbose = False debug = 0 config = None # Should I get this from a configuration file somewhere? cache_dir = "/var/db/system/update" train = None pkg_type = None snl = False for o, a in opts: if o in ("-v", "--verbose"): verbose = True elif o in ("-d", "--debug"): debug += 1 elif o in ('-C', "--cache"): cache_dir = a elif o in ("-T", "--train"): train = a elif o in ("--no-delta"): pkg_type = Update.PkgFileFullOnly elif o in ("--snl"): snl = True else: assert False, "unhandled option %s" % o config = Configuration.Configuration() if train is None: train = config.SystemManifest().Train() if len(args) != 1: usage() if args[0] == "check": # To see if we have an update available, we # call Update.DownloadUpdate. If we have been # given a cache directory, we pass that in; otherwise, # we make a temporary directory and use that. We # have to clean up afterwards in that case. rv = DoDownload(train, cache_dir, pkg_type) if rv is False: if verbose: print("No updates available") if cache_dir is None: Update.RemoveUpdate(cache_dir) sys.exit(1) else: diffs = Update.PendingUpdatesChanges(cache_dir) if diffs is None or len(diffs) == 0: print( "Strangely, DownloadUpdate says there updates, but PendingUpdates says otherwise", file=sys.stderr) sys.exit(1) PrintDifferences(diffs) if snl: print( "I've got a fever, and the only prescription is applying the pending update." ) sys.exit(0) elif args[0] == "update": # This will attempt to apply an update. # If cache_dir is given, then we will only check that directory, # not force a download if it is already there. If cache_dir is not # given, however, then it downloads. (The reason is that you would # want to run "freenas-update -c /foo check" to look for an update, # and it will download the latest one as necessary, and then run # "freenas-update -c /foo update" if it said there was an update. try: update_opts, update_args = getopt.getopt(args[1:], "R", "--reboot") except getopt.GetoptError as err: print(str(err)) usage() force_reboot = False for o, a in update_opts: if o in ("-R", "--reboot"): force_reboot = True else: assert False, "Unhandled option %s" % o # See if the cache directory has an update downloaded already do_download = True try: f = Update.VerifyUpdate(cache_dir) if f: f.close() do_download = False except Exceptions.UpdateBusyCacheException: printf("Cache directory busy, cannot update") sys.exit(0) except (Exceptions.UpdateInvalidCacheException, Exceptions.UpdateIncompleteCacheException): pass except: raise if do_download: rv = DoDownload(train, cache_dir, pkg_type) diffs = Update.PendingUpdatesChanges(cache_dir) if diffs is None or diffs == {}: if verbose: print("No updates to apply", file=sys.stderr) else: if verbose: PrintDifferences(diffs) try: rv = Update.ApplyUpdate(cache_dir, force_reboot=force_reboot) except BaseException as e: print("Unable to apply update: %s" % str(e), file=sys.stderr) sys.exit(1) if rv: print("System should be rebooted now", file=sys.stderr) if snl: print("Really explore the space.") sys.exit(0) else: usage()