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 import chroot
27 from mic.plugin import pluginmgr
28 from mic.utils import proxy
29 from mic.utils import misc
30 from mic.utils import errors
32 minibase_grps = [ "tizen-bootstrap" ]
34 required_pkgs = [ "syslinux", "syslinux-extlinux", "satsolver-tools",
35 "libzypp", "python-zypp", "qemu-arm-static", "mic" ]
38 def query_package_rpmdb(root='/', tag='name', pattern=None):
41 ts = rpm.TransactionSet(root)
42 mi = ts.dbMatch(tag, pattern)
44 version = hdr['version']
45 return (name, version)
47 def query_package_metadat(root='/', tag='name', pattern=None):
51 with open(root + '/.metadata', 'r') as f:
52 metadata = pickle.load(f)
55 raise errors.BootstrapError("Load %s/.metadata error" % root)
57 for pkg in metadata.keys():
58 m = misc.RPM_RE.match(pkg)
60 (n, a, v, r) = m.groups()
62 raise errors.BootstrapError("Wrong Format .metadata in %s"
66 return (name, version)
68 class Bootstrap(object):
69 def __init__(self, homedir='/var/mic/bootstrap', **kwargs):
73 self.homedir = homedir
75 if not os.path.exists(self.homedir):
76 os.makedirs(self.homedir)
78 self.__dict__.update(**kwargs)
80 def _setRootdir(self, name):
81 self._rootdir = os.path.join(self.homedir, name)
83 def _getRootdir(self):
84 if not os.path.exists(self._rootdir):
85 raise errors.BootstrapError("dir: %s not exist" % self._rootdir)
88 rootdir = property(fget = lambda self: self._getRootdir(),
89 fset = lambda self, name: self._setRootdir(name),
90 doc = 'root directory')
92 def _setPkgmgr(self, name):
93 backend_plugins = pluginmgr.get_plugins('backend')
94 for (key, cls) in backend_plugins.iteritems():
98 raise errors.BootstrapError("Backend: %s can't be loaded correctly"\
101 pkgmgr = property(fget = lambda self: self._pkgmgr,
102 fset = lambda self, name: self._setPkgmgr(name),
103 doc = 'package manager')
106 def bootstraps(self):
108 return self._bootstraps
109 for dir in os.listdir(self.homedir):
110 metadata_fp = os.path.join(self.homedir, dir, '.metadata')
111 if os.path.exists(metadata_fp) \
112 and 0 != os.path.getsize(metadata_fp):
113 self._bootstraps.append(dir)
114 return self._bootstraps
116 def run(self, name, cmd, chdir='/', bindmounts=None):
119 os.chroot(self.rootdir)
122 if isinstance(cmd, list):
125 lvl = msger.get_loglevel()
126 msger.set_loglevel('quiet')
127 globalmounts = chroot.setup_chrootenv(self.rootdir, bindmounts)
129 proxy.set_proxy_environ()
130 subprocess.call(cmd, preexec_fn=mychroot, shell=True)
131 proxy.unset_proxy_environ()
133 raise errors.BootstrapError("Run in bootstrap fail")
135 chroot.cleanup_chrootenv(self.rootdir, bindmounts, globalmounts)
137 msger.set_loglevel(lvl)
139 def list(self, **kwargs):
141 for binst in self.bootstraps:
142 (mver, kver, rver) = self.status(binst)
143 bsinfo = {'name':binst, 'meego':mver, 'kernel':kver, 'rpm': rver}
144 bslist.append(bsinfo)
148 def status(self, name):
150 if os.path.exists(self.rootdir + '/.metadata'):
151 query_package = query_package_metadat
153 query_package = query_package_rpmdb
155 name, mver = query_package(self.rootdir, 'name', 'meego-release')
156 msger.debug("MeeGo Release: %s" % mver)
158 name, kver = query_package(self.rootdir, 'name', 'kernel')
159 msger.debug("Kernel Version: %s" % kver)
161 name, rver = query_package(self.rootdir, 'name', 'rpm')
162 msger.debug("RPM Version: %s" % rver)
164 return (mver, kver, rver)
166 def create(self, name, repolist, **kwargs):
171 self.cachedir = '/var/tmp/mic/cache' # TBD from conf, do NOT hardcode
174 self.arch = kwargs['arch']
175 if 'cachedir' in kwargs:
176 self.cachedir = kwargs['cachedir']
178 if os.path.exists(self._rootdir):
179 metadata_fp = os.path.join(self._rootdir, '.metadata')
180 if os.path.exists(metadata_fp) and \
181 0 != os.path.getsize(metadata_fp):
182 msger.warning("bootstrap already exists") # TBD more details
185 shutil.rmtree(self._rootdir)
187 if not os.path.exists(self._rootdir):
188 os.makedirs(self._rootdir)
190 pkg_manager = self.pkgmgr(self.arch, self.rootdir, self.cachedir)
193 for repo in repolist:
195 pkg_manager.addRepository(repo['name'], repo['baseurl'],
198 pkg_manager.addRepository(repo['name'], repo['baseurl'])
200 rpm.addMacro("_dbpath", "/var/lib/rpm")
201 rpm.addMacro("__file_context_path", "%{nil}")
203 for grp in minibase_grps:
204 pkg_manager.selectGroup(grp)
205 for pkg in minibase_pkgs:
206 pkg_manager.selectPackage(pkg)
207 for pkg in required_pkgs:
208 pkg_manager.selectPackage(pkg)
211 pkg_manager.runInstall(512 * 1024L * 1024L)
213 raise errors.BootstrapError("Create bootstrap fail")
215 metadata = pkg_manager.getAllContent()
216 metadata_fp = os.path.join(self.rootdir, '.metadata')
217 with open(metadata_fp, 'w') as f:
218 pickle.dump(metadata, f)
221 pkg_manager.closeRpmDB()
224 # Copy bootstrap repo files
225 srcdir = "%s/etc/zypp/repos.d/" % self.cachedir
226 destdir= "%s/etc/zypp/repos.d/" % os.path.abspath(self.rootdir)
227 shutil.rmtree(destdir, ignore_errors = True)
228 shutil.copytree(srcdir, destdir)
229 # create '/tmp' in chroot
230 _tmpdir = os.path.join(os.path.abspath(self.rootdir), "tmp")
231 if not os.path.exists(_tmpdir):
234 msger.info("Bootstrap created.")
239 def update(self, name):
241 chrootdir = self.rootdir
246 shutil.copyfile("/etc/resolv.conf", chrootdir + "/etc/resolv.conf")
248 subprocess.call("zypper -n --no-gpg-checks update",
249 preexec_fn=mychroot, shell=True)
251 raise errors.BootstrapError("Bootstrap: %s update failed" %\
254 def cleanup(self, name):
257 chroot.cleanup_mounts(self.rootdir)
258 shutil.rmtree(self.rootdir, ignore_errors=True)
260 raise errors.BootstrapError("Bootstrap: %s clean up failed" %\