In this step preceeding repotasksel (repo UI) all non-UI repo requirements should be collected (from method, ks, driverdisc, /etc/anaconda/repos.d config). This used to be done as part of reposetup - partly in configBaseURL (for method), partly in doConfigSetup (for other repos), we need to move it before repo UI. Another part of configBaseURL - mounting of nfs, nfsiso, media was separated so that it can be done in reposetup step for each repo (RepoSpec.mount() method). A tricky part here is obtaining specifications of repos from /etc/anaconda.repos.d for which temporary AnacondaYumBase object is created in the repocollect step. --- pyanaconda/backend.py | 3 + pyanaconda/dispatch.py | 3 +- pyanaconda/installclass.py | 1 + pyanaconda/upgrade.py | 1 + pyanaconda/yuminstall.py | 450 ++++++++++++++++++++----------------------- 5 files changed, 216 insertions(+), 242 deletions(-) diff --git a/pyanaconda/backend.py b/pyanaconda/backend.py index 747252d..f7c9078 100644 --- a/pyanaconda/backend.py +++ b/pyanaconda/backend.py @@ -264,6 +264,9 @@ class AnacondaBackend: def complete(self, anaconda): pass +def doCollectRepos(anaconda): + if anaconda.backend.doCollectRepos(anaconda) == DISPATCH_BACK: + return DISPATCH_BACK def doBackendSetup(anaconda): if anaconda.backend.doBackendSetup(anaconda) == DISPATCH_BACK: diff --git a/pyanaconda/dispatch.py b/pyanaconda/dispatch.py index 94f70f2..ad7e7c4 100644 --- a/pyanaconda/dispatch.py +++ b/pyanaconda/dispatch.py @@ -42,7 +42,7 @@ from upgrade import findRootParts, queryUpgradeContinue from installmethod import doMethodComplete from kickstart import runPostScripts -from backend import doPostSelection, doBackendSetup, doBasePackageSelect +from backend import doPostSelection, doBackendSetup, doBasePackageSelect, doCollectRepos from backend import doPreInstall, doPostInstall, doInstall from backend import writeConfiguration @@ -95,6 +95,7 @@ installSteps = [ ("upgbootloader", ), ("bootloadersetup", bootloaderSetupChoices, ), ("bootloader", ), + ("repocollect", doCollectRepos, ), ("repotasksel", ), ("reposetup", doBackendSetup, ), ("basepkgsel", doBasePackageSelect, ), diff --git a/pyanaconda/installclass.py b/pyanaconda/installclass.py index 920c710..5344933 100644 --- a/pyanaconda/installclass.py +++ b/pyanaconda/installclass.py @@ -94,6 +94,7 @@ class BaseInstallClass(object): "network", "timezone", "accounts", + "repocollect", "repotasksel", "reposetup", "basepkgsel", diff --git a/pyanaconda/upgrade.py b/pyanaconda/upgrade.py index 1978409..82c0737 100644 --- a/pyanaconda/upgrade.py +++ b/pyanaconda/upgrade.py @@ -332,6 +332,7 @@ def setSteps(anaconda): "upgrademigratefs", "enablefilesystems", "upgradecontinue", + "repocollect", "reposetup", "upgbootloader", "checkdeps", diff --git a/pyanaconda/yuminstall.py b/pyanaconda/yuminstall.py index a7e5385..1fcf7f8 100644 --- a/pyanaconda/yuminstall.py +++ b/pyanaconda/yuminstall.py @@ -236,6 +236,100 @@ class YumRepoSpec(RepoSpec): self.enabled = yumrepo.enabled self.mediaid = yumrepo.mediaid + def mount(self, ayum): + # TODORV: failure handling + if self.url.startswith("hd:"): + if self.url.count(":") == 2: + (device, path) = self.url[3:].split(":") + else: + (device, fstype, path) = self.url[3:].split(":") + + ayum.isodir = "/mnt/isodir/%s" % path + + # This takes care of mounting /mnt/isodir first. + ayum._switchImage(1) + ayum.mediagrabber = ayum.mediaHandler + elif self.url.startswith("http") or self.url.startswith("ftp:"): + self.baseurl = self.url + elif self.url.startswith("cdrom:"): + # When/if supported (KS, UI), parse device + if not self.media_device: + cdr = scanForMedia(ayum.tree, ayum.anaconda.storage) + if cdr: + self.media_device = cdr + log.info("found installation media on %s" % cdr) + else: + ayum.anaconda.intf.messageWindow(_("No Media Found"), + _("No installation media was found. " + "Please insert a disc into your drive " + "and try again.")) + self.setup_fail_comment = _("No Media Found") + self.setup = "failed" + return False + ayum.anaconda.mediaDevice = self.media_device + ayum._switchCD(1) + ayum.mediagrabber = ayum.mediaHandler + self.baseurl = "file://%s" % ayum.tree + elif self.url.startswith("nfs:"): + if self.type == "method": + dest = ayum.tree + else: + dest = tempfile.mkdtemp("", self.name.replace(" ", ""), "/mnt") + + (opts, server, path) = iutil.parseNfsUrl(self.url) + try: + isys.mount(server+":"+path, dest, "nfs", options=opts) + except Exception as e: + log.error("error mounting NFS repo %s: %s" % (self.name, e)) + raise + self.baseurl = "file://%s" % dest + + # This really should be fixed in loader instead but for now see + # if there's images and if so go with this being an NFSISO + # install instead. + if self.type == "method": + images = findIsoImages(ayum.tree, ayum.anaconda.intf.messageWindow) + if images != {}: + isys.umount(ayum.tree, removeDir=False) + self.url = "nfsiso:%s" % self.url[4:] + # TODORV - fix properly? SPOT? + # "nfsiso:" case pasted + ayum.isodir = "/mnt/isodir" + ayum._switchImage(1) + ayum.mediagrabber = ayum.mediaHandler + self.baseurl = "file://%s" % ayum.tree + elif self.url.startswith("nfsiso:"): + ayum.isodir = "/mnt/isodir" + ayum._switchImage(1) + ayum.mediagrabber = ayum.mediaHandler + self.baseurl = "file://%s" % ayum.tree + else: + log.info("repo %s has unsupported url: %s" % (self.name, + self.url)) + if self.isIsoRepo(): + self.mediaid = getMediaId(ayum.tree) + log.info("set mediaid of repo %s to: %s" % (self.id, self.mediaid)) + + return True + + def dirCleanup(self): + if not self.yumrepo: + return False + cachedir = self.yumrepo.getAttribute('cachedir') + if os.path.isdir(cachedir): + # Remove also cached metadata only for non-network repos + # or installation repos or repos that has not been used (enabled). + # TODORV: count also addon installation repos in when implemented + if (not (self.url.startswith("http") or self.url.startswith("ftp")) + or self.type == "method" + or not self.enabled): + shutil.rmtree(cachedir) + else: + if os.path.exists("%s/headers" % cachedir): + shutil.rmtree("%s/headers" % cachedir) + if os.path.exists("%s/packages" % cachedir): + shutil.rmtree("%s/packages" % cachedir) + def isValidRepoURL(url): return (url.startswith("hd:") or url.startswith("nfsiso:") or @@ -464,6 +558,8 @@ class AnacondaYum(YumSorter): self.anaconda = anaconda self._timestamp = None + self.readReposFromConfig = False + self.repoIDcounter = itertools.count() # Only needed for hard drive and nfsiso installs. @@ -586,117 +682,6 @@ class AnacondaYum(YumSorter): discImages=self._discImages) self.currentMedia = discnum - def configBaseURL(self): - # We only have a methodstr if method= or repo= was passed to - # anaconda. No source for this base repo (the CD media, NFS, - # whatever) is mounted yet since loader only mounts the source - # for the stage2 image. We need to set up the source mount - # now. - if flags.cmdline.has_key("preupgrade"): - path = "/var/cache/yum/preupgrade" - self.anaconda.methodstr = "hd::%s" % path - self._baseRepoURL = "file:///mnt/sysimage/%s" % path - elif self.anaconda.methodstr: - m = self.anaconda.methodstr - - if m.startswith("hd:"): - if m.count(":") == 2: - (device, path) = m[3:].split(":") - else: - (device, fstype, path) = m[3:].split(":") - - self.isodir = "/mnt/isodir/%s" % path - - # This takes care of mounting /mnt/isodir first. - self._switchImage(1) - self.mediagrabber = self.mediaHandler - elif m.startswith("nfsiso:"): - self.isodir = "/mnt/isodir" - - # Calling _switchImage takes care of mounting /mnt/isodir first. - if not network.hasActiveNetDev(): - if not self.anaconda.intf.enableNetwork(): - self._baseRepoURL = None - return - - urlgrabber.grabber.reset_curl_obj() - - self._switchImage(1) - self.mediagrabber = self.mediaHandler - elif m.startswith("http") or m.startswith("ftp:"): - self._baseRepoURL = m - elif m.startswith("nfs:"): - if not network.hasActiveNetDev(): - if not self.anaconda.intf.enableNetwork(): - self._baseRepoURL = None - - urlgrabber.grabber.reset_curl_obj() - - (opts, server, path) = iutil.parseNfsUrl(m) - isys.mount(server+":"+path, self.tree, "nfs", options=opts) - - # This really should be fixed in loader instead but for now see - # if there's images and if so go with this being an NFSISO - # install instead. - images = findIsoImages(self.tree, self.anaconda.intf.messageWindow) - if images != {}: - isys.umount(self.tree, removeDir=False) - self.anaconda.methodstr = "nfsiso:%s" % m[4:] - self.configBaseURL() - return - elif m.startswith("cdrom:"): - self._switchCD(1) - self.mediagrabber = self.mediaHandler - self._baseRepoURL = "file://%s" % self.tree - else: - # No methodstr was given. In order to find an installation source, - # we should first check to see if there's a CD/DVD with packages - # on it, and then default to the mirrorlist URL. The user can - # always change the repo with the repo editor later. - cdr = scanForMedia(self.tree, self.anaconda.storage) - if cdr: - self.mediagrabber = self.mediaHandler - self.anaconda.mediaDevice = cdr - self.currentMedia = 1 - log.info("found installation media on %s" % cdr) - else: - # No CD with media on it and no repo=/method= parameter, so - # default to using whatever's enabled in /etc/yum.repos.d/ - self._baseRepoURL = None - - def configBaseRepo(self, root='/'): - # Create the "base" repo object, assuming there is one. Otherwise we - # just skip all this and use the defaults from /etc/yum.repos.d. - if not self._baseRepoURL: - return - - # add default repos - anacondabaseurl = (self.anaconda.methodstr or - "cdrom:%s" % (self.anaconda.mediaDevice)) - anacondabasepaths = self.anaconda.instClass.getPackagePaths(anacondabaseurl) - for (name, uri) in self.anaconda.instClass.getPackagePaths(self._baseRepoURL).items(): - rid = name.replace(" ", "") - - repo = AnacondaYumRepo("anaconda-%s-%s" % (rid, productStamp)) - repo.baseurl = uri - repo.anacondaBaseURLs = anacondabasepaths[name] - - repo.name = name - repo.cost = 100 - - if self.anaconda.mediaDevice or self.isodir: - repo.mediaid = getMediaId(self.tree) - log.info("set mediaid of repo %s to: %s" % (rid, repo.mediaid)) - - if self.anaconda.proxy: - repo.setProxy(self.anaconda) - - if flags.noverifyssl: - repo.sslverify = False - - repo.enable() - self.repos.add(repo) - def mediaHandler(self, *args, **kwargs): mediaid = kwargs["mediaid"] discnum = kwargs["discnum"] @@ -719,8 +704,8 @@ class AnacondaYum(YumSorter): text=kwargs["text"], range=kwargs["range"], copy_local=1) return kwargs["local"] - # XXX: This is straight out of yum, but we need to override it here in - # order to use our own repo class. + # We need to have more control (esp. in UI) over using repos from config + # At some point, after repo selection, we don't want to add them at all. def readRepoConfig(self, parser, section): '''Parse an INI file section for a repository. @@ -728,41 +713,10 @@ class AnacondaYum(YumSorter): @param section: INI file section to read. @return: YumRepository instance. ''' - repo = AnacondaYumRepo(section) - repo.populate(parser, section, self.conf) - - # Ensure that the repo name is set - if not repo.name: - repo.name = section - self.logger.error(_('Repository %r is missing name in configuration, ' - 'using id') % section) - - # Set attributes not from the config file - repo.yumvar.update(self.conf.yumvar) - repo.cfg = parser - - if "-source" in repo.id or "-debuginfo" in repo.id: - name = repo.name - del(repo) - raise RepoError, "Repo %s contains -source or -debuginfo, excluding" % name - - # this is a little hard-coded, but it's effective - if not BETANAG and ("rawhide" in repo.id or "development" in repo.id): - name = repo.name - del(repo) - raise RepoError, "Excluding devel repo %s for non-devel anaconda" % name - - if BETANAG and not repo.enabled: - name = repo.name - del(repo) - raise RepoError, "Excluding disabled repo %s for prerelease" % name - - # If repo=/method= was passed in, we want to default these extra - # repos to off. - if self._baseRepoURL: - repo.enabled = False - - return repo + if not self.readReposFromConfig: + raise RepoError, "Intentionally ignoring .repo configuration file" + else: + return super(AnacondaYum,self).readRepoConfig(parser, section) # We need to make sure $releasever gets set up before .repo files are # read. Since there's no redhat-release package in /mnt/sysimage (and @@ -827,99 +781,6 @@ class AnacondaYum(YumSorter): else: YumSorter._getConfig(self, fn=fn, root=root, enabled_plugins=["whiteout", "blacklist"]) - self.configBaseRepo(root=root) - - extraRepos = [] - - ddArch = os.uname()[4] - - #Add the Driver disc repos to Yum - for d in glob.glob(DD_RPMS): - dirname = os.path.basename(d) - rid = "anaconda-%s" % dirname - - repo = AnacondaYumRepo(rid) - repo.baseurl = [ "file://%s" % d ] - repo.name = "Driver Disk %s" % dirname.split("-")[1] - repo.enable() - extraRepos.append(repo) - - if self.anaconda.ksdata: - for ksrepo in self.anaconda.ksdata.repo.repoList: - anacondaBaseURLs = [ksrepo.baseurl] - - # yum doesn't understand nfs:// and doesn't want to. We need - # to first do the mount, then translate it into a file:// that - # yum does understand. - # "nfs:" and "nfs://" prefixes are accepted in ks repo --baseurl - if ksrepo.baseurl and ksrepo.baseurl.startswith("nfs:"): - if not network.hasActiveNetDev() and not self.anaconda.intf.enableNetwork(): - self.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) - - urlgrabber.grabber.reset_curl_obj() - - dest = tempfile.mkdtemp("", ksrepo.name.replace(" ", ""), "/mnt") - - # handle "nfs://" prefix - if ksrepo.baseurl[4:6] == '//': - ksrepo.baseurl = ksrepo.baseurl.replace('//', '', 1) - anacondaBaseURLs = [ksrepo.baseurl] - try: - isys.mount(ksrepo.baseurl[4:], dest, "nfs") - except Exception as e: - log.error("error mounting NFS repo: %s" % e) - - ksrepo.baseurl = "file://%s" % dest - - repo = AnacondaYumRepo(ksrepo.name) - repo.mirrorlist = ksrepo.mirrorlist - repo.name = ksrepo.name - - if not ksrepo.baseurl: - repo.baseurl = [] - else: - repo.baseurl = [ ksrepo.baseurl ] - repo.anacondaBaseURLs = anacondaBaseURLs - - if ksrepo.cost: - repo.cost = ksrepo.cost - - if ksrepo.excludepkgs: - repo.exclude = ksrepo.excludepkgs - - if ksrepo.includepkgs: - repo.includepkgs = ksrepo.includepkgs - - if ksrepo.noverifyssl: - repo.sslverify = False - - if ksrepo.proxy: - repo.setProxy(ksrepo) - - repo.enable() - extraRepos.append(repo) - - for repo in extraRepos: - try: - self.repos.add(repo) - log.info("added repository %s with URL %s" % (repo.name, repo.mirrorlist or repo.baseurl)) - except: - log.warning("ignoring duplicate repository %s with URL %s" % (repo.name, repo.mirrorlist or repo.baseurl)) - - self.repos.setCacheDir(self.conf.cachedir) - - if os.path.exists("%s/boot/upgrade/install.img" % self.anaconda.rootPath): - log.info("REMOVING stage2 image from %s /boot/upgrade" % self.anaconda.rootPath ) - try: - os.unlink("%s/boot/upgrade/install.img" % self.anaconda.rootPath) - except: - log.warning("failed to clean /boot/upgrade") def downloadHeader(self, po): while True: @@ -1281,6 +1142,113 @@ reposdir=/etc/anaconda.repos.d,/tmp/updates/anaconda.repos.d,/tmp/product/anacon # unhappy (#496961) iutil.resetRpmDb(anaconda.rootPath) + def doCollectRepos(self, anaconda): + """from methodstr, KS, /etc/yumrepos.d, addon (RHEL)""" + if anaconda.dir == DISPATCH_BACK: + return DISPATCH_BACK + + anaconda.repos = [] + + # base install repo + rs = YumRepoSpec() + + # special preupgrade case + if flags.cmdline.has_key("preupgrade"): + path = "/var/cache/yum/preupgrade" + rs.url = "hd::%s" % path + rs.baseurl = "file:///mnt/sysimage/%s" % path + rs.type = "preupgrade" + self.anaconda.repos.append(rs) + rs.name = "Preupgrade Repo" + else: + # method=/repo= - base installation repository + m = self.anaconda.methodstr + if not m: + cdr = scanForMedia(self.tree, self.anaconda.storage) + if cdr: + log.info("found installation media on %s" % cdr) + rs.media_device = cdr + m = "cdrom://" + else: + m = "" + if isValidRepoURL(m): + rs.url = m + rs.name = "Installation Repo" + rs.type = "method" + rs.cost = 100 + rs.enabled = True + if self.anaconda.proxy: + rs.setProxy(self.anaconda) + if flags.noverifyssl: + rs.sslverify = False + self.anaconda.repos.append(rs) + + # DD repos + for d in glob.glob(DD_RPMS): + rs = YumRepoSpec() + dirname = os.path.basename(d) + rs.url = "file://%s" + rs.name = "Driver Disk %s" % dirname.split("-")[1] + rs.type = "driverdisc" + rs.enabled = True + self.anaconda.repos.append(rs) + + # ks repos + if self.anaconda.ksdata: + for ksrepo in self.anaconda.ksdata.repo.repoList: + rs = YumRepoSpec() + baseurl = ksrepo.baseurl or ksrepo.mirrorlist or "" + # change "nfs://" prefix to "nfs:" + if baseurl.startswith("nfs://"): + baseurl = baseurl.replace('//', '', 1) + if isValidRepoURL(baseurl): + rs.url = baseurl + if ksrepo.mirrorlist: + rs.mirrorlist = True + rs.type = "kickstart" + rs.name = ksrepo.name + rs.enabled = True + if ksrepo.excludepkgs: + rs.excludepkgs = ksrepo.excludepkgs + if ksrepo.includepkgs: + rs.includepkgs = ksrepo.includepkgs + if ksrepo.noverifyssl: + rs.sslverify = False + if ksrepo.proxy: + rs.setProxy(ksrepo) + else: + log.info("Kickstart repository with invalid url %s ignored" + % baseurl) + self.anaconda.repos.append(rs) + + # addon repos (rhel only?) + + # config repos (.repo) + ayum = AnacondaYum(anaconda) + ayum.readReposFromConfig = True + ayum.doConfigSetup() + for repo in ayum.repos.repos.values(): + if "-source" in repo.id or "-debuginfo" in repo.id: + log.info("Repo %s contains -source or -debuginfo, excluding" % + repo.name) + continue + if not BETANAG and ("rawhide" in repo.id or "development" in repo.id): + log.info("Excluding devel repo %s for non-devel anaconda" % + repo.name) + continue + if BETANAG and not repo.enabled: + log.info("Excluding disabled repo %s for prerelease" % repo.name) + continue + + # If repo=/method= was passed in, we want to default these extra + # repos to off. + if [rs for rs in self.anaconda.repos if rs.type == "method"]: + repo.enabled = False + rs = YumRepoSpec(yumrepo=repo) + rs.type = "config" + self.anaconda.repos.append(rs) + ayum.readReposFromConfig = False + def doBackendSetup(self, anaconda): if anaconda.dir == DISPATCH_BACK: return DISPATCH_BACK -- 1.7.2 _______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list