|
| 1 | +#!/usr/bin/env python |
| 2 | +# ex:ts=4:sw=4:sts=4:et |
| 3 | +# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- |
| 4 | +# |
| 5 | +# Copyright (c) 2017, Intel Corporation. |
| 6 | +# All rights reserved. |
| 7 | +# |
| 8 | +# This program is free software; you can redistribute it and/or modify |
| 9 | +# it under the terms of the GNU General Public License version 2 as |
| 10 | +# published by the Free Software Foundation. |
| 11 | +# |
| 12 | +# This program is distributed in the hope that it will be useful, |
| 13 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | +# GNU General Public License for more details. |
| 16 | +# |
| 17 | +# You should have received a copy of the GNU General Public License along |
| 18 | +# with this program; if not, write to the Free Software Foundation, Inc., |
| 19 | +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| 20 | +# |
| 21 | +# AUTHORS |
| 22 | +# Ismo Puustinen <ismo.puustinen@intel.com> |
| 23 | +# |
| 24 | +# Based on meta/lib/oeqa/selftest/* and meta-refkit/lib/oeqa/selftest/* |
| 25 | + |
| 26 | +"""Tests for Reference Kit image licensing. Contains a test case for |
| 27 | +computer vision production image without GPLv3 components.""" |
| 28 | + |
| 29 | +# Important: This test does by no means guarantee that there is license |
| 30 | +# compliance. Having the license compatibility rules in a map is not precise |
| 31 | +# enough, and many licenses are just omitted. This test is just meant to help |
| 32 | +# detect obvious image problems, and it might not do even that in all cases. |
| 33 | +# Especially the dual-licensing rules are not very accurate due to the way |
| 34 | +# Bitbake recipes express dual-licensing and multi-licensing. |
| 35 | + |
| 36 | +from oeqa.selftest.base import oeSelfTest |
| 37 | +from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars, runqemu |
| 38 | +import licensecheck |
| 39 | +import glob |
| 40 | + |
| 41 | +class LicensingTest(oeSelfTest): |
| 42 | + """Licensing test class.""" |
| 43 | + |
| 44 | + def _analyzePackages(self, packageNames, whitelistFile, prohibited): |
| 45 | + checker = licensecheck.LicenseCheck(whitelistFile, prohibited) |
| 46 | + |
| 47 | + # Process packages which are installed to the image. |
| 48 | + |
| 49 | + for name in packageNames: |
| 50 | + print("Processing package %s..." % name) |
| 51 | + |
| 52 | + # We can safely skip the kernel modules, also works around kernel |
| 53 | + # naming issues. |
| 54 | + if name.startswith("kernel"): |
| 55 | + continue |
| 56 | + |
| 57 | + # Pam has some packaging issues, leading to "package not |
| 58 | + # found" error messages. |
| 59 | + if name.startswith("libpam") or name.startswith("pam"): |
| 60 | + continue |
| 61 | + |
| 62 | + # Packagegroups do not have licensing in the sense that we |
| 63 | + # are interested in. |
| 64 | + if name.startswith("packagegroup"): |
| 65 | + continue |
| 66 | + |
| 67 | + # Lots of custom licenses, can't really be automatically |
| 68 | + # checked. |
| 69 | + if name.startswith("linux-firmware"): |
| 70 | + continue |
| 71 | + |
| 72 | + self.assertTrue(checker.testPackage(name), msg="License check for package %s failed" % name) |
| 73 | + |
| 74 | + def _get_latest_manifest(self, imagename, deploydir): |
| 75 | + # A hack for finding the correct package.manifest for the image we just |
| 76 | + # baked. Assume that has the latest timestamp. First, remove the |
| 77 | + # timestamp from image name: |
| 78 | + imagename_without_timestamp = ("-").join(imagename.split("-")[:-1]) |
| 79 | + # Find the corresponding files: |
| 80 | + path = os.path.join(deploydir, "licenses", imagename_without_timestamp) |
| 81 | + # Sort them (by time stamp): |
| 82 | + candidates = glob.glob(path + "*") |
| 83 | + candidates.sort() |
| 84 | + # Get the latest: |
| 85 | + manifestdir = candidates[-1] |
| 86 | + |
| 87 | + return os.path.join(manifestdir, "package.manifest") |
| 88 | + |
| 89 | + def test_check_computervision_licensing(self): |
| 90 | + |
| 91 | + """ Check that computer vision production build image can be |
| 92 | + made without using GPLv3 family licenses in any component. |
| 93 | + """ |
| 94 | + |
| 95 | + test_image = 'refkit-image-computervision' |
| 96 | + |
| 97 | + print("test_check_computervision_licensing") |
| 98 | + |
| 99 | + # Create the test image (rootfs is enough). |
| 100 | + print('Building test image (%s)...' % test_image) |
| 101 | + |
| 102 | + # Get variables from BB and initialize package list. |
| 103 | + bb_vars = get_bb_vars(["DEPLOY_DIR", "IMAGE_NAME", "META_REFKIT_BASE", "META_REFKIT_CORE_BASE"], test_image) |
| 104 | + deploydir = bb_vars["DEPLOY_DIR"] |
| 105 | + imagename = bb_vars["IMAGE_NAME"] |
| 106 | + basedir = bb_vars["META_REFKIT_BASE"] |
| 107 | + coredir = bb_vars["META_REFKIT_CORE_BASE"] |
| 108 | + |
| 109 | + self.append_config('IMAGE_MODE="production"') |
| 110 | + self.append_config('IMAGE_MODE_SUFFIX="-production"') |
| 111 | + self.append_config('REFKIT_DMVERITY_PRIVATE_KEY = "' + os.path.join(coredir, 'files/dm-verity/private.pem') + '"') |
| 112 | + self.append_config('REFKIT_DMVERITY_PASSWORD = "pass:refkit"') |
| 113 | + |
| 114 | + # Create the root filesystem. It's enough for getting a package |
| 115 | + # list. |
| 116 | + bitbake('-c rootfs %s' % test_image) |
| 117 | + |
| 118 | + # Find package list manifest. |
| 119 | + manifest = self._get_latest_manifest(imagename, deploydir) |
| 120 | + self.assertTrue(os.path.isfile(manifest), msg="No manifest file created for image. It should have been created in %s" % manifest) |
| 121 | + |
| 122 | + # Find whitelist. |
| 123 | + whitelist = os.path.join(basedir, "../meta-iotqa/scripts/contrib/licensetree-whitelist.txt") |
| 124 | + self.assertTrue(os.path.isfile(whitelist), msg="Whitelist file not found. It should have been in %s" % whitelist) |
| 125 | + |
| 126 | + lines = [] |
| 127 | + |
| 128 | + with open(manifest) as f: |
| 129 | + lines = f.readlines() |
| 130 | + |
| 131 | + packageNames = [line.split()[0] for line in lines] |
| 132 | + |
| 133 | + # GPLv3 and LGPLv3 are not allowed in this image. |
| 134 | + prohibited=["GPLv3", "LGPLv3"] |
| 135 | + |
| 136 | + self._analyzePackages(packageNames, whitelist, prohibited) |
0 commit comments