3 # Copyright (c) 2009, 2010, 2011 Intel, Inc.
5 # This program is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by the Free
7 # Software Foundation; version 2 of the License
9 # This program is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 # You should have received a copy of the GNU General Public License along
15 # with this program; if not, write to the Free Software Foundation, Inc., 59
16 # Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 from __future__ import with_statement
26 from mic.utils import errors, proxy, misc
27 from mic.utils.rpmmisc import readRpmHeader, RPMInstallCallback
28 from mic.chroot import cleanup_mounts, setup_chrootenv, cleanup_chrootenv
30 RPMTRANS_FLAGS = [rpm.RPMTRANS_FLAG_ALLFILES,
31 rpm.RPMTRANS_FLAG_NOSCRIPTS,
32 rpm.RPMTRANS_FLAG_NOTRIGGERS,
33 rpm.RPMTRANS_FLAG_NODOCS]
35 RPMVSF_FLAGS = [rpm._RPMVSF_NOSIGNATURES,
36 rpm._RPMVSF_NODIGESTS]
38 class MiniBackend(object):
39 def __init__(self, rootdir, repomd=None):
41 self.rootdir = os.path.abspath(rootdir)
56 self._ts = rpm.TransactionSet(self.rootdir)
57 self._ts.setFlags(reduce(lambda x, y: x|y, RPMTRANS_FLAGS))
58 self._ts.setVSFlags(reduce(lambda x, y: x|y, RPMVSF_FLAGS))
66 ts = property(fget = lambda self: self.get_ts(),
67 fdel = lambda self: self.del_ts(),
68 doc="TransactionSet object")
70 def selectPackage(self, pkg):
71 if not pkg in self.dlpkgs:
72 self.dlpkgs.append(pkg)
79 for pkg in self.preins.keys():
80 prog, script = self.preins[pkg]
81 self.run_pkg_script(pkg, prog, script, '0')
82 for pkg in self.postins.keys():
83 prog, script = self.postins[pkg]
84 self.run_pkg_script(pkg, prog, script, '1')
86 def downloadPkgs(self):
88 for pkg in self.dlpkgs:
90 localpth = misc.get_package(pkg, self.repomd, None)
92 # skip non-existent rpm
95 self.localpkgs[pkg] = localpth
100 msger.warning("\ncan't get rpm binary: %s" % ','.join(nonexist))
102 def installPkgs(self):
103 for pkg in self.localpkgs.keys():
104 rpmpath = self.localpkgs[pkg]
106 hdr = readRpmHeader(self.ts, rpmpath)
108 # save prein and postin scripts
109 self.preins[pkg] = (hdr['PREINPROG'], hdr['PREIN'])
110 self.postins[pkg] = (hdr['POSTINPROG'], hdr['POSTIN'])
112 # mark pkg as install
113 self.ts.addInstall(hdr, rpmpath, 'u')
117 cb = RPMInstallCallback(self.ts)
118 self.ts.run(cb.callback, '')
120 def run_pkg_script(self, pkg, prog, script, arg):
121 mychroot = lambda: os.chroot(self.rootdir)
127 prog = "/usr/bin/lua"
129 tmpdir = os.path.join(self.rootdir, "tmp")
130 if not os.path.exists(tmpdir):
132 tmpfd, tmpfp = tempfile.mkstemp(dir=tmpdir, prefix="%s.pre-" % pkg)
133 script = script.replace('\r', '')
134 os.write(tmpfd, script)
136 os.chmod(tmpfp, 0700)
139 script_fp = os.path.join('/tmp', os.path.basename(tmpfp))
140 subprocess.call([prog, script_fp, arg], preexec_fn=mychroot)
141 except (OSError, IOError), err:
142 raise RuntimeError(err)
146 class Bootstrap(object):
147 def __init__(self, rootdir, distro):
148 self.rootdir = rootdir
156 def get_rootdir(self):
157 if os.path.exists(self.rootdir):
158 shutil.rmtree(self.rootdir, ignore_errors=True)
159 os.makedirs(self.rootdir)
162 def _path(self, pth):
163 return os.path.join(self.rootdir, pth.lstrip('/'))
165 def create(self, repomd, pkglist):
167 pkgmgr = MiniBackend(self.get_rootdir())
168 pkgmgr.repomd = repomd
169 map(pkgmgr.selectPackage, pkglist)
173 tmpdir = self._path('/tmp')
174 if not os.path.exists(tmpdir):
178 tzdist = self._path('/etc/%s-release' % self.distro)
179 if not os.path.exists(tzdist):
180 with open(tzdist, 'w') as wf:
181 wf.write("bootstrap")
183 except (OSError, IOError, errors.CreatorError), err:
184 raise errors.BootstrapError("%s" % err)
186 def run(self, cmd, chdir, bindmounts=None):
188 os.chroot(self.rootdir)
191 if isinstance(cmd, list):
198 proxy.set_proxy_environ()
199 gloablmounts = setup_chrootenv(self.rootdir, bindmounts)
200 subprocess.call(cmd, preexec_fn = mychroot, shell=shell)
201 except (OSError, IOError), err:
202 raise RuntimeError(err)
204 cleanup_chrootenv(self.rootdir, bindmounts, gloablmounts)
205 proxy.unset_proxy_environ()
210 cleanup_mounts(self.rootdir)
212 shutil.rmtree(self.rootdir, ignore_errors=True)