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("Root 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" % name)
100 pkgmgr = property(fget = lambda self: self._pkgmgr,
101 fset = lambda self, name: self._setPkgmgr(name),
102 doc = 'package manager')
105 def bootstraps(self):
107 return self._bootstraps
108 for dir in os.listdir(self.homedir):
109 metadata_fp = os.path.join(self.homedir, dir, '.metadata')
110 if os.path.exists(metadata_fp) \
111 and 0 != os.path.getsize(metadata_fp):
112 self._bootstraps.append(dir)
113 return self._bootstraps
115 def run(self, name, cmd, chdir='/', bindmounts=None):
118 os.chroot(self.rootdir)
121 if isinstance(cmd, list):
124 lvl = msger.get_loglevel()
125 msger.set_loglevel('quiet')
126 globalmounts = chroot.setup_chrootenv(self.rootdir, bindmounts)
128 proxy.set_proxy_environ()
129 subprocess.call(cmd, preexec_fn=mychroot, shell=True)
130 proxy.unset_proxy_environ()
132 raise errors.BootstrapError("Run in bootstrap fail")
134 chroot.cleanup_chrootenv(self.rootdir, bindmounts, globalmounts)
136 msger.set_loglevel(lvl)
138 def list(self, **kwargs):
140 for binst in self.bootstraps:
141 (mver, kver, rver) = self.status(binst)
142 bsinfo = {'name':binst, 'meego':mver, 'kernel':kver, 'rpm': rver}
143 bslist.append(bsinfo)
147 def status(self, name):
149 if os.path.exists(self.rootdir + '/.metadata'):
150 query_package = query_package_metadat
152 query_package = query_package_rpmdb
154 name, mver = query_package(self.rootdir, 'name', 'meego-release')
155 msger.debug("MeeGo Release: %s" % mver)
157 name, kver = query_package(self.rootdir, 'name', 'kernel')
158 msger.debug("Kernel Version: %s" % kver)
160 name, rver = query_package(self.rootdir, 'name', 'rpm')
161 msger.debug("RPM Version: %s" % rver)
163 return (mver, kver, rver)
165 def create(self, name, repolist, **kwargs):
170 self.cachedir = '/var/tmp/mic/cache' # TBD from conf, do NOT hardcode
173 self.arch = kwargs['arch']
174 if 'cachedir' in kwargs:
175 self.cachedir = kwargs['cachedir']
177 if os.path.exists(self._rootdir):
178 metadata_fp = os.path.join(self._rootdir, '.metadata')
179 if os.path.exists(metadata_fp) and \
180 0 != os.path.getsize(metadata_fp):
181 msger.warning("bootstrap already exists") # TBD more details
184 shutil.rmtree(self._rootdir)
186 if not os.path.exists(self._rootdir):
187 os.makedirs(self._rootdir)
189 pkg_manager = self.pkgmgr(self.arch, self.rootdir, self.cachedir)
192 for repo in repolist:
193 if 'proxy' in repo.keys():
194 pkg_manager.addRepository(repo['name'], repo['baseurl'], proxy = repo['proxy'])
196 pkg_manager.addRepository(repo['name'], repo['baseurl'])
198 rpm.addMacro("_dbpath", "/var/lib/rpm")
199 rpm.addMacro("__file_context_path", "%{nil}")
201 for grp in minibase_grps:
202 pkg_manager.selectGroup(grp)
203 for pkg in minibase_pkgs:
204 pkg_manager.selectPackage(pkg)
205 for pkg in required_pkgs:
206 pkg_manager.selectPackage(pkg)
209 pkg_manager.runInstall(512 * 1024L * 1024L)
211 raise errors.BootstrapError("Create bootstrap fail")
213 metadata = pkg_manager.getAllContent()
214 metadata_fp = os.path.join(self.rootdir, '.metadata')
215 with open(metadata_fp, 'w') as f:
216 pickle.dump(metadata, f)
219 pkg_manager.closeRpmDB()
222 # Copy bootstrap repo files
223 srcdir = "%s/etc/zypp/repos.d/" % self.cachedir
224 destdir= "%s/etc/zypp/repos.d/" % os.path.abspath(self.rootdir)
225 shutil.rmtree(destdir, ignore_errors = True)
226 shutil.copytree(srcdir, destdir)
227 # create '/tmp' in chroot
228 if not os.path.exists(os.path.join(os.path.abspath(self.rootdir), "tmp")):
229 os.makedirs(os.path.join(os.path.abspath(self.rootdir), "tmp"))
231 msger.info("Bootstrap created.")
236 def update(self, name):
238 chrootdir = self.rootdir
243 shutil.copyfile("/etc/resolv.conf", chrootdir + "/etc/resolv.conf")
245 subprocess.call("zypper -n --no-gpg-checks update", preexec_fn=mychroot, shell=True)
247 raise errors.BootstrapError("Bootstrap: %s Update fail" % chrootdir)
249 def cleanup(self, name):
252 chroot.cleanup_mounts(self.rootdir)
253 shutil.rmtree(self.rootdir, ignore_errors=True)
255 raise errors.BootstrapError("Bootstrap: %s clean up fail " % self.rootdir)