def __init__(self, datadir=None, logdir=None): DistUpgradeView.__init__(self) self.config = DistUpgradeConfig(".") self._fetchProgress = NonInteractiveFetchProgress() self._installProgress = NonInteractiveInstallProgress(logdir) self._opProgress = apt.progress.base.OpProgress() sys.__excepthook__ = self.excepthook
def main(): """ main method """ # commandline setup and config (options, args) = do_commandline() config = DistUpgradeConfig(".") logdir = setup_logging(options, config) from DistUpgradeVersion import VERSION logging.info("release-upgrader version '%s' started" % VERSION) # create view and app objects view = setup_view(options, config, logdir) # gnu screen support if (view.needs_screen and not "RELEASE_UPGRADER_NO_SCREEN" in os.environ and not options.disable_gnu_screen): run_new_gnu_screen_window_or_reattach() app = DistUpgradeController(view, options, datadir=options.datadir) atexit.register(app._enableAptCronJob) # partial upgrade only if options.partial: if not app.doPartialUpgrade(): sys.exit(1) sys.exit(0) # save system state (only if not doing just a partial upgrade) save_system_state(logdir) # full upgrade, return error code for success/failure if app.run(): return 0 return 1
def __init__(self, logdir): InstallProgress.__init__(self) logging.debug("setting up environ for non-interactive use") if not os.environ.has_key("DEBIAN_FRONTEND"): os.environ["DEBIAN_FRONTEND"] = "noninteractive" os.environ["APT_LISTCHANGES_FRONTEND"] = "none" os.environ["RELEASE_UPRADER_NO_APPORT"] = "1" self.config = DistUpgradeConfig(".") self.logdir = logdir self.install_run_number = 0 try: if self.config.getWithDefault("NonInteractive","ForceOverwrite", False): apt_pkg.config.set("DPkg::Options::","--force-overwrite") except (NoSectionError, NoOptionError): pass # more debug #apt_pkg.Config.Set("Debug::pkgOrderList","true") #apt_pkg.Config.Set("Debug::pkgDPkgPM","true") # default to 2400 sec timeout self.timeout = 2400 try: self.timeout = self.config.getint("NonInteractive","TerminalTimeout") except Exception: pass
def __init__(self, logdir): InstallProgress.__init__(self) logging.debug("setting up environ for non-interactive use") os.environ["DEBIAN_FRONTEND"] = "noninteractive" os.environ["APT_LISTCHANGES_FRONTEND"] = "none" os.environ["RELEASE_UPRADER_NO_APPORT"] = "1" self.config = DistUpgradeConfig(".") self.logdir = logdir self.install_run_number = 0 try: if self.config.getWithDefault("NonInteractive","ForceOverwrite", False): apt_pkg.config.set("DPkg::Options::","--force-overwrite") except (NoSectionError, NoOptionError): pass # more debug #apt_pkg.Config.Set("Debug::pkgOrderList","true") #apt_pkg.Config.Set("Debug::pkgDPkgPM","true") # default to 2400 sec timeout self.timeout = 2400 try: self.timeout = self.config.getint("NonInteractive","TerminalTimeout") except Exception: pass
parser.add_option("--with-network", dest="withNetwork", action="store_true") parser.add_option("--without-network", dest="withNetwork", action="store_false") (options, args) = parser.parse_args() if not os.path.exists("/var/log/dist-upgrade"): os.mkdir("/var/log/dist-upgrade") logging.basicConfig(level=logging.DEBUG, filename="/var/log/dist-upgrade/main.log", format='%(asctime)s %(levelname)s %(message)s', filemode='w') config = DistUpgradeConfig(".") requested_view = config.get("View", "View") try: view_modul = __import__(requested_view) view_class = getattr(view_modul, requested_view) view = view_class() except (ImportError, AttributeError): logging.error("can't import view '%s'" % requested_view) print "can't find %s" % requested_view sys.exit(1) app = DistUpgradeControler(view, options) app.run() # testcode to see if the bullets look nice in the dialog #for i in range(4):
class NonInteractiveInstallProgress(InstallProgress): """ Non-interactive version of the install progress class This ensures that conffile prompts are handled and that hanging scripts are killed after a (long) timeout via ctrl-c """ def __init__(self, logdir): InstallProgress.__init__(self) logging.debug("setting up environ for non-interactive use") if not os.environ.has_key("DEBIAN_FRONTEND"): os.environ["DEBIAN_FRONTEND"] = "noninteractive" os.environ["APT_LISTCHANGES_FRONTEND"] = "none" os.environ["RELEASE_UPRADER_NO_APPORT"] = "1" self.config = DistUpgradeConfig(".") self.logdir = logdir self.install_run_number = 0 try: if self.config.getWithDefault("NonInteractive","ForceOverwrite", False): apt_pkg.config.set("DPkg::Options::","--force-overwrite") except (NoSectionError, NoOptionError): pass # more debug #apt_pkg.Config.Set("Debug::pkgOrderList","true") #apt_pkg.Config.Set("Debug::pkgDPkgPM","true") # default to 2400 sec timeout self.timeout = 2400 try: self.timeout = self.config.getint("NonInteractive","TerminalTimeout") except Exception: pass def error(self, pkg, errormsg): logging.error("got a error from dpkg for pkg: '%s': '%s'" % (pkg, errormsg)) # check if re-run of maintainer script is requested if not self.config.getWithDefault( "NonInteractive","DebugBrokenScripts", False): return # re-run maintainer script with sh -x/perl debug to get a better # idea what went wrong # # FIXME: this is just a approximation for now, we also need # to pass: # - a version after remove (if upgrade to new version) # # not everything is a shell or perl script # # if the new preinst fails, its not yet in /var/lib/dpkg/info # so this is inaccurate as well environ = copy.copy(os.environ) environ["PYCENTRAL"] = "debug" cmd = [] # find what maintainer script failed if "post-installation" in errormsg: prefix = "/var/lib/dpkg/info/" name = "postinst" argument = "configure" maintainer_script = "%s/%s.%s" % (prefix, pkg, name) elif "pre-installation" in errormsg: prefix = "/var/lib/dpkg/tmp.ci/" #prefix = "/var/lib/dpkg/info/" name = "preinst" argument = "install" maintainer_script = "%s/%s" % (prefix, name) elif "pre-removal" in errormsg: prefix = "/var/lib/dpkg/info/" name = "prerm" argument = "remove" maintainer_script = "%s/%s.%s" % (prefix, pkg, name) elif "post-removal" in errormsg: prefix = "/var/lib/dpkg/info/" name = "postrm" argument = "remove" maintainer_script = "%s/%s.%s" % (prefix, pkg, name) else: print "UNKNOWN (trigger?) dpkg/script failure for %s (%s) " % (pkg, errormsg) return # find out about the interpreter if not os.path.exists(maintainer_script): logging.error("can not find failed maintainer script '%s' " % maintainer_script) return interp = open(maintainer_script).readline()[2:].strip().split()[0] if ("bash" in interp) or ("/bin/sh" in interp): debug_opts = ["-ex"] elif ("perl" in interp): debug_opts = ["-d"] environ["PERLDB_OPTS"] = "AutoTrace NonStop" else: logging.warning("unknown interpreter: '%s'" % interp) # check if debconf is used and fiddle a bit more if it is if ". /usr/share/debconf/confmodule" in open(maintainer_script).read(): environ["DEBCONF_DEBUG"] = "developer" environ["DEBIAN_HAS_FRONTEND"] = "1" interp = "/usr/share/debconf/frontend" debug_opts = ["sh","-ex"] # build command cmd.append(interp) cmd.extend(debug_opts) cmd.append(maintainer_script) cmd.append(argument) # check if we need to pass a version if name == "postinst": version = Popen("dpkg-query -s %s|grep ^Config-Version" % pkg,shell=True, stdout=PIPE).communicate()[0] if version: cmd.append(version.split(":",1)[1].strip()) elif name == "preinst": pkg = os.path.basename(pkg) pkg = pkg.split("_")[0] version = Popen("dpkg-query -s %s|grep ^Version" % pkg,shell=True, stdout=PIPE).communicate()[0] if version: cmd.append(version.split(":",1)[1].strip()) logging.debug("re-running '%s' (%s)" % (cmd, environ)) ret = subprocess.call(cmd, env=environ) logging.debug("%s script returned: %s" % (name,ret)) def conffile(self, current, new): logging.warning("got a conffile-prompt from dpkg for file: '%s'" % current) # looks like we have a race here *sometimes* time.sleep(5) try: # don't overwrite os.write(self.master_fd,"n\n") except Exception, e: logging.error("error '%s' when trying to write to the conffile"%e)
class DistUpgradeViewNonInteractive(DistUpgradeView): " non-interactive version of the upgrade view " def __init__(self, datadir=None, logdir=None): DistUpgradeView.__init__(self) self.config = DistUpgradeConfig(".") self._fetchProgress = NonInteractiveFetchProgress() self._installProgress = NonInteractiveInstallProgress(logdir) self._opProgress = apt.progress.base.OpProgress() sys.__excepthook__ = self.excepthook def excepthook(self, type, value, traceback): " on uncaught exceptions -> print error and reboot " logging.exception("got exception '%s': %s " % (type, value)) #sys.excepthook(type, value, traceback) self.confirmRestart() def getOpCacheProgress(self): " return a OpProgress() subclass for the given graphic" return self._opProgress def getFetchProgress(self): " return a fetch progress object " return self._fetchProgress def getInstallProgress(self, cache=None): " return a install progress object " return self._installProgress def updateStatus(self, msg): """ update the current status of the distUpgrade based on the current view """ pass def setStep(self, step): """ we have 5 steps current for a upgrade: 1. Analyzing the system 2. Updating repository information 3. Performing the upgrade 4. Post upgrade stuff 5. Complete """ pass def confirmChanges(self, summary, changes, demotions, downloadSize, actions=None, removal_bold=True): DistUpgradeView.confirmChanges(self, summary, changes, demotions, downloadSize, actions) logging.debug("toinstall: '%s'" % [p.name for p in self.toInstall]) logging.debug("toupgrade: '%s'" % [p.name for p in self.toUpgrade]) logging.debug("toremove: '%s'" % [p.name for p in self.toRemove]) return True def askYesNoQuestion(self, summary, msg, default='No'): " ask a Yes/No question and return True on 'Yes' " # if this gets enabled upgrades over ssh with the non-interactive # frontend will no longer work #if default.lower() == "no": # return False return True def confirmRestart(self): " generic ask about the restart, can be overridden " logging.debug("confirmRestart() called") # rebooting here makes sense if we run e.g. in qemu return self.config.getWithDefault("NonInteractive","RealReboot", False) def error(self, summary, msg, extended_msg=None): " display a error " logging.error("%s %s (%s)" % (summary, msg, extended_msg)) def abort(self): logging.error("view.abort called")
) parser.add_option("--have-backports", dest="haveBackports", action="store_true", default=False) parser.add_option("--with-network", dest="withNetwork", action="store_true") parser.add_option("--without-network", dest="withNetwork", action="store_false") (options, args) = parser.parse_args() if not os.path.exists("/var/log/dist-upgrade"): os.mkdir("/var/log/dist-upgrade") logging.basicConfig( level=logging.DEBUG, filename="/var/log/dist-upgrade/main.log", format="%(asctime)s %(levelname)s %(message)s", filemode="w", ) config = DistUpgradeConfig(".") requested_view = config.get("View", "View") try: view_modul = __import__(requested_view) view_class = getattr(view_modul, requested_view) view = view_class() except (ImportError, AttributeError): logging.error("can't import view '%s'" % requested_view) print "can't find %s" % requested_view sys.exit(1) app = DistUpgradeControler(view, options) app.run() # testcode to see if the bullets look nice in the dialog # for i in range(4):