--- docs/driverdisc.txt | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 125 insertions(+), 0 deletions(-) create mode 100644 docs/driverdisc.txt
diff --git a/docs/driverdisc.txt b/docs/driverdisc.txt new file mode 100644 index 0000000..5075989 --- /dev/null +++ b/docs/driverdisc.txt @@ -0,0 +1,125 @@ +Brief description of DriverDisc version 3 +========================================== + +For a new major release we decided to introduce a new version of DriverDisc +feature to ensure the smoothest vendor and user experience possible. We had +many reasons for it: + +- the old DD didn't support multiple architectures +- the old DD wasn't particulary easy to create +- the old DD had two copys of modules, one for anaconda and one for + instalation +- the modules in old DD weren't checked for kernel version + +We also changed the feature internal code to enable some functionality that +was missing from the old version. More about it below. + +Devices which can contain DDs +----------------------------- + +The best place to save your DriverDisc to is USB flash device. We also support +(or plan to) IDE and SATA block devices with or without partitions, DriverDisc +image stored on block device, initrd overlay (see documentation below) and for +special cases even network retrieval of DriverDisc image. + +What can be updated using DDs? +------------------------------ + +All drivers for block devices, which weren't used for retrieving DriverDiscs, +the same applies also for network drivers eg. you cannot upgrade network +driver for device, which was used prior the DriverDisc extraction. + +RPMs for installation. If the DriverDisc repo contains newer package, than the +official repository, the newer package will get used. + +We also plan to support anaconda's updates.img placement on the DriverDisc to +update stage2 behaviour of anaconda. + +Selecting DD manually +--------------------- + +There are two ways of triggering DD mode and loading updated drivers manually. + +The first is using 'dd=<location>' argument on the kernel command line during +installation boot. + +Second way is by using only 'dd' argument on the command line and then using +the TUI provided by anaconda to select DriverDisc's source location. + +Documentation for current release will provide more details as this wasn't +changed. + +Automatic DriverDisc detection +------------------------------ + +Anaconda can be told to look for driverdisc automatically by using 'dlabel=on' +kernel command line argument. This is enabled by default in Red Hat Enterprise +Linux version of Anaconda. + +The DriverDisc has to be on partition or filesystem which has been labeled +with 'oemdrv' label. + + +DDv3 structure +-------------- + +The new DriverDisc format uses simple layout which can be created on top of +any anaconda's supported filesystem (vfat, squashfs, ext2 and ext3). + +/ +|rhdd3 - DD marker, contains the DD's description string +/rpms +| /i386 - contains RPMs for this arch and acts as Yum repo +| /i586 +| /x86_64 +| /ppc +| /... - any other architecture the DD provides drivers for + +There is a special requirement for the RPMs used to update drivers. Anaconda +picks up only RPMs which provide kernel-modules-<running kernel version>. + +Initrd overlay driverdisc image +------------------------------- + +We have designed another possible way of providing updates in network boot +environments. It is possible to update all modules this way, so if special +storage module (which gets used early) needs to be updated, this is the +preffered way. + +This kind of driverdisc image is applied over the standard initrd and so has +to respect some rules. + +- All updated modules belong to /lib/modules/<kernel version>/.. according to + their usual location +- All new modules belong to /tmp/DD/lib/modules +- All new firmware files belong to /tmp/DD/lib/firmware +- The rpm repo with updated packages belongs to /tmp/DD-initrd/ +- The (empty) trigger file /.rundepmod must be present + +Firmware and module update +-------------------------- + +The firmware files together with all .ko files from the RPMs are exploded to +special module location, which has preference over built-in Anaconda modules. + +Anaconda doesn't use built-in modules (except some storage modules needed for +the DD to function properly) during the DriverDisc mode, so even in case when +you are updating some modules with second (or later) DriverDisc, the updated +modules will be loaded. There is one exception though, if your module depends +on a module which is only present in built-in module directory, that built-in +module gets also loaded. + +Package installation +-------------------- + +It is also possible to include arbitrary packages on the DriverDisc media and +mark them for installation. You just have to include the package name in the +Yum repo for correct architecture and mark it as mandatory. + + +Summary +------- + +This new DriverDisc format should simplify the DD creation and usage a lot. We +will gladly hear any comments as this is partially still work in progress. +
On 12/21/2009 04:21 PM, Martin Sivak wrote:
docs/driverdisc.txt | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 125 insertions(+), 0 deletions(-) create mode 100644 docs/driverdisc.txt
I think this hasn't changed much since I acked it the first time. So it's fine.
On 01/05/2010 10:55 AM, Ales Kozumplik wrote:
On 12/21/2009 04:21 PM, Martin Sivak wrote:
docs/driverdisc.txt | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 125 insertions(+), 0 deletions(-) create mode 100644 docs/driverdisc.txt
I think this hasn't changed much since I acked it the first time. So it's fine.
Oh except one thing --- who is supposed to update this wiki: http://fedoraproject.org/wiki/Anaconda/Options
with the new dlabel option?
Ales
Oh except one thing --- who is supposed to update this wiki: http://fedoraproject.org/wiki/Anaconda/Options
with the new dlabel option?
It works best if people update the wiki as they add new options. I try to keep the kickstart one up to date as I make kickstart changes, and I try to keep the Options one up to date as well. But since everyone makes changes there, it's a little harder for me to keep up.
It's probably worth auditing that page before RHEL6.
- Chris
--- anaconda.spec.in | 3 + loader/Makefile.am | 6 +- loader/rpmextract.c | 325 +++++++++++++++++++++++++++++++++++++++++++++++++++ loader/rpmextract.h | 45 +++++++ 4 files changed, 377 insertions(+), 2 deletions(-) create mode 100644 loader/rpmextract.c create mode 100644 loader/rpmextract.h
diff --git a/anaconda.spec.in b/anaconda.spec.in index c1689ae..8133451 100644 --- a/anaconda.spec.in +++ b/anaconda.spec.in @@ -55,6 +55,7 @@ BuildRequires: gettext >= %{gettextver} BuildRequires: gtk2-devel BuildRequires: intltool >= %{intltoolver} BuildRequires: isomd5sum-devel +BuildRequires: libarchive-devel BuildRequires: libX11-devel BuildRequires: libXt-devel BuildRequires: libXxf86misc-devel @@ -69,6 +70,7 @@ BuildRequires: pango-devel BuildRequires: pykickstart >= %{pykickstartver} BuildRequires: python-devel BuildRequires: python-urlgrabber +BuildRequires: rpm-devel BuildRequires: rpm-python >= %{rpmpythonver} BuildRequires: slang-devel >= %{slangver} BuildRequires: xmlto @@ -103,6 +105,7 @@ Requires: device-mapper-libs >= %{dmver} Requires: dosfstools Requires: e2fsprogs >= %{e2fsver} Requires: gzip +Requires: libarchive %ifarch %{ix86} x86_64 ia64 Requires: dmidecode %endif diff --git a/loader/Makefile.am b/loader/Makefile.am index e5d1b7f..e9e12c9 100644 --- a/loader/Makefile.am +++ b/loader/Makefile.am @@ -45,13 +45,15 @@ loader_CFLAGS = $(COMMON_CFLAGS) $(GLIB_CFLAGS) $(LIBNM_GLIB_CFLAGS) \ loader_LDADD = $(NEWT_LIBS) $(GLIB_LIBS) $(LIBNL_LIBS) \ $(LIBNM_GLIB_LIBS) $(CHECKISOMD5_LIBS) \ $(LIBCURL_LIBS) \ - $(ISCSI_LIBS) $(top_srcdir)/isys/libisys.la + $(ISCSI_LIBS) $(top_srcdir)/isys/libisys.la \ + -lrpm -lrpmio -larchive loader_SOURCES = loader.c copy.c log.c moduleinfo.c loadermisc.c \ modules.c windows.c lang.c kbd.c driverdisk.c \ selinux.c mediacheck.c kickstart.c driverselect.c \ getparts.c dirbrowser.c fwloader.c ibft.c hardware.c \ method.c cdinstall.c hdinstall.c nfsinstall.c \ - urlinstall.c net.c urls.c telnet.c telnetd.c + urlinstall.c net.c urls.c telnet.c telnetd.c \ + rpmextract.c
init_CFLAGS = $(COMMON_CFLAGS) init_SOURCES = init.c undomounts.c shutdown.c copy.c diff --git a/loader/rpmextract.c b/loader/rpmextract.c new file mode 100644 index 0000000..64d5d7d --- /dev/null +++ b/loader/rpmextract.c @@ -0,0 +1,325 @@ +/* unpack the payload of RPM package to the current directory + * + * File name: rpmextract.c + * Date: 2009/12/18 + * Author: Martin Sivak <msivak at redhat dot com> + * + * Copyright (C) 2009 Red Hat, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + * + * */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <rpm/rpmlib.h> /* rpmReadPackageFile .. */ +#include <rpm/rpmtag.h> +#include <rpm/rpmio.h> +#include <rpm/rpmpgp.h> + +#include <rpm/rpmts.h> + +#include <stdio.h> +#include <archive.h> +#include <archive_entry.h> + +#include "loader.h" +#include "log.h" +#include "rpmextract.h" + +/* + * internal structure to pass to libarchive callbacks + */ + +struct cpio_mydata { + FD_t gzdi; + char *buffer; +}; + +/* + * libarchive callbacks + */ + +ssize_t rpm_myread(struct archive *a, void *client_data, const void **buff) +{ + struct cpio_mydata *mydata = client_data; + *buff = mydata->buffer; + return Fread(mydata->buffer, BUFFERSIZE, 1, mydata->gzdi); +} + +int rpm_myclose(struct archive *a, void *client_data) +{ + struct cpio_mydata *mydata = client_data; + if (mydata->gzdi > 0) + Fclose(mydata->gzdi); + return ARCHIVE_OK; +} + +/* read data from RPM header */ + +const char * headerGetString(Header h, rpmTag tag) +{ + const char *res = NULL; + struct rpmtd_s td; + + if (headerGet(h, tag, &td, HEADERGET_MINMEM)) { + if (rpmtdCount(&td) == 1) { + res = rpmtdGetString(&td); + } + rpmtdFreeData(&td); + } + return res; +} + +/* + * explode source RPM into the current directory + * use filters to skip packages and files we do not need + */ +int explodeRPM(const char *source, + filterfunc filter, + dependencyfunc provides, + dependencyfunc deps, + void* userptr) +{ + char buffer[BUFFERSIZE+1]; /* make space for trailing \0 */ + FD_t fdi; + Header h; + char * rpmio_flags = NULL; + rpmRC rc; + FD_t gzdi; + struct archive *cpio; + struct archive_entry *cpio_entry; + struct cpio_mydata cpio_mydata; + + rpmts ts; + rpmVSFlags vsflags; + const char *compr; + + if (strcmp(source, "-") == 0) + fdi = fdDup(STDIN_FILENO); + else + fdi = Fopen(source, "r.ufdio"); + + if (Ferror(fdi)) { + const char *srcname = (strcmp(source, "-") == 0) ? "<stdin>" : source; + logMessage(ERROR, "%s: %s\n", srcname, Fstrerror(fdi)); + return EXIT_FAILURE; + } + rpmReadConfigFiles(NULL, NULL); + + /* Initialize RPM transaction */ + ts = rpmtsCreate(); + vsflags = 0; + + /* Do not check digests, signatures or headers */ + vsflags |= _RPMVSF_NODIGESTS; + vsflags |= _RPMVSF_NOSIGNATURES; + vsflags |= RPMVSF_NOHDRCHK; + (void) rpmtsSetVSFlags(ts, vsflags); + + rc = rpmReadPackageFile(ts, fdi, "rpm2dir", &h); + + ts = rpmtsFree(ts); + + switch (rc) { + case RPMRC_OK: + case RPMRC_NOKEY: + case RPMRC_NOTTRUSTED: + break; + case RPMRC_NOTFOUND: + logMessage(ERROR, "%s is not an RPM package", source); + return EXIT_FAILURE; + break; + case RPMRC_FAIL: + default: + logMessage(ERROR, "error reading header from %s package\n", source); + return EXIT_FAILURE; + break; + } + + /* Retrieve all dependencies and run them through deps function */ + while (deps) { + struct rpmtd_s td; + const char *depname; + + if (!headerGet(h, RPMTAG_REQUIRENAME, &td, HEADERGET_MINMEM)) + break; + + /* iterator */ + while ((depname = rpmtdNextString(&td))) { + if (deps(depname, userptr)) { + Fclose(fdi); + return EXIT_BADDEPS; + } + } + rpmtdFreeData(&td); + break; + } + + /* Retrieve all provides and run them through provides function */ + while (provides) { + struct rpmtd_s td; + const char *depname; + int found = 0; + + if (!headerGet(h, RPMTAG_PROVIDES, &td, HEADERGET_MINMEM)) + break; + + /* iterator */ + while ((depname = rpmtdNextString(&td))) { + if (!provides(depname, userptr)) { + found++; + } + } + rpmtdFreeData(&td); + if (found<=0) + return EXIT_BADDEPS; + break; + } + + /* Retrieve type of payload compression. */ + compr = headerGetString(h, RPMTAG_PAYLOADCOMPRESSOR); + if (compr && strcmp(compr, "gzip")) { + checked_asprintf(&rpmio_flags, "r.%sdio", compr); + } + else { + checked_asprintf(&rpmio_flags, "r.gzdio"); + } + + /* Open uncompressed cpio stream */ + gzdi = Fdopen(fdi, rpmio_flags); + free(rpmio_flags); + + if (gzdi == NULL) { + logMessage(ERROR, "cannot re-open payload: %s\n", Fstrerror(gzdi)); + return EXIT_FAILURE; + } + + /* initialize cpio decompressor */ + cpio = archive_read_new(); + if (cpio==NULL) { + Fclose(gzdi); + return -1; + } + + cpio_mydata.gzdi = gzdi; + cpio_mydata.buffer = buffer; + archive_read_support_compression_all(cpio); + archive_read_support_format_all(cpio); + rc = archive_read_open(cpio, &cpio_mydata, NULL, rpm_myread, rpm_myclose); + + /* check the status of archive_open */ + if (rc != ARCHIVE_OK){ + Fclose(gzdi); + return -1; + } + + /* read all files in cpio archive */ + while ((rc = archive_read_next_header(cpio, &cpio_entry)) == ARCHIVE_OK){ + const struct stat *fstat; + int64_t fsize; + const char* filename; + int needskip = 1; /* do we need to read the data to get to the next header? */ + int offset = 0; + int towrite = 0; + + filename = archive_entry_pathname(cpio_entry); + fstat = archive_entry_stat(cpio_entry); + fsize = archive_entry_size(cpio_entry); + + /* Strip leading slashes */ + while (filename[offset] == '/') + offset+=1; + + /* Strip leading ./ */ + while (filename[offset] == '.' && filename[offset+1] == '/') + offset+=2; + + /* Other file type - we do not care except special cases */ + if (!S_ISREG(fstat->st_mode)) + towrite = 1; + else + towrite = 2; + + if (filter && filter(filename+offset, fstat, userptr)) { + /* filter this file */ + towrite = 0; + } + + /* Create directories */ + char* dirname = strdup(filename+offset); + + /* If the dup fails, let's hope the dirs already exist */ + if (dirname){ + char* dirptr = dirname; + while (dirptr && *dirptr) { + dirptr = strchr(dirptr, '/'); + if (dirptr) { + *dirptr = 0; + mkdir(dirname, 0700); + *dirptr = '/'; + dirptr++; + } + } + free(dirname); + } + + /* Regular file */ + if (towrite>=2) { + FILE *fdout = fopen(filename+offset, "w"); + + if (fdout==NULL){ + free((void*)filename); + rc = 33; + break; + } + + rc = archive_read_data_into_fd(cpio, fileno(fdout)); + if (rc!=ARCHIVE_OK) { + /* XXX We didn't get the file.. well.. */ + needskip = 0; + } else { + needskip = 0; + fclose(fdout); + } + } + + /* symlink, we assume that the path contained in symlink + * is shorter than BUFFERSIZE */ + while (towrite && S_ISLNK(fstat->st_mode)) { + char symlinkbuffer[BUFFERSIZE-1]; + + needskip = 0; + if ((rc = archive_read_data(cpio, symlinkbuffer, fsize))!=ARCHIVE_OK) { + /* XXX We didn't get the file.. well.. */ + break; + } + + if (symlink(buffer, filename+offset)) { + logMessage(ERROR, "Failed to create symlink %s -> %s", filename+offset, buffer); + } + + break; + } + + if(needskip) + archive_read_data_skip(cpio); + } + + archive_read_finish(cpio); + + return rc != ARCHIVE_OK; +} diff --git a/loader/rpmextract.h b/loader/rpmextract.h new file mode 100644 index 0000000..53a90cf --- /dev/null +++ b/loader/rpmextract.h @@ -0,0 +1,45 @@ +/* + File name: rpmextract.h + Date: 2009/09/16 + Author: msivak + + Copyright (C) 2009 Red Hat, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see http://www.gnu.org/licenses/. +*/ + + +#ifndef __RPMEXTRACT_H__ +#define __RPMEXTRACT_H__ + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#define EXIT_BADDEPS 4 +#define BUFFERSIZE 1024 + +/* both filter functions return 0 - match, 1 - match not found */ +typedef int (*filterfunc)(const char* name, const struct stat *fstat, void *userptr); +typedef int (*dependencyfunc)(const char* depends, void *userptr); + +int explodeRPM(const char* file, + filterfunc filter, + dependencyfunc provides, + dependencyfunc deps, + void* userptr); + +#endif + +/* end of rpmextract.h */
On 12/21/2009 04:21 PM, Martin Sivak wrote:
anaconda.spec.in | 3 + loader/Makefile.am | 6 +- loader/rpmextract.c | 325 +++++++++++++++++++++++++++++++++++++++++++++++++++ loader/rpmextract.h | 45 +++++++ 4 files changed, 377 insertions(+), 2 deletions(-) create mode 100644 loader/rpmextract.c create mode 100644 loader/rpmextract.h
diff --git a/anaconda.spec.in b/anaconda.spec.in index c1689ae..8133451 100644
This looks good.
/* Strip leading slashes */
while (filename[offset] == '/')
offset+=1;
/* Strip leading ./ */
while (filename[offset] == '.' && filename[offset+1] == '/')
offset+=2;
I think you're still going to have the problem with "/", ".", "./" that pjones mentioned in https://www.redhat.com/archives/anaconda-devel-list/2009-December/msg00416.h... here.
if (fdout==NULL){
free((void*)filename);
rc = 33;
break;
}
I don't think you need to cast this.
- Chris
----- "Chris Lumens" clumens@redhat.com wrote:
/* Strip leading slashes */
while (filename[offset] == '/')
offset+=1;
/* Strip leading ./ */
while (filename[offset] == '.' && filename[offset+1] ==
'/')
offset+=2;
I think you're still going to have the problem with "/", ".", "./" that pjones mentioned in https://www.redhat.com/archives/anaconda-devel-list/2009-December/msg00416.h... here.
No I won't... the memory looks like this:
['.', '\0'] or ['.', '/', '\0'] or ['/', '\0']
So it will end up as empty string, but it definitely won't segfault, because '\0' won't match neither '/' nor '.'.
if (fdout==NULL){
free((void*)filename);
rc = 33;
break;
}
I don't think you need to cast this.
My GCC thinks I do for some reason. It didn't build without this... I tried. (it was just a warning, but we are converting them to errors)
Martin
No I won't... the memory looks like this:
['.', '\0'] or ['.', '/', '\0'] or ['/', '\0']
So it will end up as empty string, but it definitely won't segfault, because '\0' won't match neither '/' nor '.'.
Yep, okay.
I don't think you need to cast this.
My GCC thinks I do for some reason. It didn't build without this... I tried. (it was just a warning, but we are converting them to errors)
Huh, that's strange. What version of gcc is it?
- Chris
I was testing it with this:
gcc (GCC) 4.4.1 20090725 (Red Hat 4.4.1-2)
----- "Chris Lumens" clumens@redhat.com wrote:
No I won't... the memory looks like this:
['.', '\0'] or ['.', '/', '\0'] or ['/', '\0']
So it will end up as empty string, but it definitely won't
segfault,
because '\0' won't match neither '/' nor '.'.
Yep, okay.
I don't think you need to cast this.
My GCC thinks I do for some reason. It didn't build without this...
I
tried. (it was just a warning, but we are converting them to
errors)
Huh, that's strange. What version of gcc is it?
- Chris
Anaconda-devel-list mailing list Anaconda-devel-list@redhat.com https://www.redhat.com/mailman/listinfo/anaconda-devel-list
On Wed, 6 Jan 2010, Martin Sivak wrote:
----- "Chris Lumens" clumens@redhat.com wrote:
if (fdout==NULL){
free((void*)filename);
rc = 33;
break;
}
I don't think you need to cast this.
My GCC thinks I do for some reason. It didn't build without this... I tried. (it was just a warning, but we are converting them to errors)
Well, filename is declared as const char* so passing it to free() will certainly complain. The question is: are you *really* supposed to free anything coming from archive_entry_pathname()? It's only getting freed in an unlikely error path here, so either its leaking memory or the free() here is just wrong.
- Panu -
Looks like you are right. The free seems to be just a leftover from the previous version. libarchive documentation about this is not existing though..
Martin
----- "Panu Matilainen" pmatilai@laiskiainen.org wrote:
On Wed, 6 Jan 2010, Martin Sivak wrote:
----- "Chris Lumens" clumens@redhat.com wrote:
if (fdout==NULL){
free((void*)filename);
rc = 33;
break;
}
I don't think you need to cast this.
My GCC thinks I do for some reason. It didn't build without this...
I
tried. (it was just a warning, but we are converting them to
errors)
Well, filename is declared as const char* so passing it to free() will
certainly complain. The question is: are you *really* supposed to free
anything coming from archive_entry_pathname()? It's only getting freed in an unlikely error path here, so either its leaking memory or the free() here is just wrong.
- Panu -
Anaconda-devel-list mailing list Anaconda-devel-list@redhat.com https://www.redhat.com/mailman/listinfo/anaconda-devel-list
--- isys/isys.py | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/isys/isys.py b/isys/isys.py index 44f9d3d..1d6e88d 100755 --- a/isys/isys.py +++ b/isys/isys.py @@ -390,6 +390,15 @@ def ext2HasJournal(device): hasjournal = _isys.e2hasjournal(device); return hasjournal
+def modulesWithPaths(): + mods = [] + for modline in open("/proc/modules", "r"): + modName = modline.split(" ", 1)[0] + modInfo = os.popen("modinfo -F filename '%s'" % (modName,)).readlines() + modPaths = [ line.strip() for line in modInfo if line!="" ] + mods.extend(modPaths) + return mods + def driveUsesModule(device, modules): """Returns true if a drive is using a prticular module. Only works for SCSI devices right now."""
modName = modline.split(" ", 1)[0]
modInfo = os.popen("modinfo -F filename '%s'" % (modName,)).readlines()
modPaths = [ line.strip() for line in modInfo if line!="" ]
I accidentally found out that os.popen is obsolete. So I would be against using it in a new code.
modName = modline.split(" ", 1)[0]
modInfo = os.popen("modinfo -F filename '%s'" % (modName,)).readlines()
modPaths = [ line.strip() for line in modInfo if line!="" ]
I accidentally found out that os.popen is obsolete. So I would be against using it in a new code.
They likely want you to use subprocess, which execWithCapture in iutil.py uses.
- Chris
But making isys dependend on iutil, does it seem wise? It should be the other way around, shouldn't it?
Martin
----- "Chris Lumens" clumens@redhat.com wrote:
modName = modline.split(" ", 1)[0]
modInfo = os.popen("modinfo -F filename '%s'" %
(modName,)).readlines()
modPaths = [ line.strip() for line in modInfo if line!=""
]
I accidentally found out that os.popen is obsolete. So I would be against using it in a new code.
They likely want you to use subprocess, which execWithCapture in iutil.py uses.
- Chris
Anaconda-devel-list mailing list Anaconda-devel-list@redhat.com https://www.redhat.com/mailman/listinfo/anaconda-devel-list
But making isys dependend on iutil, does it seem wise? It should be the other way around, shouldn't it?
Wise or not, isys already depends on iutil:
clumens@localhost:~/src/anaconda$ grep iutil isys/isys.py import iutil if not iutil.isX86(): if iutil.isS390(): if not iutil.isX86():
- Chris
--- scripts/mk-images | 7 ++++++- scripts/upd-instroot | 1 + 2 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/scripts/mk-images b/scripts/mk-images index c3b1686..fd4ab11 100755 --- a/scripts/mk-images +++ b/scripts/mk-images @@ -328,6 +328,11 @@ makemoduletree() { esac done
+ # create depmod.conf to support DDs + cat > $MMB_DIR/etc/depmod.conf << EOF +search /tmp/DD/lib/modules built-in +EOF + # clean up leftover cruft find -H $MMB_DIR/lib/modules -type d -exec rmdir -f {} ; 2>/dev/null $MODLIST --modinfo-file $MODINFO --ignore-missing --modinfo \ @@ -808,7 +813,7 @@ makeinitrd() {
makeproductfile $MBD_DIR
- for n in insmod rmmod modprobe; do + for n in insmod rmmod modprobe depmod; do instbin $IMGPATH /usr/sbin/$n $MBD_DIR /sbin/$n done
diff --git a/scripts/upd-instroot b/scripts/upd-instroot index 2a79ebf..8539cdd 100755 --- a/scripts/upd-instroot +++ b/scripts/upd-instroot @@ -780,6 +780,7 @@ sbin/insmod sbin/lsmod sbin/modinfo sbin/modprobe +sbin/depmod sbin/netstat sbin/restore sbin/rrestore
On 12/21/2009 04:21 PM, Martin Sivak wrote:
scripts/mk-images | 7 ++++++- scripts/upd-instroot | 1 + 2 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/scripts/mk-images b/scripts/mk-images index c3b1686..fd4ab11 100755 --- a/scripts/mk-images +++ b/scripts/mk-images @@ -328,6 +328,11 @@ makemoduletree() { esac done
- # create depmod.conf to support DDs
- cat> $MMB_DIR/etc/depmod.conf<< EOF
+search /tmp/DD/lib/modules built-in +EOF
# clean up leftover cruft find -H $MMB_DIR/lib/modules -type d -exec rmdir -f {} \; 2>/dev/null $MODLIST --modinfo-file $MODINFO --ignore-missing --modinfo \
@@ -808,7 +813,7 @@ makeinitrd() {
makeproductfile $MBD_DIR
- for n in insmod rmmod modprobe; do
- for n in insmod rmmod modprobe depmod; do instbin $IMGPATH /usr/sbin/$n $MBD_DIR /sbin/$n done
diff --git a/scripts/upd-instroot b/scripts/upd-instroot index 2a79ebf..8539cdd 100755 --- a/scripts/upd-instroot +++ b/scripts/upd-instroot @@ -780,6 +780,7 @@ sbin/insmod sbin/lsmod sbin/modinfo sbin/modprobe +sbin/depmod sbin/netstat sbin/restore sbin/rrestore
ACK, if you haven't tried making a build with the modified scripts then let's hope it won't break it.
And adapt it to use glib and better string handling functions --- loader/driverdisk.c | 344 +++++++++++++++++++++++++++++++++++++++++++++------ loader/driverdisk.h | 12 ++ 2 files changed, 316 insertions(+), 40 deletions(-)
diff --git a/loader/driverdisk.c b/loader/driverdisk.c index 5f8d43c..7c04447 100644 --- a/loader/driverdisk.c +++ b/loader/driverdisk.c @@ -30,6 +30,12 @@ #include <unistd.h> #include <glib.h>
+#include <blkid/blkid.h> + +#include <glob.h> +#include <rpm/rpmlib.h> +#include <sys/utsname.h> + #include "copy.h" #include "loader.h" #include "log.h" @@ -48,6 +54,8 @@ #include "nfsinstall.h" #include "urlinstall.h"
+#include "rpmextract.h" + #include "../isys/isys.h" #include "../isys/imount.h" #include "../isys/eddsupport.h" @@ -55,37 +63,197 @@ /* boot flags */ extern uint64_t flags;
-static char * driverDiskFiles[] = { "modinfo", "modules.dep", - "modules.cgz", "modules.alias", NULL }; +/* modprobe DD mode */ +int modprobeDDmode(void) +{ + FILE *f = fopen("/etc/depmod.d/ddmode.conf", "w"); + if (f) { + struct utsname unamedata; + + if (uname(&unamedata)) + fprintf(f, " pblacklist /lib/modules\n"); + else + fprintf(f, " pblacklist /lib/modules/%s\n", unamedata.release); + fclose(f); + } + + return f==NULL; +} + +int modprobeNormalmode(void) +{ + /* remove depmod overrides */ + if (unlink("/etc/depmod.d/ddmode.conf")) { + logMessage(ERROR, "removing ddmode.conf failed"); + return -1; + } + + /* run depmod to refresh modules db */ + if (system("depmod -a")) { + logMessage(ERROR, "depmod -a failed"); + return -1; + } + + return 0; +} + +/* + * check if the RPM in question provides + * Provides: userptr + * we use it to check kernel-modules-<kernelversion> + */ +int dlabelProvides(const char* dep, void *userptr) +{ + char *kernelver = (char*)userptr; + + logMessage(DEBUGLVL, "Provides: %s\n", dep); + + return strcmp(dep, kernelver); +} + +/* + * during cpio extraction, only extract files we need + * eg. module .ko files and firmware directory + */ +int dlabelFilter(const char* name, const struct stat *fstat, void *userptr) +{ + int l = strlen(name); + + logMessage(DEBUGLVL, "Unpacking %s (%lluB)\n", name, fstat->st_size); + + /* we want firmware files */ + if (!strncmp("lib/firmware/", name, 13)) return 0; + + if (l<3) + return 1; + l-=3; + + /* and we want only .ko files */ + if (strcmp(".ko", name+l)) + return 1; + + /* TODO we are unpacking kernel module, read it's description */ + + return 0; +} + +char* moduleDescription(const char* modulePath) +{ + char *command = NULL; + FILE *f = NULL; + char *description = NULL; + int size; + + checked_asprintf(&command, "modinfo --description '%s'", modulePath); + f = popen(command, "r"); + free(command); + + if (f==NULL) + return NULL; + + description = malloc(sizeof(char)*256); + if (!description) + return NULL; + + size = fread(description, 1, 255, f); + if (size == 0) { + free(description); + return NULL; + } + + description[size-1]=0; /* strip the trailing newline */ + pclose(f); + + return description; +} + +int globErrFunc(const char *epath, int eerrno) +{ + /* TODO check fatal errors */ + + return 0; +} + +int dlabelUnpackRPMDir(char* rpmdir, char* destination) +{ + char *kernelver; + struct utsname unamedata; + char *oldcwd; + char *globpattern; + int rc; + + /* get current working directory */ + oldcwd = getcwd(NULL, 0); + if (!oldcwd) { + logMessage(ERROR, "getcwd() failed: %m"); + return 1; + } + + /* set the cwd to destination */ + if (chdir(destination)) { + logMessage(ERROR, "We weren't able to CWD to "%s": %m", destination); + free(oldcwd); + return 1; + } + + /* get running kernel version */ + rc = uname(&unamedata); + checked_asprintf(&kernelver, "kernel-modules-%s", + rc ? "unknown" : unamedata.release); + logMessage(DEBUGLVL, "Kernel version: %s\n", kernelver); + + checked_asprintf(&globpattern, "%s/*.rpm", rpmdir); + glob_t globres; + char** globitem; + if (!glob(globpattern, GLOB_NOSORT|GLOB_NOESCAPE, globErrFunc, &globres)) { + /* iterate over all rpm files */ + globitem = globres.gl_pathv; + while (globres.gl_pathc>0 && globitem != NULL) { + explodeRPM(*globitem, dlabelFilter, dlabelProvides, NULL, kernelver); + } + globfree(&globres); + /* end of iteration */ + } + free(globpattern); + + /* restore CWD */ + if (chdir(oldcwd)) { + logMessage(WARNING, "We weren't able to restore CWD to "%s": %m", oldcwd); + } + + /* cleanup */ + free(kernelver); + free(oldcwd); + return rc; +} + + +static char * driverDiskFiles[] = { "repodata", NULL };
static int verifyDriverDisk(char *mntpt) { char ** fnPtr; char file[200]; struct stat sb;
- for (fnPtr = driverDiskFiles; *fnPtr; fnPtr++) { - sprintf(file, "%s/%s", mntpt, *fnPtr); - if (access(file, R_OK)) { - logMessage(ERROR, "cannot find %s, bad driver disk", file); - return LOADER_BACK; - } - } - - /* check for both versions */ - sprintf(file, "%s/rhdd", mntpt); + /* check for dd descriptor */ + sprintf(file, "%s/rhdd3", mntpt); if (access(file, R_OK)) { - logMessage(DEBUGLVL, "not a new format driver disk, checking for old"); - sprintf(file, "%s/rhdd-6.1", mntpt); - if (access(file, R_OK)) { - logMessage(ERROR, "can't find either driver disk identifier, bad " - "driver disk"); - } + logMessage(ERROR, "can't find driver disk identifier, bad " + "driver disk"); + return LOADER_BACK; }
/* side effect: file is still mntpt/ddident */ stat(file, &sb); if (!sb.st_size) return LOADER_BACK; + for (fnPtr = driverDiskFiles; *fnPtr; fnPtr++) { + snprintf(file, 200, "%s/%s/%s", mntpt, getProductArch(), *fnPtr); + if (access(file, R_OK)) { + logMessage(ERROR, "cannot find %s, bad driver disk", file); + return LOADER_BACK; + } + }
return LOADER_OK; } @@ -101,25 +269,20 @@ static void copyErrorFn (char *msg) { /* this copies the contents of the driver disk to a ramdisk and loads * the moduleinfo, etc. assumes a "valid" driver disk mounted at mntpt */ static int loadDriverDisk(struct loaderData_s *loaderData, char *mntpt) { - moduleInfoSet modInfo = loaderData->modInfo; - char file[200], dest[200]; + /* FIXME moduleInfoSet modInfo = loaderData->modInfo; */ + char file[200], dest[200], src[200]; char *title; char *fwdir = NULL; struct moduleBallLocation * location; struct stat sb; static int disknum = 0; - int version = 1; int fd, ret;
- /* check for both versions */ - sprintf(file, "%s/rhdd", mntpt); + /* check for new version */ + sprintf(file, "%s/rhdd3", mntpt); if (access(file, R_OK)) { - version = 0; - sprintf(file, "%s/rhdd-6.1", mntpt); - if (access(file, R_OK)) { - /* this can't happen, we already verified it! */ - return LOADER_BACK; - } + /* this can't happen, we already verified it! */ + return LOADER_BACK; } stat(file, &sb); title = malloc(sb.st_size + 1); @@ -131,24 +294,39 @@ static int loadDriverDisk(struct loaderData_s *loaderData, char *mntpt) { title[sb.st_size] = '\0'; close(fd);
- sprintf(file, "/tmp/DD-%d", disknum); + sprintf(file, DD_RPMDIR_TEMPLATE, disknum); mkdirChain(file); + mkdirChain(DD_MODULES); + mkdirChain(DD_FIRMWARE);
if (!FL_CMDLINE(flags)) { startNewt(); winStatus(40, 3, _("Loading"), _("Reading driver disk")); }
- sprintf(dest, "/tmp/DD-%d", disknum); - copyDirectory(mntpt, dest, copyWarnFn, copyErrorFn); - location = malloc(sizeof(struct moduleBallLocation)); location->title = strdup(title); - location->version = version; + checked_asprintf(&location->path, DD_MODULES); + + sprintf(dest, DD_RPMDIR_TEMPLATE, disknum); + sprintf(src, "%s/rpms/%s", mntpt, getProductArch()); + copyDirectory(src, dest, copyWarnFn, copyErrorFn); + + /* unpack packages from dest into location->path */ + if (dlabelUnpackRPMDir(dest, DD_EXTRACTED)) { + /* fatal error, log this and jump to exception handler */ + logMessage(ERROR, "Error unpacking RPMs from driver disc no.%d", + disknum); + goto loadDriverDiscException; + }
- checked_asprintf(&location->path, "/tmp/DD-%d/modules.cgz", disknum); - checked_asprintf(&fwdir, "/tmp/DD-%d/firmware", disknum); + /* run depmod to refresh modules db */ + if (system("depmod -a")) { + /* this is not really fatal error, it might still work, log it */ + logMessage(ERROR, "Error running depmod -a for driverdisc no.%d", disknum); + }
+ checked_asprintf(&fwdir, DD_FIRMWARE); if (!access(fwdir, R_OK|X_OK)) { add_fw_search_dir(loaderData, fwdir); stop_fw_loader(loaderData); @@ -156,8 +334,13 @@ static int loadDriverDisk(struct loaderData_s *loaderData, char *mntpt) { } free(fwdir);
- sprintf(file, "%s/modinfo", mntpt); - readModuleInfo(file, modInfo, location, 1); + /* TODO generate and read module info + * + * sprintf(file, "%s/modinfo", mntpt); + * readModuleInfo(file, modInfo, location, 1); + */ + +loadDriverDiscException:
if (!FL_CMDLINE(flags)) newtPopWindow(); @@ -248,7 +431,14 @@ int loadDriverFromMedia(int class, struct loaderData_s *loaderData, char ** part_list = getPartitionsList(device); int nump = 0, num = 0;
- if (part != NULL) free(part); + /* Do not crash if the device disappeared */ + if (!part_list) { + stage = DEV_DEVICE; + break; + } + + if (part != NULL) + free(part);
if ((nump = lenPartitionsList(part_list)) == 0) { if (dir == -1) @@ -317,7 +507,7 @@ int loadDriverFromMedia(int class, struct loaderData_s *loaderData, }
case DEV_LOADFILE: { - if(ddfile == NULL) { + if (ddfile == NULL) { logMessage(DEBUGLVL, "trying to load dd from NULL"); stage = DEV_CHOOSEFILE; break; @@ -623,3 +813,77 @@ static void getDDFromDev(struct loaderData_s * loaderData, char * dev) { umount("/tmp/drivers"); unlink("/tmp/drivers"); } + + +/* + * Look for partition with specific label (part of #316481) + */ +GSList* findDriverDiskByLabel(void) +{ + char *ddLabel = "OEMDRV"; + GSList *ddDevice = NULL; + blkid_cache bCache; + + int res; + blkid_dev_iterate bIter; + blkid_dev bDev; + + if (blkid_get_cache(&bCache, NULL)<0) { + logMessage(ERROR, "Cannot initialize cache instance for blkid"); + return NULL; + } + if ((res = blkid_probe_all(bCache))<0) { + logMessage(ERROR, "Cannot probe devices in blkid: %d", res); + return NULL; + } + + if ((ddDevice = g_slist_alloc())==NULL) { + logMessage(ERROR, "Cannot allocate space for list of devices"); + return NULL; + } + + bIter = blkid_dev_iterate_begin(bCache); + blkid_dev_set_search(bIter, "LABEL", ddLabel); + while ((res = blkid_dev_next(bIter, &bDev)) !=0 ) { + bDev = blkid_verify(bCache, bDev); + if (!bDev) + continue; + logMessage(DEBUGLVL, "Adding driver disc %s to the list " + "of available DDs.", blkid_dev_devname(bDev)); + ddDevice = g_slist_prepend(ddDevice, (gpointer)blkid_dev_devname(bDev)); + /* Freeing bDev is taken care of by the put cache call */ + } + blkid_dev_iterate_end(bIter); + + blkid_put_cache(bCache); + + return ddDevice; +} + +int loadDriverDiskFromPartition(struct loaderData_s *loaderData, char* device) +{ + int rc; + + logMessage(INFO, "trying to mount %s", device); + if (doPwMount(device, "/tmp/drivers", "auto", "ro", NULL)) { + logMessage(ERROR, "Failed to mount driver disk."); + return -1; + } + + rc = verifyDriverDisk("/tmp/drivers"); + if (rc == LOADER_BACK) { + logMessage(ERROR, "Driver disk is invalid for this " + "release of %s.", getProductName()); + umount("/tmp/drivers"); + return -2; + } + + rc = loadDriverDisk(loaderData, "/tmp/drivers"); + umount("/tmp/drivers"); + if (rc == LOADER_BACK) { + return -3; + } + + return 0; +} + diff --git a/loader/driverdisk.h b/loader/driverdisk.h index e6e919d..98bfd4a 100644 --- a/loader/driverdisk.h +++ b/loader/driverdisk.h @@ -24,6 +24,11 @@ #include "modules.h" #include "moduleinfo.h"
+#define DD_RPMDIR_TEMPLATE "/tmp/DD-%d" +#define DD_EXTRACTED "/tmp/DD" +#define DD_MODULES "/tmp/DD/lib/modules" +#define DD_FIRMWARE "/tmp/DD/lib/firmware" + extern char *ddFsTypes[];
int loadDriverFromMedia(int class, struct loaderData_s *loaderData, @@ -39,4 +44,11 @@ void useKickstartDD(struct loaderData_s * loaderData, int argc,
void getDDFromSource(struct loaderData_s * loaderData, char * src);
+int loadDriverDiskFromPartition(struct loaderData_s *loaderData, char* device); + +GSList* findDriverDiskByLabel(void); + +int modprobeNormalmode(); +int modprobeDDmode(); + #endif
On 12/21/2009 04:21 PM, Martin Sivak wrote:
And adapt it to use glib and better string handling functions
loader/driverdisk.c | 344 +++++++++++++++++++++++++++++++++++++++++++++------ loader/driverdisk.h | 12 ++ 2 files changed, 316 insertions(+), 40 deletions(-)
Ack.
- size = fread(description, 1, 255, f);
- if (size == 0) {
free(description);
return NULL;
- }
- description[size-1]=0; /* strip the trailing newline */
- pclose(f);
- return description;
+}
+int globErrFunc(const char *epath, int eerrno) +{
- /* TODO check fatal errors */
- return 0;
+}
I think pjones's comments from https://www.redhat.com/archives/anaconda-devel-list/2009-December/msg00421.h... still apply here.
static int verifyDriverDisk(char *mntpt) { char ** fnPtr; char file[200]; struct stat sb;
- for (fnPtr = driverDiskFiles; *fnPtr; fnPtr++) {
sprintf(file, "%s/%s", mntpt, *fnPtr);
if (access(file, R_OK)) {
logMessage(ERROR, "cannot find %s, bad driver disk", file);
return LOADER_BACK;
}
- }
- /* check for both versions */
- sprintf(file, "%s/rhdd", mntpt);
- /* check for dd descriptor */
- sprintf(file, "%s/rhdd3", mntpt); if (access(file, R_OK)) {
logMessage(DEBUGLVL, "not a new format driver disk, checking for old");
sprintf(file, "%s/rhdd-6.1", mntpt);
if (access(file, R_OK)) {
logMessage(ERROR, "can't find either driver disk identifier, bad "
"driver disk");
}
logMessage(ERROR, "can't find driver disk identifier, bad "
"driver disk");
return LOADER_BACK;
}
/* side effect: file is still mntpt/ddident */ stat(file, &sb); if (!sb.st_size) return LOADER_BACK;
for (fnPtr = driverDiskFiles; *fnPtr; fnPtr++) {
snprintf(file, 200, "%s/%s/%s", mntpt, getProductArch(), *fnPtr);
if (access(file, R_OK)) {
logMessage(ERROR, "cannot find %s, bad driver disk", file);
return LOADER_BACK;
}
}
return LOADER_OK;
}
Likewise here.
- Chris
- enable dlabel on RHEL by default - use glib's linked lists to traverse through available DDs - run depmod if the .rundepmod trigger file is present --- loader/loader.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ loader/loader.h | 2 ++ 2 files changed, 47 insertions(+), 0 deletions(-)
diff --git a/loader/loader.c b/loader/loader.c index 4ef03b5..637af6e 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -956,6 +956,10 @@ static void parseCmdLineFlags(struct loaderData_s * loaderData, else if (!strcasecmp(argv[i], "dd") || !strcasecmp(argv[i], "driverdisk")) flags |= LOADER_FLAGS_MODDISK; + else if (!strcasecmp(argv[i], "dlabel=on")) + flags |= LOADER_FLAGS_AUTOMODDISK; + else if (!strcasecmp(argv[i], "dlabel=off")) + flags &= ~LOADER_FLAGS_AUTOMODDISK; else if (!strcasecmp(argv[i], "rescue")) flags |= LOADER_FLAGS_RESCUE; else if (!strcasecmp(argv[i], "nopass")) @@ -1781,6 +1785,7 @@ int main(int argc, char ** argv) { struct loaderData_s loaderData;
char *path, *fmt; + GSList *dd, *dditer;
gchar *cmdLine = NULL, *ksFile = NULL, *virtpcon = NULL; gboolean mediacheck = FALSE; @@ -1878,6 +1883,12 @@ int main(int argc, char ** argv) {
openLog(); openlog("loader", 0, LOG_LOCAL0); + + /* XXX if RHEL, enable the AUTODD feature by default, + * but we should come with more general way how to control this */ + if (!strncmp(getProductName(), "Red Hat", 7)) { + flags |= LOADER_FLAGS_AUTOMODDISK; + }
memset(&loaderData, 0, sizeof(loaderData)); loaderData.method = -1; @@ -1939,6 +1950,34 @@ int main(int argc, char ** argv) { /* FIXME: this is a bit of a hack */ loaderData.modInfo = modInfo;
+ /* Setup depmod & modprobe so we can load multiple DDs */ + modprobeDDmode(); + + /* If there is /.rundepmod file present, rerun depmod */ + if (!access("/.rundepmod", R_OK)){ + if (system("depmod -a")) { + /* this is not really fatal error, it might still work, log it */ + logMessage(ERROR, "Error running depmod -a for initrd overlay"); + } + } + + if (FL_AUTOMODDISK(flags)) { + /* Load all autodetected DDs */ + logMessage(INFO, "Trying to detect vendor driver discs"); + dd = findDriverDiskByLabel(); + dditer = dd; + while(dditer) { + if (loadDriverDiskFromPartition(&loaderData, (char*)(dditer->data))) { + logMessage(ERROR, "Automatic driver disk loader failed for %s.", (char*)(dditer->data)); + } + else { + logMessage(INFO, "Automatic driver disk loader succeeded for %s.", (char*)(dditer->data)); + } + dditer = g_slist_next(dditer); + } + g_slist_free(dd); + } + if (FL_MODDISK(flags)) { startNewt(); loadDriverDisks(DEVICE_ANY, &loaderData); @@ -1948,6 +1987,9 @@ int main(int argc, char ** argv) { logMessage(INFO, "found /dd.img, loading drivers"); getDDFromSource(&loaderData, "path:/dd.img"); } + + /* Reset depmod & modprobe to normal mode and get the rest of drivers*/ + modprobeNormalmode();
/* this allows us to do an early load of modules specified on the * command line to allow automating the load order of modules so that @@ -2128,6 +2170,9 @@ int main(int argc, char ** argv) { tmparg++; }
+ if (FL_AUTOMODDISK(flags)) + *argptr++ = "--dlabel"; + if (FL_NOIPV4(flags)) *argptr++ = "--noipv4";
diff --git a/loader/loader.h b/loader/loader.h index a0d706c..1121b20 100644 --- a/loader/loader.h +++ b/loader/loader.h @@ -70,6 +70,7 @@ #define LOADER_FLAGS_HAVE_CMSCONF (((uint64_t) 1) << 37) #define LOADER_FLAGS_NOKILL (((uint64_t) 1) << 38) #define LOADER_FLAGS_KICKSTART_SEND_SERIAL (((uint64_t) 1) << 39) +#define LOADER_FLAGS_AUTOMODDISK (((uint64_t) 1) << 40)
#define FL_TEXT(a) ((a) & LOADER_FLAGS_TEXT) #define FL_RESCUE(a) ((a) & LOADER_FLAGS_RESCUE) @@ -106,6 +107,7 @@ #define FL_HAVE_CMSCONF(a) ((a) & LOADER_FLAGS_HAVE_CMSCONF) #define FL_NOKILL(a) ((a) & LOADER_FLAGS_NOKILL) #define FL_KICKSTART_SEND_SERIAL(a) ((a) & LOADER_FLAGS_KICKSTART_SEND_SERIAL) +#define FL_AUTOMODDISK(a) ((a) & LOADER_FLAGS_AUTOMODDISK)
void startNewt(void); void stopNewt(void);
On 12/21/2009 04:21 PM, Martin Sivak wrote:
if (system("depmod -a")) {
/* this is not really fatal error, it might still work, log it */
logMessage(ERROR, "Error running depmod -a for initrd overlay");
}
I know that a zero should stay a zero, but shouldn't you check the value returned from system() with WEXITSTATUS? Looks good otherwise.
--- anaconda | 4 ++++ backend.py | 19 +++++++++++++------ constants.py | 5 +++++ flags.py | 1 + yuminstall.py | 42 +++++++++++++++++++++++++++--------------- 5 files changed, 50 insertions(+), 21 deletions(-)
diff --git a/anaconda b/anaconda index 78e5fd1..20ecb12 100755 --- a/anaconda +++ b/anaconda @@ -231,6 +231,7 @@ def parseOptions(): op.add_option("--nomount", dest="rescue_nomount", action="store_true", default=False) op.add_option("--updates", dest="updateSrc", action="store", type="string") op.add_option("--dogtail", dest="dogtail", action="store", type="string") + op.add_option("--dlabel", action="store_true", default=False)
# Deprecated, unloved, unused op.add_option("-r", "--rootPath", dest="unsupportedMode", @@ -657,6 +658,9 @@ if __name__ == "__main__": # Default is to prompt to mount the installed system. anaconda.rescue_mount = not opts.rescue_nomount
+ if opts.dlabel: #autodetected driverdisc in use + flags.dlabel = True + if opts.noipv4: flags.useIPv4 = False
diff --git a/backend.py b/backend.py index 5ddeb8c..8dd17a5 100644 --- a/backend.py +++ b/backend.py @@ -73,8 +73,8 @@ class AnacondaBackend:
def copyFirmware(self, anaconda): # Multiple driver disks may be loaded, so we need to glob for all - # the firmware files in all the driver disk directories. - for f in glob.glob("/tmp/DD-*/firmware/*"): + # the firmware files in the common DD firmware directory + for f in glob.glob(DD_EXTRACTED+"/lib/firmware/*"): try: shutil.copyfile(f, "%s/lib/firmware/" % anaconda.rootPath) except IOError, e: @@ -94,15 +94,22 @@ class AnacondaBackend: has_iscsi_disk = True break
- if anaconda.id.extraModules: - self.copyFirmware(anaconda) + #always copy the firmware files from DD + self.copyFirmware(anaconda)
if anaconda.id.extraModules or has_iscsi_disk: for (n, arch, tag) in self.kernelVersionList(anaconda.rootPath): packages.recreateInitrd(n, anaconda.rootPath)
- for d in glob.glob("/tmp/DD-*"): - shutil.copytree(d, "/root/" + os.path.basename(d)) + #copy RPMS + for d in glob.glob(DD_RPMS): + shutil.copytree(d, anaconda.rootPath + "/root/" + os.path.basename(d)) + + #copy modules and firmware + try: + shutil.copytree(DD_EXTRACTED, anaconda.rootPath + "/root/DD") + except IOError, e: + pass
storage.writeEscrowPackets(anaconda)
diff --git a/constants.py b/constants.py index 9c4fbb1..fb81c90 100644 --- a/constants.py +++ b/constants.py @@ -82,3 +82,8 @@ else: # this string will be combined with "An unhandled exception"... # the leading space is not a typo. exceptionText += _(" against anaconda at %s") %(bugzillaUrl,) + +# DriverDisc Paths +DD_EXTRACTED = "/tmp/DD" +DD_RPMS = "/tmp/DD-*" + diff --git a/flags.py b/flags.py index 17bc2e0..05e84e9 100644 --- a/flags.py +++ b/flags.py @@ -69,6 +69,7 @@ class Flags: self.__dict__['flags'] = {} self.__dict__['flags']['test'] = 0 self.__dict__['flags']['livecdInstall'] = 0 + self.__dict__['flags']['dlabel'] = 0 self.__dict__['flags']['ibft'] = 1 self.__dict__['flags']['iscsi'] = 0 self.__dict__['flags']['serial'] = 0 diff --git a/yuminstall.py b/yuminstall.py index 7db91cf..d33b267 100644 --- a/yuminstall.py +++ b/yuminstall.py @@ -651,16 +651,18 @@ class AnacondaYum(YumSorter):
extraRepos = []
- if self.anaconda.id.extraModules: - for d in glob.glob("/tmp/DD-*/rpms"): - dirname = os.path.basename(os.path.dirname(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) + 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.isKickstart: # This is the same pattern as from loader/urls.c:splitProxyParam. @@ -1290,19 +1292,29 @@ reposdir=/etc/anaconda.repos.d,/tmp/updates/anaconda.repos.d,/tmp/product/anacon def selectModulePackages(self, anaconda, kernelPkgName): (base, sep, ext) = kernelPkgName.partition("-")
+ moduleProvides = [] + for (path, name) in anaconda.id.extraModules: if ext != "": - moduleProvides = "dud-%s-%s" % (name, ext) + moduleProvides.append("dud-%s-%s" % (name, ext)) + else: + moduleProvides.append("dud-%s" % name) + + #We need to install the packages which contain modules from DriverDiscs + for modPath in isys.modulesWithPaths(): + if modPath.startswith(DD_EXTRACTED): + moduleProvides.append(modPath[len(DD_EXTRACTED):]) else: - moduleProvides = "dud-%s" % name + continue
- pkgs = self.ayum.returnPackagesByDep(moduleProvides) + for module in moduleProvides: + pkgs = self.ayum.returnPackagesByDep(module)
if not pkgs: - log.warning("Didn't find any package providing module %s" % name) + log.warning("Didn't find any package providing %s" % module)
for pkg in pkgs: - log.info("selecting package %s for module %s" % (pkg.name, name)) + log.info("selecting package %s for %s" % (pkg.name, module)) self.ayum.install(po=pkg)
def selectBestKernel(self, anaconda):
for f in glob.glob("/tmp/DD-*/firmware/*"):
# the firmware files in the common DD firmware directory
for f in glob.glob(DD_EXTRACTED+"/lib/firmware/*"):
os.path.join() ?
Otherwise looks good.
anaconda | 4 ++++ backend.py | 19 +++++++++++++------ constants.py | 5 +++++ flags.py | 1 + yuminstall.py | 42 +++++++++++++++++++++++++++--------------- 5 files changed, 50 insertions(+), 21 deletions(-)
This patch looks fine now. Thanks for making the changes.
- Chris
anaconda-devel@lists.stg.fedoraproject.org