summaryrefslogtreecommitdiffstats
path: root/meta/lib/oe
diff options
context:
space:
mode:
authorHongxu Jia <hongxu.jia@windriver.com>2014-01-26 17:40:55 +0800
committerRichard Purdie <richard.purdie@linuxfoundation.org>2014-02-11 11:53:41 +0000
commitc8103fba58c59acbfc541aec6c9c03315613766a (patch)
treebf71ea04d8fa4de0651ba742f45ed825126c5c32 /meta/lib/oe
parentdff8a593afc880a18c2a48d33161cefb45263c8e (diff)
downloadpoky-c8103fba58c59acbfc541aec6c9c03315613766a.tar.gz
lib/oe/package_manager.py: support RpmPM
- Implementation RpmPM class - Support rpm incremental image generation (From OE-Core rev: ca5203d6b1bb0cbf7830ea4f46109c6867138efc) Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com> Signed-off-by: Laurentiu Palcu <laurentiu.palcu@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/lib/oe')
-rw-r--r--meta/lib/oe/package_manager.py656
1 files changed, 651 insertions, 5 deletions
diff --git a/meta/lib/oe/package_manager.py b/meta/lib/oe/package_manager.py
index e802edd492..15e56b550d 100644
--- a/meta/lib/oe/package_manager.py
+++ b/meta/lib/oe/package_manager.py
@@ -1,8 +1,63 @@
1from abc import ABCMeta, abstractmethod 1from abc import ABCMeta, abstractmethod
2import os 2import os
3import glob
3import subprocess 4import subprocess
5import shutil
4import multiprocessing 6import multiprocessing
5import re 7import re
8import bb
9
10DB_CONFIG_CONTENT = '''# ================ Environment
11set_data_dir .
12set_create_dir .
13set_lg_dir ./log
14set_tmp_dir ./tmp
15set_flags db_log_autoremove on
16
17# -- thread_count must be >= 8
18set_thread_count 64
19
20# ================ Logging
21
22# ================ Memory Pool
23set_cachesize 0 1048576 0
24set_mp_mmapsize 268435456
25
26# ================ Locking
27set_lk_max_locks 16384
28set_lk_max_lockers 16384
29set_lk_max_objects 16384
30mutex_set_max 163840
31
32# ================ Replication
33'''
34
35SCRIPTLET_FORMAT = '''#!/bin/bash
36
37export PATH=%s
38export D=%s
39export OFFLINE_ROOT="$D"
40export IPKG_OFFLINE_ROOT="$D"
41export OPKG_OFFLINE_ROOT="$D"
42export INTERCEPT_DIR=%s
43export NATIVE_ROOT=%s
44
45$2 $1/$3 $4
46if [ $? -ne 0 ]; then
47 if [ $4 -eq 1 ]; then
48 mkdir -p $1/etc/rpm-postinsts
49 num=100
50 while [ -e $1/etc/rpm-postinsts/${num}-* ]; do num=$((num + 1)); done
51 name=`head -1 $1/$3 | cut -d\' \' -f 2`
52 echo "#!$2" > $1/etc/rpm-postinsts/${num}-${name}
53 echo "# Arg: $4" >> $1/etc/rpm-postinsts/${num}-${name}
54 cat $1/$3 >> $1/etc/rpm-postinsts/${num}-${name}
55 chmod +x $1/etc/rpm-postinsts/${num}-${name}
56 else
57 echo "Error: pre/post remove scriptlet failed"
58 fi
59fi
60'''
6 61
7 62
8# this can be used by all PM backends to create the index files in parallel 63# this can be used by all PM backends to create the index files in parallel
@@ -127,13 +182,604 @@ class PackageManager(object):
127 182
128 self.deploy_lock = None 183 self.deploy_lock = None
129 184
185
130class RpmPM(PackageManager): 186class RpmPM(PackageManager):
131 def __init__(self): 187 def __init__(self,
132 super(RpmPM, self).__init__() 188 d,
189 target_rootfs,
190 package_archs,
191 target_os,
192 target_vendor,
193 task_name='target',
194 providename=None):
195 super(RpmPM, self).__init__(d)
196 self.target_rootfs = target_rootfs
197 self.ml_os_list = target_os
198 self.target_vendor = target_vendor
199 self.task_name = task_name
200 self.providename = providename
201 self.fullpkglist = list()
202 self.deploy_dir = self.d.getVar('DEPLOY_DIR_RPM', True)
203 self.etcrpm_dir = os.path.join(self.target_rootfs, "etc/rpm")
204 self.install_dir = os.path.join(self.target_rootfs, "install")
205 self.rpm_cmd = bb.utils.which(os.getenv('PATH'), "rpm")
206 self.smart_cmd = bb.utils.which(os.getenv('PATH'), "smart")
207 self.smart_opt = "--data-dir=" + os.path.join(target_rootfs,
208 'var/lib/smart')
209 self.scriptlet_wrapper = self.d.expand('${WORKDIR}/scriptlet_wrapper')
210 self.solution_manifest = self.d.expand('${T}/saved/%s_solution' %
211 self.task_name)
212 self.saved_rpmlib = self.d.expand('${T}/saved/%s' % self.task_name)
213 self.image_rpmlib = os.path.join(self.target_rootfs, 'var/lib/rpm')
214
215 if not os.path.exists(self.d.expand('${T}/saved')):
216 bb.utils.mkdirhier(self.d.expand('${T}/saved'))
217
218 # arch order is reversed. This ensures the -best- match is
219 # listed first!
220 self.ml_prefix_list = dict()
221 for mlib in package_archs:
222 if mlib == 'default':
223 self.ml_prefix_list[mlib] = package_archs[mlib]
224 else:
225 self.ml_prefix_list[mlib] = list()
226 for arch in package_archs[mlib]:
227 if arch in ['all', 'noarch', 'any']:
228 self.ml_prefix_list[mlib].append(arch)
229 else:
230 self.ml_prefix_list[mlib].append(mlib + "_" + arch)
231
232 '''
233 Create configs for rpm and smart, and multilib is supported
234 '''
235 def create_configs(self):
236 target_arch = self.d.getVar('TARGET_ARCH', True)
237 platform = '%s%s-%s' % (target_arch.replace('-', '_'),
238 self.target_vendor,
239 self.ml_os_list['default'])
240
241 # List must be prefered to least preferred order
242 default_platform_extra = list()
243 platform_extra = list()
244 bbextendvariant = self.d.getVar('BBEXTENDVARIANT', True) or ""
245 for mlib in self.ml_os_list:
246 for arch in self.ml_prefix_list[mlib]:
247 plt = arch.replace('-', '_') + '-.*-' + self.ml_os_list[mlib]
248 if mlib == bbextendvariant:
249 if plt not in default_platform_extra:
250 default_platform_extra.append(plt)
251 else:
252 if plt not in platform_extra:
253 platform_extra.append(plt)
254 platform_extra = default_platform_extra + platform_extra
133 255
134 """ 256 self._create_configs(platform, platform_extra)
135 TBD 257
136 """ 258 def _invoke_smart(self, args):
259 cmd = "%s %s %s" % (self.smart_cmd, self.smart_opt, args)
260 # bb.note(cmd)
261 try:
262 complementary_pkgs = subprocess.check_output(cmd, shell=True)
263 # bb.note(complementary_pkgs)
264 return complementary_pkgs
265 except subprocess.CalledProcessError as e:
266 bb.fatal("Could not invoke smart. Command "
267 "%s returned %d!" % (cmd, e.returncode))
268
269 '''
270 Translate the RPM/Smart format names to the OE multilib format names
271 '''
272 def _pkg_translate_smart_to_oe(self, pkg, arch):
273 new_pkg = pkg
274 fixed_arch = arch.replace('_', '-')
275 found = 0
276 for mlib in self.ml_prefix_list:
277 for cmp_arch in self.ml_prefix_list[mlib]:
278 fixed_cmp_arch = cmp_arch.replace('_', '-')
279 if fixed_arch == fixed_cmp_arch:
280 if mlib == 'default':
281 new_pkg = pkg
282 new_arch = cmp_arch
283 else:
284 new_pkg = mlib + '-' + pkg
285 # We need to strip off the ${mlib}_ prefix on the arch
286 new_arch = cmp_arch.replace(mlib + '_', '')
287
288 # Workaround for bug 3565. Simply look to see if we
289 # know of a package with that name, if not try again!
290 filename = os.path.join(self.d.getVar('PKGDATA_DIR', True),
291 'runtime-reverse',
292 new_pkg)
293 if os.path.exists(filename):
294 found = 1
295 break
296
297 if found == 1 and fixed_arch == fixed_cmp_arch:
298 break
299 #bb.note('%s, %s -> %s, %s' % (pkg, arch, new_pkg, new_arch))
300 return new_pkg, new_arch
301
302 def _search_pkg_name_in_feeds(self, pkg, feed_archs):
303 for arch in feed_archs:
304 arch = arch.replace('-', '_')
305 for p in self.fullpkglist:
306 if pkg in p and '@' + arch in p:
307 # First found is best match
308 # bb.note('%s -> %s' % (pkg, pkg + '@' + arch))
309 return pkg + '@' + arch
310
311 return ""
312
313 '''
314 Translate the OE multilib format names to the RPM/Smart format names
315 It searched the RPM/Smart format names in probable multilib feeds first,
316 and then searched the default base feed.
317 '''
318 def _pkg_translate_oe_to_smart(self, pkgs, attempt_only=False):
319 new_pkgs = list()
320
321 for pkg in pkgs:
322 new_pkg = pkg
323 # Search new_pkg in probable multilibs first
324 for mlib in self.ml_prefix_list:
325 # Jump the default archs
326 if mlib == 'default':
327 continue
328
329 subst = pkg.replace(mlib + '-', '')
330 # if the pkg in this multilib feed
331 if subst != pkg:
332 feed_archs = self.ml_prefix_list[mlib]
333 new_pkg = self._search_pkg_name_in_feeds(subst, feed_archs)
334 if not new_pkg:
335 # Failed to translate, package not found!
336 err_msg = '%s not found in the %s feeds (%s).\n' % \
337 (pkg, mlib, " ".join(feed_archs))
338 if not attempt_only:
339 err_msg += " ".join(self.fullpkglist)
340 bb.fatal(err_msg)
341 bb.warn(err_msg)
342 else:
343 new_pkgs.append(new_pkg)
344
345 break
346
347 # Apparently not a multilib package...
348 if pkg == new_pkg:
349 # Search new_pkg in default archs
350 default_archs = self.ml_prefix_list['default']
351 new_pkg = self._search_pkg_name_in_feeds(pkg, default_archs)
352 if not new_pkg:
353 err_msg = '%s not found in the base feeds (%s).\n' % \
354 (pkg, ' '.join(default_archs))
355 if not attempt_only:
356 err_msg += " ".join(self.fullpkglist)
357 bb.fatal(err_msg)
358 bb.warn(err_msg)
359 else:
360 new_pkgs.append(new_pkg)
361
362 return new_pkgs
363
364 def _create_configs(self, platform, platform_extra):
365 # Setup base system configuration
366 bb.note("configuring RPM platform settings")
367
368 # Configure internal RPM environment when using Smart
369 os.environ['RPM_ETCRPM'] = self.etcrpm_dir
370 bb.utils.mkdirhier(self.etcrpm_dir)
371
372 # Setup temporary directory -- install...
373 if os.path.exists(self.install_dir):
374 bb.utils.remove(self.install_dir, True)
375 bb.utils.mkdirhier(os.path.join(self.install_dir, 'tmp'))
376
377 channel_priority = 5
378 platform_dir = os.path.join(self.etcrpm_dir, "platform")
379 with open(platform_dir, "w+") as platform_fd:
380 platform_fd.write(platform + '\n')
381 for pt in platform_extra:
382 channel_priority += 5
383 platform_fd.write(pt + '.*\n')
384
385 # Tell RPM that the "/" directory exist and is available
386 bb.note("configuring RPM system provides")
387 sysinfo_dir = os.path.join(self.etcrpm_dir, "sysinfo")
388 bb.utils.mkdirhier(sysinfo_dir)
389 with open(os.path.join(sysinfo_dir, "Dirnames"), "w+") as dirnames:
390 dirnames.write("/\n")
391
392 if self.providename:
393 providename_dir = os.path.join(sysinfo_dir, "Providename")
394 if not os.path.exists(providename_dir):
395 providename_content = '\n'.join(self.providename)
396 providename_content += '\n'
397 open(providename_dir, "w+").write(providename_content)
398
399 # Configure RPM... we enforce these settings!
400 bb.note("configuring RPM DB settings")
401 # After change the __db.* cache size, log file will not be
402 # generated automatically, that will raise some warnings,
403 # so touch a bare log for rpm write into it.
404 rpmlib_log = os.path.join(self.image_rpmlib, 'log', 'log.0000000001')
405 if not os.path.exists(rpmlib_log):
406 bb.utils.mkdirhier(os.path.join(self.image_rpmlib, 'log'))
407 open(rpmlib_log, 'w+').close()
408 db_config_dir = os.path.join(self.image_rpmlib, 'DB_CONFIG')
409 if not os.path.exists(db_config_dir):
410 open(db_config_dir, 'w+').write(DB_CONFIG_CONTENT)
411
412 # Create database so that smart doesn't complain (lazy init)
413 cmd = "%s --root %s --dbpath /var/lib/rpm -qa > /dev/null" % (
414 self.rpm_cmd,
415 self.target_rootfs)
416 try:
417 subprocess.check_output(cmd, shell=True)
418 except subprocess.CalledProcessError as e:
419 bb.fatal("Create rpm database failed. Command %s "
420 "returned %d" % (cmd, e.returncode))
421
422 # Configure smart
423 bb.note("configuring Smart settings")
424 bb.utils.remove(os.path.join(self.target_rootfs, 'var/lib/smart'),
425 True)
426 self._invoke_smart('config --set rpm-root=%s' % self.target_rootfs)
427 self._invoke_smart('config --set rpm-dbpath=/var/lib/rpm')
428 self._invoke_smart('config --set rpm-extra-macros._var=%s' %
429 self.d.getVar('localstatedir', True))
430 cmd = 'config --set rpm-extra-macros._tmppath=/install/tmp'
431 self._invoke_smart(cmd)
432
433 # Write common configuration for host and target usage
434 self._invoke_smart('config --set rpm-nolinktos=1')
435 self._invoke_smart('config --set rpm-noparentdirs=1')
436 for i in self.d.getVar('BAD_RECOMMENDATIONS', True).split():
437 self._invoke_smart('flag --set ignore-recommends %s' % i)
438
439 # Do the following configurations here, to avoid them being
440 # saved for field upgrade
441 if self.d.getVar('NO_RECOMMENDATIONS', True).strip() == "1":
442 self._invoke_smart('config --set ignore-all-recommends=1')
443 pkg_exclude = self.d.getVar('PACKAGE_EXCLUDE', True) or ""
444 for i in pkg_exclude.split():
445 self._invoke_smart('flag --set exclude-packages %s' % i)
446
447 # Optional debugging
448 # self._invoke_smart('config --set rpm-log-level=debug')
449 # cmd = 'config --set rpm-log-file=/tmp/smart-debug-logfile'
450 # self._invoke_smart(cmd)
451
452 for canonical_arch in platform_extra:
453 arch = canonical_arch.split('-')[0]
454 arch_channel = os.path.join(self.deploy_dir, arch)
455 if os.path.exists(arch_channel):
456 bb.note('Note: adding Smart channel %s (%s)' %
457 (arch, channel_priority))
458 self._invoke_smart('channel --add %s type=rpm-md baseurl=%s -y'
459 % (arch, arch_channel))
460 self._invoke_smart('channel --set %s priority=%d' %
461 (arch, channel_priority))
462 channel_priority -= 5
463
464 bb.note('adding Smart RPM DB channel')
465 self._invoke_smart('channel --add rpmsys type=rpm-sys -y')
466
467 # Construct install scriptlet wrapper.
468 # Scripts need to be ordered when executed, this ensures numeric order.
469 # If we ever run into needing more the 899 scripts, we'll have to.
470 # change num to start with 1000.
471 #
472 intercept_dir = self.d.expand('${WORKDIR}/intercept_scripts')
473 native_root = self.d.getVar('STAGING_DIR_NATIVE', True)
474 scriptlet_content = SCRIPTLET_FORMAT % (os.environ['PATH'],
475 self.target_rootfs,
476 intercept_dir,
477 native_root)
478 open(self.scriptlet_wrapper, 'w+').write(scriptlet_content)
479
480 bb.note("Note: configuring RPM cross-install scriptlet_wrapper")
481 os.chmod(self.scriptlet_wrapper, 0755)
482 cmd = 'config --set rpm-extra-macros._cross_scriptlet_wrapper=%s' % \
483 self.scriptlet_wrapper
484 self._invoke_smart(cmd)
485
486 # Debug to show smart config info
487 # bb.note(self._invoke_smart('config --show'))
488
489 def update(self):
490 self._invoke_smart('update rpmsys')
491
492 '''
493 Install pkgs with smart, the pkg name is oe format
494 '''
495 def install(self, pkgs, attempt_only=False):
496
497 bb.note("Installing the following packages: %s" % ' '.join(pkgs))
498 if len(pkgs) == 0:
499 return
500 pkgs = self._pkg_translate_oe_to_smart(pkgs, attempt_only)
501
502 if not attempt_only:
503 bb.note('to be installed: %s' % ' '.join(pkgs))
504 cmd = "%s %s install -y %s" % \
505 (self.smart_cmd, self.smart_opt, ' '.join(pkgs))
506 bb.note(cmd)
507 else:
508 bb.note('installing attempt only packages...')
509 bb.note('Attempting %s' % ' '.join(pkgs))
510 cmd = "%s %s install --attempt -y %s" % \
511 (self.smart_cmd, self.smart_opt, ' '.join(pkgs))
512 try:
513 output = subprocess.check_output(cmd.split())
514 bb.note(output)
515 except subprocess.CalledProcessError as e:
516 if not attempt_only:
517 bb.note("Unable to install packages. Command %s "
518 "returned %d" % (cmd, e.returncode))
519
520 '''
521 Remove pkgs with smart, the pkg name is smart/rpm format
522 '''
523 def remove(self, pkgs, with_dependencies=True):
524 bb.note('to be removed: ' + ' '.join(pkgs))
525
526 if not with_dependencies:
527 cmd = "%s -e --nodeps " % self.rpm_cmd
528 cmd += "--root=%s " % self.target_rootfs
529 cmd += "--dbpath=/var/lib/rpm "
530 cmd += "--define='_cross_scriptlet_wrapper %s' " % \
531 self.scriptlet_wrapper
532 cmd += "--define='_tmppath /install/tmp' %s" % ' '.join(pkgs)
533 else:
534 # for pkg in pkgs:
535 # bb.note('Debug: What required: %s' % pkg)
536 # bb.note(self._invoke_smart('query %s --show-requiredby' % pkg))
537
538 cmd = "%s %s remove -y %s" % (self.smart_cmd,
539 self.smart_opt,
540 ' '.join(pkgs))
541
542 try:
543 bb.note(cmd)
544 output = subprocess.check_output(cmd, shell=True)
545 bb.note(output)
546 except subprocess.CalledProcessError as e:
547 bb.note("Unable to remove packages. Command %s "
548 "returned %d" % (cmd, e.returncode))
549
550 def upgrade(self):
551 bb.note('smart upgrade')
552 self._invoke_smart('upgrade')
553
554 def write_index(self):
555 arch_list = list()
556 for mlib in self.ml_prefix_list:
557 for arch in self.ml_prefix_list[mlib]:
558 if arch not in arch_list:
559 arch_list.append(arch)
560
561 sdk_pkg_archs = self.d.getVar('SDK_PACKAGE_ARCHS', True)
562 if sdk_pkg_archs is not None:
563 arch_list += [i.replace('-', '_') for i in sdk_pkg_archs.split()
564 if i.replace('-', '_') not in arch_list]
565
566 rpm_createrepo = bb.utils.which(os.getenv('PATH'), "createrepo")
567 index_cmds = []
568 rpm_dirs_found = False
569 for arch in arch_list:
570 arch_dir = os.path.join(self.deploy_dir, arch)
571 if not os.path.isdir(arch_dir):
572 continue
573
574 index_cmds.append("%s --update -q %s" % (rpm_createrepo, arch_dir))
575
576 rpm_dirs_found = True
577
578 if not rpm_dirs_found:
579 bb.fatal("There are no packages in %s" % self.deploy_dir)
580
581 nproc = multiprocessing.cpu_count()
582 pool = bb.utils.multiprocessingpool(nproc)
583 results = list(pool.imap(create_index, index_cmds))
584 pool.close()
585 pool.join()
586
587 for result in results:
588 if result is not None:
589 bb.fatal(result)
590
591 def remove_packaging_data(self):
592 bb.utils.remove(self.image_rpmlib, True)
593 bb.utils.remove(os.path.join(self.target_rootfs, 'var/lib/smart'),
594 True)
595 bb.utils.remove(os.path.join(self.target_rootfs, 'var/lib/opkg'), True)
596
597 # remove temp directory
598 bb.utils.remove(self.d.expand('${IMAGE_ROOTFS}/install'), True)
599
600 def backup_packaging_data(self):
601 # Save the rpmlib for increment rpm image generation
602 if os.path.exists(self.saved_rpmlib):
603 bb.utils.remove(self.saved_rpmlib, True)
604 shutil.copytree(self.image_rpmlib,
605 self.saved_rpmlib,
606 symlinks=True)
607
608 def recovery_packaging_data(self):
609 # Move the rpmlib back
610 if os.path.exists(self.saved_rpmlib):
611 if os.path.exists(self.image_rpmlib):
612 bb.utils.remove(self.image_rpmlib, True)
613
614 bb.note('Recovery packaging data')
615 shutil.copytree(self.saved_rpmlib,
616 self.image_rpmlib,
617 symlinks=True)
618
619 def list_installed(self, format=None):
620 cmd = self.rpm_cmd + ' --root ' + self.target_rootfs
621 cmd += ' -D "_dbpath /var/lib/rpm" -qa'
622 cmd += " --qf '[%{NAME} %{ARCH} %{VERSION} %{PACKAGEORIGIN}\n]'"
623
624 try:
625 # bb.note(cmd)
626 tmp_output = subprocess.check_output(cmd, shell=True).strip()
627 self._unlock_rpm_db()
628 except subprocess.CalledProcessError as e:
629 bb.fatal("Cannot get the installed packages list. Command %s "
630 "returned %d" % (cmd, e.returncode))
631
632 output = list()
633 for line in tmp_output.split('\n'):
634 if len(line.strip()) == 0:
635 continue
636 pkg = line.split()[0]
637 arch = line.split()[1]
638 ver = line.split()[2]
639 pkgorigin = line.split()[3]
640 new_pkg, new_arch = self._pkg_translate_smart_to_oe(pkg, arch)
641
642 if format == "arch":
643 output.append('%s %s' % (new_pkg, new_arch))
644 elif format == "file":
645 output.append('%s %s %s' % (new_pkg, pkgorigin, new_arch))
646 elif format == "ver":
647 output.append('%s %s %s' % (new_pkg, new_arch, ver))
648 else:
649 output.append('%s' % (new_pkg))
650
651 output.sort()
652
653 return '\n'.join(output)
654
655 '''
656 If incremental install, we need to determine what we've got,
657 what we need to add, and what to remove...
658 The dump_install_solution will dump and save the new install
659 solution.
660 '''
661 def dump_install_solution(self, pkgs):
662 bb.note('creating new install solution for incremental install')
663 if len(pkgs) == 0:
664 return
665
666 pkgs = self._pkg_translate_oe_to_smart(pkgs, False)
667 install_pkgs = list()
668
669 cmd = "%s %s install -y --dump %s 2>%s" % \
670 (self.smart_cmd,
671 self.smart_opt,
672 ' '.join(pkgs),
673 self.solution_manifest)
674 try:
675 # Disable rpmsys channel for the fake install
676 self._invoke_smart('channel --disable rpmsys')
677
678 subprocess.check_output(cmd, shell=True)
679 with open(self.solution_manifest, 'r') as manifest:
680 for pkg in manifest.read().split('\n'):
681 if '@' in pkg:
682 install_pkgs.append(pkg)
683 except subprocess.CalledProcessError as e:
684 bb.note("Unable to dump install packages. Command %s "
685 "returned %d" % (cmd, e.returncode))
686 # Recovery rpmsys channel
687 self._invoke_smart('channel --enable rpmsys')
688 return install_pkgs
689
690 '''
691 If incremental install, we need to determine what we've got,
692 what we need to add, and what to remove...
693 The load_old_install_solution will load the previous install
694 solution
695 '''
696 def load_old_install_solution(self):
697 bb.note('load old install solution for incremental install')
698 installed_pkgs = list()
699 if not os.path.exists(self.solution_manifest):
700 bb.note('old install solution not exist')
701 return installed_pkgs
702
703 with open(self.solution_manifest, 'r') as manifest:
704 for pkg in manifest.read().split('\n'):
705 if '@' in pkg:
706 installed_pkgs.append(pkg.strip())
707
708 return installed_pkgs
709
710 '''
711 Dump all available packages in feeds, it should be invoked after the
712 newest rpm index was created
713 '''
714 def dump_all_available_pkgs(self):
715 available_manifest = self.d.expand('${T}/saved/available_pkgs.txt')
716 available_pkgs = list()
717 cmd = "%s %s query --output %s" % \
718 (self.smart_cmd, self.smart_opt, available_manifest)
719 try:
720 subprocess.check_output(cmd, shell=True)
721 with open(available_manifest, 'r') as manifest:
722 for pkg in manifest.read().split('\n'):
723 if '@' in pkg:
724 available_pkgs.append(pkg.strip())
725 except subprocess.CalledProcessError as e:
726 bb.note("Unable to list all available packages. Command %s "
727 "returned %d" % (cmd, e.returncode))
728
729 self.fullpkglist = available_pkgs
730
731 return
732
733 def save_rpmpostinist(self, pkg):
734 mlibs = self.d.getVar('MULTILIB_GLOBAL_VARIANTS').split()
735 new_pkg = pkg
736 # Remove any multilib prefix from the package name
737 for mlib in mlibs:
738 if mlib in pkg:
739 new_pkg = pkg.replace(mlib + '-', '')
740 break
741
742 bb.note(' * postponing %s' % new_pkg)
743 saved_dir = self.image_rootfs + self.d.expand('${sysconfdir}/rpm-postinsts/') + new_pkg
744 cmd = self.rpm_cmd + ' -q --scripts --root ' + self.target_rootfs
745 cmd += ' --dbpath=/var/lib/rpm ' + new_pkg
746 cmd += ' | sed -n -e "/^postinstall scriptlet (using .*):$/,/^.* scriptlet (using .*):$/ {/.*/p}"'
747 cmd += ' | sed -e "s/postinstall scriptlet (using \(.*\)):$/#!\1/"'
748 cmd += ' -e "/^.* scriptlet (using .*):$/d" > %s' % saved_dir
749
750 try:
751 bb.note(cmd)
752 output = subprocess.check_output(cmd, shell=True).strip()
753 bb.note(output)
754 os.chmod(saved_dir, 0755)
755 self._unlock_rpm_db()
756 except subprocess.CalledProcessError as e:
757 bb.fatal("Invoke save_rpmpostinist failed. Command %s "
758 "returned %d" % (cmd, e.returncode))
759
760 '''Write common configuration for target usage'''
761 def rpm_setup_smart_target_config(self):
762 bb.utils.remove(os.path.join(self.target_rootfs, 'var/lib/smart'),
763 True)
764
765 self._invoke_smart('config --set rpm-nolinktos=1')
766 self._invoke_smart('config --set rpm-noparentdirs=1')
767 for i in self.d.getVar('BAD_RECOMMENDATIONS', True).split():
768 self._invoke_smart('flag --set ignore-recommends %s' % i)
769 self._invoke_smart('channel --add rpmsys type=rpm-sys -y')
770
771 self._unlock_rpm_db()
772
773 '''
774 The rpm db lock files were produced after invoking rpm to query on
775 build system, and they caused the rpm on target didn't work, so we
776 need to unlock the rpm db by removing the lock files.
777 '''
778 def _unlock_rpm_db(self):
779 # Remove rpm db lock files
780 rpm_db_locks = glob.glob('%s/var/lib/rpm/__db.*' % self.target_rootfs)
781 for f in rpm_db_locks:
782 bb.utils.remove(f, True)
137 783
138 784
139class OpkgPM(PackageManager): 785class OpkgPM(PackageManager):