/[gli]/branches/qs/src/GLIPortage.py
Gentoo

Contents of /branches/qs/src/GLIPortage.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1338 - (hide annotations) (download) (as text)
Sun Mar 5 03:06:44 2006 UTC (8 years, 4 months ago) by agaffney
Original Path: trunk/src/GLIPortage.py
File MIME type: text/x-python
File size: 17618 byte(s)
preserve permissions when copying from image dir to chroot

1 agaffney 1181 """
2     # Copyright 1999-2005 Gentoo Foundation
3     # This source code is distributed under the terms of version 2 of the GNU
4     # General Public License as published by the Free Software Foundation, a copy
5     # of which can be found in the main directory of this project.
6     Gentoo Linux Installer
7    
8 agaffney 1338 $Id: GLIPortage.py,v 1.49 2006/03/05 03:06:44 agaffney Exp $
9 agaffney 1181 """
10    
11 agaffney 1182 import re
12 agaffney 1216 import os
13 agaffney 1306 import sys
14 agaffney 1181 import GLIUtility
15 agaffney 1204 from GLIException import GLIException
16 agaffney 1181
17     class GLIPortage(object):
18    
19 agaffney 1205 def __init__(self, chroot_dir, grp_install, logger, debug, cc, compile_logfile):
20 agaffney 1182 self._chroot_dir = chroot_dir
21 agaffney 1189 self._grp_install = grp_install
22 agaffney 1182 self._logger = logger
23     self._debug = debug
24 agaffney 1205 self._cc = cc
25     self._compile_logfile = compile_logfile
26 agaffney 1181
27 agaffney 1183 def get_deps(self, pkgs):
28 agaffney 1189 pkglist = []
29     if isinstance(pkgs, str):
30     pkgs = pkgs.split()
31     for pkg in pkgs:
32 agaffney 1305 if not pkg: continue
33 agaffney 1190 if self._debug: self._logger.log("get_deps(): pkg is " + pkg)
34 agaffney 1189 if not self._grp_install or not self.get_best_version_vdb(pkg):
35 agaffney 1190 if self._debug: self._logger.log("get_deps(): grabbing compile deps")
36 agaffney 1208 tmppkglist = GLIUtility.spawn("emerge -p " + pkg + r" 2>/dev/null | grep -e '^\[[a-z]' | cut -d ']' -f2 | sed -e 's:^ ::' -e 's: .\+$::'", chroot=self._chroot_dir, return_output=True)[1].strip().split("\n")
37 agaffney 1189 else:
38 agaffney 1190 if self._debug: self._logger.log("get_deps(): grabbing binary deps")
39 agaffney 1210 # The runtimedeps.py script generates a package install order that is *very* different from emerge itself
40     # tmppkglist = GLIUtility.spawn("python ../../runtimedeps.py " + self._chroot_dir + " " + pkg, return_output=True)[1].strip().split("\n")
41     tmppkglist = []
42 agaffney 1214 for tmppkg in GLIUtility.spawn("emerge -p " + pkg + r" 2>/dev/null | grep -e '^\[[a-z]' | cut -d ']' -f2 | sed -e 's:^ ::' -e 's: .\+$::'", chroot=self._chroot_dir, return_output=True)[1].strip().split("\n"):
43 agaffney 1210 if self._debug: self._logger.log("get_deps(): looking at " + tmppkg)
44 agaffney 1211 if self.get_best_version_vdb("=" + tmppkg):
45 agaffney 1210 if self._debug: self._logger.log("get_deps(): package " + tmppkg + " in host vdb...adding to tmppkglist")
46     tmppkglist.append(tmppkg)
47 agaffney 1190 if self._debug: self._logger.log("get_deps(): deplist for " + pkg + ": " + str(tmppkglist))
48 agaffney 1189 for tmppkg in tmppkglist:
49 agaffney 1192 if self._debug: self._logger.log("get_deps(): checking to see if " + tmppkg + " is already in pkglist")
50 agaffney 1194 if not tmppkg in pkglist and not self.get_best_version_vdb_chroot("=" + tmppkg):
51 agaffney 1192 if self._debug: self._logger.log("get_deps(): adding " + tmppkg + " to pkglist")
52 agaffney 1189 pkglist.append(tmppkg)
53 agaffney 1190 if self._debug: self._logger.log("get_deps(): pkglist is " + str(pkglist))
54 agaffney 1189 return pkglist
55 agaffney 1182
56 agaffney 1221 def parse_vdb_contents(self, file):
57     entries = []
58     try:
59     vdbfile = open(file, "r")
60     except:
61     return entries
62     for line in vdbfile.readlines():
63     parts = line.strip().split(" ")
64     if parts[0] == "obj":
65     entries.append(parts[1])
66 agaffney 1222 # elif parts[0] == "dir":
67     # entries.append(parts[1] + "/")
68 agaffney 1221 elif parts[0] == "sym":
69     entries.append(" ".join(parts[1:4]))
70     entries.sort()
71     return entries
72    
73 agaffney 1280 def copy_pkg_to_chroot(self, package, use_root=False, ignore_missing=False):
74 agaffney 1221 symlinks = { '/bin': '/mnt/livecd/bin/', '/boot': '/mnt/livecd/boot/', '/lib': '/mnt/livecd/lib/',
75     '/opt': '/mnt/livecd/opt/', '/sbin': '/mnt/livecd/sbin/', '/usr': '/mnt/livecd/usr/',
76     '/etc/gconf': '/usr/livecd/gconf/' }
77 agaffney 1182
78 agaffney 1208 tmpdir = "/var/tmp/portage"
79     image_dir = tmpdir + "/" + package.split("/")[1] + "/image"
80 agaffney 1198 root_cmd = ""
81     tmp_chroot_dir = self._chroot_dir
82 agaffney 1204 portage_tmpdir = "/var/tmp/portage"
83 agaffney 1270 vdb_dir = "/var/db/pkg/"
84 agaffney 1198 if use_root:
85     root_cmd = "ROOT=" + self._chroot_dir
86 agaffney 1203 tmp_chroot_dir = ""
87 agaffney 1204 portage_tmpdir = self._chroot_dir + "/var/tmp/portage"
88 agaffney 1270 vdb_dir = self._chroot_dir + "/var/db/pkg/"
89 agaffney 1198
90 agaffney 1280 # Check to see if package is actually in vdb
91     if not GLIUtility.is_file("/var/db/pkg/" + package):
92     if ignore_missing:
93     if self._debug:
94     self._logger.log("DEBUG: copy_pkg_to_chroot(): package " + package + " does not have a vdb entry but ignore_missing=True...ignoring error")
95     return
96     else:
97     raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "There is no vdb entry for " + package)
98    
99 agaffney 1182 # Copy the vdb entry for the package from the LiveCD to the chroot
100     if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot(): copying vdb entry for " + package)
101 agaffney 1314 if not GLIUtility.exitsuccess(GLIUtility.spawn("mkdir -p " + self._chroot_dir + "/var/db/pkg/" + package + " && cp -a /var/db/pkg/" + package + "/* " + self._chroot_dir + "/var/db/pkg/" + package, logfile=self._compile_logfile, append_log=True)):
102 agaffney 1182 raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "Could not copy vdb entry for " + package)
103    
104 agaffney 1208 # Create the image dir in the chroot
105     if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot(): running 'mkdir -p " + self._chroot_dir + image_dir + "'")
106 agaffney 1314 if not GLIUtility.exitsuccess(GLIUtility.spawn("mkdir -p " + self._chroot_dir + image_dir, logfile=self._compile_logfile, append_log=True)):
107 agaffney 1208 raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "Could not create image dir for " + package)
108    
109 agaffney 1182 # Create list of files for tar to work with from CONTENTS file in vdb entry
110 agaffney 1221 entries = self.parse_vdb_contents("/var/db/pkg/" + package + "/CONTENTS")
111 agaffney 1208 if not entries:
112     if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot(): no files for " + package + "...skipping tar and symlink fixup")
113     else:
114     if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot: files for " + package + ": " + str(entries))
115     try:
116     tarfiles = open("/tmp/tarfilelist", "w")
117     for entry in entries:
118     parts = entry.split(" ")
119 agaffney 1222 # # Hack for symlink crappiness
120 agaffney 1221 # for symlink in symlinks:
121     # if parts[0].startswith(symlink):
122     # parts[0] = symlinks[symlink] + parts[0][len(symlink):]
123 agaffney 1208 tarfiles.write(parts[0] + "\n")
124     tarfiles.close()
125     except:
126     raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "Could not create filelist for " + package)
127 agaffney 1182
128 agaffney 1208 # Use tar to transfer files into IMAGE directory
129 agaffney 1222 if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot(): running 'tar -cp --files-from=/tmp/tarfilelist --no-recursion 2>/dev/null | tar -C " + self._chroot_dir + image_dir + " -xp'")
130 agaffney 1314 if not GLIUtility.exitsuccess(GLIUtility.spawn("tar -cp --files-from=/tmp/tarfilelist --no-recursion 2>/dev/null | tar -C " + self._chroot_dir + image_dir + " -xp", logfile=self._compile_logfile, append_log=True)):
131 agaffney 1208 raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "Could not execute tar for " + package)
132 agaffney 1182
133 agaffney 1338 # Fix mode, uid, and gid of directories
134     if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot(): running find " + self._chroot_dir + image_dir + " -type d 2>/dev/null | sed -e 's:^" + self._chroot_dir + image_dir + "::' | grep -v '^$'")
135     dirlist = GLIUtility.spawn("find " + self._chroot_dir + image_dir + " -type d 2>/dev/null | sed -e 's:^" + self._chroot_dir + image_dir + "::' | grep -v '^$'", return_output=True)[1].strip().split("\n")
136     if not dirlist or dirlist[0] == "":
137     raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "directory list entry for " + package + "...this shouldn't happen!")
138     for dir in dirlist:
139     dirstat = os.stat(dir)
140     os.chown(self._chroot_dir + image_dir + dir, dirstat[4], dirstat[5])
141     os.chmod(self._chroot_dir + image_dir + dir, dirstat[0])
142    
143 agaffney 1221 # # More symlink crappiness hacks
144     # for symlink in symlinks:
145     ## if GLIUtility.is_file(self._chroot_dir + image_dir + symlinks[symlink]):
146     # if os.path.islink(self._chroot_dir + image_dir + symlink):
147     # if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot(): fixing " + symlink + " symlink ickiness stuff in " + image_dir + " for " + package)
148     # GLIUtility.spawn("rm " + self._chroot_dir + image_dir + symlink)
149     # if not GLIUtility.exitsuccess(GLIUtility.spawn("mv " + self._chroot_dir + image_dir + symlinks[symlink] + " " + self._chroot_dir + image_dir + symlink)):
150     # raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "Could not fix " + symlink + " symlink ickiness for " + package)
151 agaffney 1182
152     # Run pkg_setup
153     if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot(): running pkg_setup for " + package)
154 agaffney 1314 if not GLIUtility.exitsuccess(GLIUtility.spawn("env " + root_cmd + " PORTAGE_TMPDIR=" + portage_tmpdir + " ebuild " + vdb_dir + package + "/*.ebuild setup", chroot=tmp_chroot_dir, logfile=self._compile_logfile, append_log=True)):
155 agaffney 1182 raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "Could not execute pkg_setup for " + package)
156    
157     # Run pkg_preinst
158     if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot(): running preinst for " + package)
159 agaffney 1314 if not GLIUtility.exitsuccess(GLIUtility.spawn("env " + root_cmd + " PORTAGE_TMPDIR=" + portage_tmpdir + " ebuild " + vdb_dir + package + "/*.ebuild preinst", chroot=tmp_chroot_dir, logfile=self._compile_logfile, append_log=True)):
160 agaffney 1182 raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "Could not execute preinst for " + package)
161    
162     # Copy files from image_dir to chroot
163 agaffney 1208 if not entries:
164 agaffney 1209 if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot(): no files for " + package + "...skipping copy from image dir to /")
165 agaffney 1208 else:
166     if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot(): copying files from " + image_dir + " to / for " + package)
167 agaffney 1291 # if not GLIUtility.exitsuccess(GLIUtility.spawn("cp -a " + self._chroot_dir + image_dir + "/* " + self._chroot_dir)):
168 agaffney 1338 if not GLIUtility.exitsuccess(GLIUtility.spawn("tar -C " + self._chroot_dir + image_dir + "/ -cp . | tar -C " + self._chroot_dir + "/ -xp", logfile=self._compile_logfile, append_log=True)):
169 agaffney 1208 raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "Could not copy files from " + image_dir + " to / for " + package)
170 agaffney 1182
171     # Run pkg_postinst
172     if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot(): running postinst for " + package)
173 agaffney 1314 if not GLIUtility.exitsuccess(GLIUtility.spawn("env " + root_cmd + " PORTAGE_TMPDIR=" + portage_tmpdir + " ebuild " + vdb_dir + package + "/*.ebuild postinst", chroot=tmp_chroot_dir, logfile=self._compile_logfile, append_log=True)):
174 agaffney 1182 raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "Could not execute postinst for " + package)
175    
176     # Remove image_dir
177 agaffney 1208 if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot(): removing " + image_dir + " for " + package)
178 agaffney 1314 if not GLIUtility.exitsuccess(GLIUtility.spawn("rm -rf " + self._chroot_dir + image_dir, logfile=self._compile_logfile, append_log=True)):
179 agaffney 1182 raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "Could not remove + " + image_dir + " for " + package)
180    
181 agaffney 1297 # Run env-update
182     if not use_root:
183     if self._debug: self._logger.log("DEBUG: copy_pkg_to_chroot(): running env-update inside chroot")
184 agaffney 1314 if not GLIUtility.exitsuccess(GLIUtility.spawn("env-update", chroot=self._chroot_dir, logfile=self._compile_logfile, append_log=True)):
185 agaffney 1297 raise GLIException("CopyPackageToChrootError", 'fatal', 'copy_pkg_to_chroot', "Could not run env-update for " + package)
186    
187 agaffney 1182 def add_pkg_to_world(self, package):
188     if package.find("/") == -1:
189 agaffney 1195 package = self.get_best_version_vdb_chroot(package)
190 agaffney 1182 if not package: return False
191 agaffney 1205 expr = re.compile('^=?(.+?/.+?)(-\d.+)?$')
192 agaffney 1182 res = expr.match(package)
193     if res:
194     GLIUtility.spawn("echo " + res.group(1) + " >> " + self._chroot_dir + "/var/lib/portage/world")
195    
196 agaffney 1185 def get_best_version_vdb(self, package):
197 agaffney 1285 if package.startswith('='):
198     package = package[1:]
199     if GLIUtility.is_file("/var/db/pkg/" + package):
200     return package
201 agaffney 1286 else:
202     return ""
203 agaffney 1285 else:
204     return GLIUtility.spawn("portageq best_version / " + package, return_output=True)[1].strip()
205 agaffney 1189
206 agaffney 1194 def get_best_version_vdb_chroot(self, package):
207 agaffney 1287 if package.startswith('='):
208     package = package[1:]
209     if GLIUtility.is_file(self._chroot_dir + "/var/db/pkg/" + package):
210     return package
211     else:
212     return ""
213     else:
214     return GLIUtility.spawn("portageq best_version / " + package, chroot=self._chroot_dir, return_output=True)[1].strip()
215 agaffney 1194
216 agaffney 1184 # def get_best_version_tree(self, package):
217     # return portage.best(tree.match(package))
218 agaffney 1205
219     def emerge(self, packages, add_to_world=True):
220     if isinstance(packages, str):
221     packages = packages.split()
222 agaffney 1223 self._cc.addNotification("progress", (0, "Calculating dependencies for " + " ".join(packages)))
223 agaffney 1205 pkglist = self.get_deps(packages)
224     if self._debug: self._logger.log("install_packages(): pkglist is " + str(pkglist))
225     for i, pkg in enumerate(pkglist):
226 agaffney 1305 if not pkg: continue
227 agaffney 1205 if self._debug: self._logger.log("install_packages(): processing package " + pkg)
228 agaffney 1208 self._cc.addNotification("progress", (float(i) / len(pkglist), "Emerging " + pkg + " (" + str(i+1) + "/" + str(len(pkglist)) + ")"))
229     if not self._grp_install or not self.get_best_version_vdb("=" + pkg):
230 agaffney 1205 status = GLIUtility.spawn("emerge -1 =" + pkg, display_on_tty8=True, chroot=self._chroot_dir, logfile=self._compile_logfile, append_log=True)
231     # status = self._emerge("=" + pkg)
232     if not GLIUtility.exitsuccess(status):
233     raise GLIException("EmergePackageError", "fatal", "emerge", "Could not emerge " + pkg + "!")
234     else:
235     # try:
236     self.copy_pkg_to_chroot(pkg)
237     # except:
238     # raise GLIException("EmergePackageError", "fatal", "emerge", "Could not emerge " + pkg + "!")
239 agaffney 1208 self._cc.addNotification("progress", (float(i+1) / len(pkglist), "Done emerging " + pkg + " (" + str(i+1) + "/" + str(len(pkglist)) + ")"))
240 agaffney 1205 if add_to_world:
241     for package in packages:
242     self.add_pkg_to_world(package)
243 agaffney 1306
244    
245 agaffney 1311 def usage(progname):
246 agaffney 1306 print """
247 agaffney 1311 Usage: %s [-c|--chroot-dir <chroot directory>] [-g|--grp] [-s|--stage3] [-h|--help]
248 agaffney 1306
249     Options:
250    
251     -c|--chroot-dir Specifies the directory where your chroot is. This is
252     "/mnt/gentoo" by default.
253    
254     -g|--grp Install specified packages and dependencies into chroot
255     by using files from the LiveCD.
256    
257     -s|--stage3 Create a stage3 equivelant in the chroot directory by using
258     files from the LiveCD.
259    
260     -h|--help Display this help
261 agaffney 1311 """ % (progname)
262 agaffney 1306
263     if __name__ == "__main__":
264     chroot_dir = "/mnt/gentoo"
265     mode = None
266     grp_packages = []
267 agaffney 1311 progname = sys.argv.pop(0)
268 agaffney 1307 while len(sys.argv):
269 agaffney 1306 arg = sys.argv.pop(0)
270     if arg == "-c" or arg == "--chroot-dir":
271     chroot_dir = sys.argv.pop(0)
272     elif arg == "-g" or arg == "--grp":
273     mode = "grp"
274     elif arg == "-s" or arg == "--stage3":
275     mode = "stage3"
276     elif arg == "-h" or arg == "--help":
277 agaffney 1311 usage(progname)
278 agaffney 1306 sys.exit(0)
279     elif arg[0] == "-":
280 agaffney 1311 usage(progname)
281 agaffney 1306 sys.exit(1)
282     else:
283     grp_packages.append(arg)
284    
285     gliportage = GLIPortage(chroot_dir, True, None, False, None, None)
286     if mode == "stage3":
287     if not GLIUtility.is_file("/usr/livecd/systempkgs.txt"):
288     print "Required file /usr/livecd/systempkgs.txt does not exist!"
289     sys.exit(1)
290     try:
291     syspkgs = open("/usr/livecd/systempkgs.txt", "r")
292     systempkgs = syspkgs.readlines()
293     syspkgs.close()
294     except:
295     print "Could not open /usr/livecd/systempkgs.txt!"
296     sys.exit(1)
297    
298     # Pre-create /lib (and possible /lib32 and /lib64)
299     if os.path.islink("/lib") and os.readlink("/lib") == "lib64":
300     if not GLIUtility.exitsuccess(GLIUtility.spawn("mkdir " + chroot_dir + "/lib64 && ln -s lib64 " + chroot_dir + "/lib")):
301     print "Could not precreate /lib64 dir and /lib -> /lib64 symlink"
302     sys.exit(1)
303    
304     syspkglen = len(systempkgs)
305     for i, pkg in enumerate(systempkgs):
306     pkg = pkg.strip()
307 agaffney 1310 print "Copying " + pkg + " (" + str(i+1) + "/" + str(syspkglen) + ")"
308 agaffney 1306 gliportage.copy_pkg_to_chroot(pkg, True, ignore_missing=True)
309     GLIUtility.spawn("cp /etc/make.conf " + chroot_dir + "/etc/make.conf")
310     GLIUtility.spawn("ln -s `readlink /etc/make.profile` " + chroot_dir + "/etc/make.profile")
311     GLIUtility.spawn("cp -f /etc/inittab.old " + chroot_dir + "/etc/inittab")
312    
313     # Nasty, nasty, nasty hack because vapier is a tool
314     for tmpfile in ("/etc/passwd", "/etc/group", "/etc/shadow"):
315     GLIUtility.spawn("grep -ve '^gentoo' " + tmpfile + " > " + chroot_dir + tmpfile)
316    
317     chrootscript = r"""
318     #!/bin/bash
319    
320     source /etc/make.conf
321     export LDPATH="/usr/lib/gcc-lib/${CHOST}/$(cd /usr/lib/gcc-lib/${CHOST} && ls -1 | head -n 1)"
322    
323     ldconfig $LDPATH
324     gcc-config 1
325     env-update
326     source /etc/profile
327     modules-update
328     [ -f /usr/bin/binutils-config ] && binutils-config 1
329     source /etc/profile
330     #mount -t proc none /proc
331     #cd /dev
332     #/sbin/MAKEDEV generic-i386
333     #umount /proc
334     [ -f /lib/udev-state/devices.tar.bz2 ] && tar -C /dev -xjf /lib/udev-state/devices.tar.bz2
335     """
336     script = open(chroot_dir + "/tmp/extrastuff.sh", "w")
337     script.write(chrootscript)
338     script.close()
339     GLIUtility.spawn("chmod 755 /tmp/extrastuff.sh && /tmp/extrastuff.sh", chroot=chroot_dir)
340     GLIUtility.spawn("rm -rf /var/tmp/portage/* /usr/portage /tmp/*", chroot=chroot_dir)
341     print "Stage3 equivelant generation complete!"
342     elif mode == "grp":
343     for pkg in grp_packages:
344     if not gliportage.get_best_version_vdb(pkg):
345     print "Package " + pkg + " is not available for install from the LiveCD"
346 agaffney 1311 continue
347 agaffney 1306 pkglist = gliportage.get_deps(pkg)
348 agaffney 1311 for i, tmppkg in enumerate(pkglist):
349     print "Copying " + tmppkg + " (" + str(i+1) + "/" + str(len(pkglist)) + ")"
350 agaffney 1306 gliportage.copy_pkg_to_chroot(tmppkg)
351     gliportage.add_pkg_to_world(pkg)
352     print "GRP install complete!"
353     else:
354     print "You must specify an operating mode (-g or -s)!"
355 agaffney 1311 usage(progname)
356 agaffney 1306 sys.exit(1)

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC 1.1.20