All the steps of a repo setup (network, mount, repo, sack, groups) are done per repo so that we can detect fail in time, offer going to repo UI ("Edit") where the failing repo can be edited, disabled, target (media, images) can be fixed etc... --- pyanaconda/yuminstall.py | 300 ++++++++++++++++++++++++++-------------------- 1 files changed, 172 insertions(+), 128 deletions(-) diff --git a/pyanaconda/yuminstall.py b/pyanaconda/yuminstall.py index 1fcf7f8..3b9f765 100644 --- a/pyanaconda/yuminstall.py +++ b/pyanaconda/yuminstall.py @@ -572,7 +572,7 @@ class AnacondaYum(YumSorter): # Where is the source media mounted? This is the directory # where Packages/ is located. - self.tree = "/mnt/source" + self.tree = anaconda.backend.tree self.macros = {} @@ -591,28 +591,6 @@ class AnacondaYum(YumSorter): self.updates = [] self.localPackages = [] - def setup(self): - # yum doesn't understand all our method URLs, so use this for all - # except FTP and HTTP installs. - self._baseRepoURL = "file://%s" % self.tree - - while True: - try: - self.configBaseURL() - break - except SystemError, e: - self.anaconda.intf.messageWindow(_("Error Setting Up Repository"), - _("The following error occurred while setting up the " - "installation repository:\n\n%(e)s\n\nPlease provide the " - "correct information for installing %(productName)s.") - % {'e': e, 'productName': productName}) - - self.anaconda.methodstr = self.anaconda.intf.methodstrRepoWindow(self.anaconda.methodstr or "cdrom:") - - self.doConfigSetup(root=self.anaconda.rootPath) - if not self.anaconda.bootloader.doUpgradeOnly: - self.conf.installonlypkgs = [] - def _switchCD(self, discnum): if os.access("%s/.discinfo" % self.tree, os.R_OK): f = open("%s/.discinfo" % self.tree) @@ -1131,6 +1109,8 @@ reposdir=/etc/anaconda.repos.d,/tmp/updates/anaconda.repos.d,/tmp/product/anacon fd = open("/tmp/anaconda-yum.conf", "w") fd.write(buf) fd.close() + self.tree = "/mnt/source" + self.ayum = None def complete(self, anaconda): if not anaconda.mediaDevice and os.path.ismount(self.ayum.tree): @@ -1257,139 +1237,198 @@ reposdir=/etc/anaconda.repos.d,/tmp/updates/anaconda.repos.d,/tmp/product/anacon # FIXME: make sure that the rpmdb doesn't have stale locks :/ iutil.resetRpmDb(anaconda.rootPath) + # TODORV move to __init__? still needed? iutil.writeRpmPlatform() + # TODORV move to __init__? anaconda.backend.freetmp(anaconda) + self.ayum = AnacondaYum(anaconda) - self.ayum.setup() - self.ayum.doMacros() + self._removeUpgradeInstallImage(anaconda.rootPath) - # If any enabled repositories require networking, go ahead and bring - # it up now. No need to have people wait for the timeout when we - # know this in advance. - for repo in self.ayum.repos.listEnabled(): - if repo.needsNetwork() and not network.hasActiveNetDev(): - if not anaconda.intf.enableNetwork(): - anaconda.intf.messageWindow(_("No Network Available"), - _("Some of your software repositories require " - "networking, but there was an error enabling the " - "network on your system."), - type="custom", custom_icon="error", - custom_buttons=[_("_Exit installer")]) - sys.exit(1) + self.ayum.doConfigSetup(root=anaconda.rootPath) - urlgrabber.grabber.reset_curl_obj() + self.ayum.doMacros() + + self._resetSetupResults(anaconda.repos) + failed = True + for repo in anaconda.repos: + if not repo.enabled: + log.debug("not adding disabled repo %s with URL %s" % + (repo.id, repo.url)) + continue + else: + log.debug("adding enabled repo %s with URL %s" % + (repo.id, repo.url)) + if not self._enableNetworkIfNeeded(repo, anaconda.intf): + break + if not repo.mount(self.ayum): + break + if not self.addEnabledRepo(self.ayum, repo, anaconda.intf): + break + # We repeat this for each repo because we want to have + # repo-specific failure + self.ayum.repos.setCacheDir(self.ayum.conf.cachedir) + if not self.doRepoSetup(self.ayum, repo, anaconda.intf): + break + if not self.doSackSetup(self.ayum, repo, anaconda.intf): break + # We repeat this for each repo because we want to have + # repo-specific failure + if not self.doGroupSetup(self.ayum, repo, anaconda.intf): + break + repo.yumrepo.setFailureObj(self.ayum.urlgrabberFailureCB) + repo.yumrepo.setMirrorFailureObj((self.ayum.mirrorFailureCB, (), + {"repo": repo.yumrepo.id})) + else: + failed = False + + if not anaconda.upgrade: + anaconda.dispatch.skipStep("repotasksel", skip = 0) + if not self.anaconda.bootloader.doUpgradeOnly: + self.ayum.conf.installonlypkgs = [] - self.doRepoSetup(anaconda) - self.doSackSetup(anaconda) - self.doGroupSetup(anaconda) + if failed: + repo.setup="failed" + return DISPATCH_BACK + # TODORV: redundant? self.ayum.doMacros() - def doGroupSetup(self, anaconda): + def _resetSetupResults(self, repos): + for repo in repos: + repo.setup = "?" + repo.setup_fail_comment = "" + + def _enableNetworkIfNeeded(self, repo, intf): + + if network.hasActiveNetDev() or not repo.needsNetwork(): + return True + + if not intf.enableNetwork(): + buttons = [_("_Exit installer"), _("Edit")] + rc = intf.messageWindow(_("No Network Available"), + _("Software repository %s requires " + "networking, but there was an error enabling the " + "network on your system." % repo.name), + type="custom", custom_icon="error", + custom_buttons=buttons) + if rc == 0: + sys.exit(1) + elif rc == 1: + repo.setup = "failed" + repo.setup_fail_comment = _("No Network Available") + return False + + urlgrabber.grabber.reset_curl_obj() + return True + + def addEnabledRepo(self, ayum, repo, intf): + yumrepo = AnacondaYumRepo(repo.id) + repo.initYumRepo(yumrepo) + yumrepo.enable() + repo.yumrepo = yumrepo + try: + ayum.repos.add(yumrepo) + except yum.Errors.DuplicateRepoError, e: + msg =_("The repository %s has already been added. Please " + "choose a different repository name and " + "URL.") % repo.name + intf.messageWindow(_("Error"), msg, type="ok", custom_icon="error") + repo.setup = "failed" + repo.setup_fail_comment = msg + return False + return True + + def _removeUpgradeInstallImage(self, rootpath): + if os.path.exists("%s/boot/upgrade/install.img" % rootpath): + log.info("REMOVING stage2 image from %s /boot/upgrade" % rootpath ) + try: + os.unlink("%s/boot/upgrade/install.img" % rootpath) + except: + log.warning("failed to clean /boot/upgrade") + + def doGroupSetup(self, ayum, repo, intf): while True: try: - self.ayum.doGroupSetup() + ayum.doGroupSetup() except (GroupsError, NoSuchGroup, RepoError), e: - buttons = [_("_Exit installer"), _("_Retry")] + buttons = [_("_Exit installer"), _("_Retry"), _("_Edit")] else: - break # success + return True - rc = anaconda.intf.messageWindow(_("Error"), - _("Unable to read group information " - "from repositories. This is " - "a problem with the generation " - "of your install tree."), - type="custom", custom_icon="error", - custom_buttons = buttons) + msg = _("Unable to read group information " + "from repositories. This is " + "a problem with the generation " + "of your install tree.\n\n%s" % e) + rc = intf.messageWindow(_("Error"), + msg, + type="custom", custom_icon="error", + custom_buttons = buttons) if rc == 0: sys.exit(0) - else: - self.ayum._setGroups(None) + elif rc == 1: + ayum._setGroups(None) continue + elif rc == 2: + repo.setup = "failed" + repo.setup_fail_comment = msg + return False - def doRepoSetup(self, anaconda, thisrepo = None, fatalerrors = True): - self.__withFuncDo(anaconda, lambda r: self.ayum.doRepoSetup(thisrepo=r.id), - thisrepo=thisrepo, fatalerrors=fatalerrors, - callback=RepoSetupPulseProgress(anaconda.intf)) + def doRepoSetup(self, ayum, repo, intf, fatalerrors = True): + return self.__withFuncDo(self.ayum.doRepoSetup, + ayum, repo, intf, fatalerrors=fatalerrors, + callback=RepoSetupPulseProgress(intf)) - def doSackSetup(self, anaconda, thisrepo = None, fatalerrors = True): - self.__withFuncDo(anaconda, lambda r: self.ayum.doSackSetup(thisrepo=r.id), - thisrepo=thisrepo, fatalerrors=fatalerrors, - callback=SackSetupProgress(anaconda.intf)) + def doSackSetup(self, ayum, repo, intf, fatalerrors = True): + return self.__withFuncDo(self.ayum.doSackSetup, + ayum, repo, intf, fatalerrors=fatalerrors, + callback=SackSetupProgress(intf)) - def __withFuncDo(self, anaconda, fn, thisrepo=None, fatalerrors=True, + # TODORV: what to do with continue? + def __withFuncDo(self, fn, ayum, repo, intf, fatalerrors=True, callback=None): - # Don't do this if we're being called as a dispatcher step (instead - # of being called when a repo is added via the UI) and we're going - # back. - if thisrepo is None and anaconda.dir == DISPATCH_BACK: - return - - # We want to call the function one repo at a time so we have some - # concept of which repo didn't set up correctly. - if thisrepo is not None: - repos = [self.ayum.repos.getRepo(thisrepo)] - else: - repos = self.ayum.repos.listEnabled() - - for repo in repos: - if callback: - callback.connect(repo) - - while True: - try: - fn(repo) - if callback: - callback.disconnect() - except RepoError, e: - if callback: - callback.disconnect() - buttons = [_("_Exit installer"), _("Edit"), _("_Retry")] - else: - break # success - - if anaconda.ksdata: - buttons.append(_("_Continue")) + if callback: + callback.connect(repo.yumrepo) + rc = -1 + while True: + try: + fn(thisrepo=repo.yumrepo.id) + if callback: + callback.disconnect() + except RepoError, e: + if callback: + callback.disconnect() + buttons = [_("_Exit installer"), _("_Continue"), _("_Edit"), _("_Retry")] + else: + repo.setup = "OK" + break # success - if not fatalerrors: - raise RepoError, e + if not fatalerrors: + raise RepoError, e - rc = anaconda.intf.messageWindow(_("Error"), - _("Unable to read package metadata. This may be " - "due to a missing repodata directory. Please " - "ensure that your install tree has been " - "correctly generated.\n\n%s" % e), - type="custom", custom_icon="error", - custom_buttons=buttons) - if rc == 0: - # abort - sys.exit(0) - elif rc == 1: - # edit - anaconda.intf.editRepoWindow(repo) - break - elif rc == 2: - # retry, but only if button is present - continue + rc = intf.messageWindow(_("Error"), + _("Unable to read package metadata. This may be " + "due to a missing repodata directory. Please " + "ensure that your install tree has been " + "correctly generated.\n\n%s" % e), + type="custom", custom_icon="error", + custom_buttons=buttons) + if rc == 0: + sys.exit(0) + elif rc == 1 or rc == 2: + repo.setup = "failed" + repo.setup_fail_comment = str(e) + if rc == 1: + return True else: - # continue, but only if button is present - self.ayum.repos.delete(repo.id) - break - - # if we're in kickstart the repo may have been deleted just above - try: - self.ayum.repos.getRepo(repo.id) - except RepoError: - log.debug("repo %s has been removed" % (repo.id,)) + return False + elif rc == 3: + # retry, but only if button is present continue - repo.setFailureObj(self.ayum.urlgrabberFailureCB) - repo.setMirrorFailureObj((self.ayum.mirrorFailureCB, (), - {"repo": repo.id})) - self.ayum.repos.callback = None + return True def getDefaultGroups(self, anaconda): langs = anaconda.instLanguage.getCurrentLangSearchList() @@ -1952,7 +1991,12 @@ reposdir=/etc/anaconda.repos.d,/tmp/updates/anaconda.repos.d,/tmp/product/anacon def groupListExists(self, grps): """Returns bool of whether all of the given groups exist.""" for gid in grps: - g = self.ayum.comps.return_group(gid) + try: + g = self.ayum.comps.return_group(gid) + # catch "No Groups Available in any repository" + except GroupsError as e: + log.debug("exception caught: %s" % e) + return False if not g: log.debug("no such group %s" % (gid,)) return False -- 1.7.2 _______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list