Bug 4120 - rootfs_deb doesn't support BAD_RECOMMENDATIONS
Summary: rootfs_deb doesn't support BAD_RECOMMENDATIONS
Status: NEW
Alias: None
Product: OE-Core
Classification: Build System, Metadata & Runtime
Component: core (show other bugs)
Version: 1.4
Hardware: x86 Multiple
: Medium enhancement
Target Milestone: Future
Assignee: Unassigned
QA Contact:
URL:
Whiteboard:
Depends on:
Blocks:
 
Reported: 2013-03-26 17:13 UTC by Ross Burton
Modified: 2025-02-06 16:14 UTC (History)
10 users (show)

See Also:
OS type for building Yocto: ---
Type of Regression: ---
Verified:
Documentation change: Don't know


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ross Burton 2013-03-26 17:13:43 UTC
BAD_RECOMMENDATIONS is only implemented for rootfs_ipkg at present.

(see 3916 for the rootfs_rpm bug)
Comment 1 Mark Hatle 2013-07-16 17:28:34 UTC
This is about image generation and not deployment.
Comment 2 Hongxu Jia 2013-09-02 09:02:03 UTC
Move to 1.6
Comment 3 Manish Das 2018-10-29 08:34:41 UTC
We tried to add below "handle_bad_recommendations(self)" function in package_manger.py to handle BAD_RECOMMENDATION for dpkg
here we are adding 

"Status: hold ok not-installed" in dpkg status file and trying to hold the specified package for  bad_recommendation.

It looks like  that "Status: hold ok not-installed" is not working for "apt-get" command.

After modifying "status:hold ok not-installed" in dpkg status file also, it is not able to hold for particular package which is specified in "BAD_RECOMMENDATION" and it is getting installed. 

It seems that issue is with apt-get.
Till the time apt-get  does not support to  prevent installation  of specific package, from a list of specified packages, BAD_RECOMMENDATIONS will not work for DPKG 


    def handle_bad_recommendations(self):
        bad_recommendations = (self.d.getVar("BAD_RECOMMENDATIONS", True) or "").strip()
        if not bad_recommendations:
            return
        status_file = self.target_rootfs + "/var/lib/dpkg/status"
        with open(status_file + ".tmp", "w") as status:
            for pkg in bad_recommendations.split():
                pkg_info = ('apt-cache', 'show', pkg)
                try:
                    output = subprocess.check_output(pkg_info, stderr=subprocess.STDOUT).decode("utf-8")
                except subprocess.CalledProcessError as e:
                    bb.fatal("Cannot get package info. Command '%s' "
                             "returned %d:\n%s" % (' '.join(pkg_info), e.returncode, e.output))
                for line in output.splitlines():
                    if not line:
                        status.write("Status: hold ok not-installed\n\n")
                        break
                    if line.startswith(' ') or line.split(': ', 1)[0] not in ('Filename', 'Size', 'MD5sum', 'MSDOS-Filename'):
                        status.write(line + "\n")
        os.rename(status_file + ".tmp", status_file)

So it looks like once apt-get support for "Status: hold ok not-installed" then by using above method we BAD_RECOMMENDATIONS should work for DPKG.
Comment 4 Ross Burton 2018-10-29 11:09:11 UTC
I believe this syntax works with apt:

$ apt-get install foo bar-

Where foo recommends bar, but bar won't be installed because it has a - suffix.
Comment 5 Manish Das 2018-11-01 01:23:44 UTC
"$ apt-get install foo bar-
Where foo recommends bar, but bar won't be installed because it has a - suffix"

As per our understating above command will remove the  specified package AFTER that package is installed. However, our target here is to prevent the installation of specified package which has been mentioned for "bad_recommendations"

We tried to remove the package after installation using below specified function under class DpkgPM(OpkgDpkgPM) but we don't think it is the correct way. Please let us know if there is any apt -get command which can prevent installation of specific package from a list of specified packages.

def install(self, pkgs, attempt_only=False): 
bad_recommendations = (self.d.getVar("BAD_RECOMMENDATIONS", True) or "").strip()
if  bad_recommendations:
    pkg=bad_recommendations.split()
    cmd = "%s --admindir=%s/var/lib/dpkg --instdir=%s"" -P --force-depends %s" % \
          (bb.utils.which(os.getenv('PATH'), "dpkg"),self.target_rootfs, self.target_rootfs,' '.join(pkg))
    try:
        bb.note("Installing the following packages: %s" % ' '.join(pkgs))
        subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError as e:
        (bb.fatal, bb.warn)[attempt_only]("Unable to install packages. "
                                      "Command '%s' returned %d:\n%s" %
                                      (cmd, e.returncode, e.output.decode("utf-8")))
Comment 6 Ross Burton 2018-11-01 11:25:26 UTC
That might be what the docs say but it's not what happens: it doesn't install a package and then uninstall it.

eg a2ps in Debian:

Package: a2ps
Version: 1:4.14-2
Installed-Size: 3624
Maintainer: Debian QA Group <packages@qa.debian.org>
Architecture: amd64
Depends: file, psutils, libc6 (>= 2.14), libpaper1
Recommends: bzip2, lpr | rlpr | cupsys-client, wdiff
Suggests: emacsen-common, ghostscript, graphicsmagick-imagemagick-compat | imagemagick, groff, gv, html2ps, t1-cyrillic, texlive-base-bin

$ sudo apt-get install a2ps
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
  lpr psutils wdiff
Suggested packages:
  graphicsmagick-imagemagick-compat | imagemagick groff gv html2ps t1-cyrillic texlive-base-bin magicfilter
  | apsfilter gs wdiff-doc
The following NEW packages will be installed:
  a2ps lpr psutils wdiff
0 upgraded, 4 newly installed, 0 to remove and 0 not upgraded.
Need to get 916 kB of archives.
After this operation, 4,925 kB of additional disk space will be used.

Note how the recommends lpr and wdiff are being installed.

Here I tell it not to install the recommendations:

$ sudo apt-get install a2ps lpr- lprng- cups-bsd- wdiff-
Reading package lists... Done
Building dependency tree
Reading state information... Done
Package 'lpr' is not installed, so not removed
Package 'lprng' is not installed, so not removed
Package 'wdiff' is not installed, so not removed
Package 'cups-bsd' is not installed, so not removed
The following additional packages will be installed:
  psutils
Suggested packages:
  graphicsmagick-imagemagick-compat | imagemagick groff gv html2ps t1-cyrillic texlive-base-bin
Recommended packages:
  lpr | rlpr | cupsys-client wdiff
The following NEW packages will be installed:
  a2ps psutils
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
Need to get 700 kB of archives.
After this operation, 3,935 kB of additional disk space will be used.
Comment 7 Manish Das 2018-11-12 06:49:26 UTC
We tried the commands mentioned below:
sudo apt-get install a2ps lpr- lprng- cups-bsd- wdiff-

But when we use this command it gives error due to the package dependency while installing. So it throws  error and bitbake stops, this  behavior is  for 'core-image-sato-sdk'We tired other packages like 'acl','debianutils','connman' etc. all gave error due to dependency. 


We tried the method which is first install and then remove the package mentioned in BAD_RECOMMENDATIONS as mentioned below
  
def install(self, pkgs, attempt_only=False):
bad_recommendations = (self.d.getVar("BAD_RECOMMENDATIONS", True) or "").strip()
if  bad_recommendations:
    pkg=bad_recommendations.split()
    cmd = "%s purge %s" % (self.apt_get_cmd, ' '.join(pkg))

    try:
        bb.warn("It will be remove :  %s  package from the list " % ' '.join(pkgs))
        subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError as e:
        (bb.fatal, bb.warn)[attempt_only]("Unable to remove packages. "
                                      "Command '%s' returned %d:\n%s" %(cmd, e.returncode, e.output.decode("utf-8")))

This works fine and removes the package mentioned in BAD_RECOMMENDATIONS with a warning. 

@Ross: Please suggest if this solution is OK or we need to look for other alternative solutions.