xref: /OK3568_Linux_fs/yocto/poky/meta/lib/oeqa/utils/package_manager.py (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#
2*4882a593Smuzhiyun# SPDX-License-Identifier: MIT
3*4882a593Smuzhiyun#
4*4882a593Smuzhiyun
5*4882a593Smuzhiyunimport os
6*4882a593Smuzhiyunimport json
7*4882a593Smuzhiyunimport shutil
8*4882a593Smuzhiyun
9*4882a593Smuzhiyunfrom oeqa.core.utils.test import getCaseFile, getCaseMethod
10*4882a593Smuzhiyun
11*4882a593Smuzhiyundef get_package_manager(d, root_path):
12*4882a593Smuzhiyun    """
13*4882a593Smuzhiyun    Returns an OE package manager that can install packages in root_path.
14*4882a593Smuzhiyun    """
15*4882a593Smuzhiyun    from oe.package_manager.rpm import RpmPM
16*4882a593Smuzhiyun    from oe.package_manager.ipk import OpkgPM
17*4882a593Smuzhiyun    from oe.package_manager.deb import DpkgPM
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun    pkg_class = d.getVar("IMAGE_PKGTYPE")
20*4882a593Smuzhiyun    if pkg_class == "rpm":
21*4882a593Smuzhiyun        pm = RpmPM(d,
22*4882a593Smuzhiyun                   root_path,
23*4882a593Smuzhiyun                   d.getVar('TARGET_VENDOR'),
24*4882a593Smuzhiyun                   filterbydependencies=False)
25*4882a593Smuzhiyun        pm.create_configs()
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun    elif pkg_class == "ipk":
28*4882a593Smuzhiyun        pm = OpkgPM(d,
29*4882a593Smuzhiyun                    root_path,
30*4882a593Smuzhiyun                    d.getVar("IPKGCONF_TARGET"),
31*4882a593Smuzhiyun                    d.getVar("ALL_MULTILIB_PACKAGE_ARCHS"),
32*4882a593Smuzhiyun                    filterbydependencies=False)
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun    elif pkg_class == "deb":
35*4882a593Smuzhiyun        pm = DpkgPM(d,
36*4882a593Smuzhiyun                    root_path,
37*4882a593Smuzhiyun                    d.getVar('PACKAGE_ARCHS'),
38*4882a593Smuzhiyun                    d.getVar('DPKG_ARCH'),
39*4882a593Smuzhiyun                    filterbydependencies=False)
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun    pm.write_index()
42*4882a593Smuzhiyun    pm.update()
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun    return pm
45*4882a593Smuzhiyun
46*4882a593Smuzhiyundef find_packages_to_extract(test_suite):
47*4882a593Smuzhiyun    """
48*4882a593Smuzhiyun    Returns packages to extract required by runtime tests.
49*4882a593Smuzhiyun    """
50*4882a593Smuzhiyun    from oeqa.core.utils.test import getSuiteCasesFiles
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun    needed_packages = {}
53*4882a593Smuzhiyun    files = getSuiteCasesFiles(test_suite)
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun    for f in set(files):
56*4882a593Smuzhiyun        json_file = _get_json_file(f)
57*4882a593Smuzhiyun        if json_file:
58*4882a593Smuzhiyun            needed_packages.update(_get_needed_packages(json_file))
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun    return needed_packages
61*4882a593Smuzhiyun
62*4882a593Smuzhiyundef _get_json_file(module_path):
63*4882a593Smuzhiyun    """
64*4882a593Smuzhiyun    Returns the path of the JSON file for a module, empty if doesn't exitst.
65*4882a593Smuzhiyun    """
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun    json_file = '%s.json' % module_path.rsplit('.', 1)[0]
68*4882a593Smuzhiyun    if os.path.isfile(module_path) and os.path.isfile(json_file):
69*4882a593Smuzhiyun        return json_file
70*4882a593Smuzhiyun    else:
71*4882a593Smuzhiyun        return ''
72*4882a593Smuzhiyun
73*4882a593Smuzhiyundef _get_needed_packages(json_file, test=None):
74*4882a593Smuzhiyun    """
75*4882a593Smuzhiyun    Returns a dict with needed packages based on a JSON file.
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun    If a test is specified it will return the dict just for that test.
78*4882a593Smuzhiyun    """
79*4882a593Smuzhiyun    needed_packages = {}
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun    with open(json_file) as f:
82*4882a593Smuzhiyun        test_packages = json.load(f)
83*4882a593Smuzhiyun    for key,value in test_packages.items():
84*4882a593Smuzhiyun        needed_packages[key] = value
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun    if test:
87*4882a593Smuzhiyun        if test in needed_packages:
88*4882a593Smuzhiyun            needed_packages = needed_packages[test]
89*4882a593Smuzhiyun        else:
90*4882a593Smuzhiyun            needed_packages = {}
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun    return needed_packages
93*4882a593Smuzhiyun
94*4882a593Smuzhiyundef extract_packages(d, needed_packages):
95*4882a593Smuzhiyun    """
96*4882a593Smuzhiyun    Extract packages that will be needed during runtime.
97*4882a593Smuzhiyun    """
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun    import bb
100*4882a593Smuzhiyun    import oe.path
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun    extracted_path = d.getVar('TEST_EXTRACTED_DIR')
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun    for key,value in needed_packages.items():
105*4882a593Smuzhiyun        packages = ()
106*4882a593Smuzhiyun        if isinstance(value, dict):
107*4882a593Smuzhiyun            packages = (value, )
108*4882a593Smuzhiyun        elif isinstance(value, list):
109*4882a593Smuzhiyun            packages = value
110*4882a593Smuzhiyun        else:
111*4882a593Smuzhiyun            bb.fatal('Failed to process needed packages for %s; '
112*4882a593Smuzhiyun                     'Value must be a dict or list' % key)
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun        for package in packages:
115*4882a593Smuzhiyun            pkg = package['pkg']
116*4882a593Smuzhiyun            rm = package.get('rm', False)
117*4882a593Smuzhiyun            extract = package.get('extract', True)
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun            if extract:
120*4882a593Smuzhiyun                #logger.debug('Extracting %s' % pkg)
121*4882a593Smuzhiyun                dst_dir = os.path.join(extracted_path, pkg)
122*4882a593Smuzhiyun                # Same package used for more than one test,
123*4882a593Smuzhiyun                # don't need to extract again.
124*4882a593Smuzhiyun                if os.path.exists(dst_dir):
125*4882a593Smuzhiyun                    continue
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun                # Extract package and copy it to TEST_EXTRACTED_DIR
128*4882a593Smuzhiyun                pkg_dir = _extract_in_tmpdir(d, pkg)
129*4882a593Smuzhiyun                oe.path.copytree(pkg_dir, dst_dir)
130*4882a593Smuzhiyun                shutil.rmtree(pkg_dir)
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun            else:
133*4882a593Smuzhiyun                #logger.debug('Copying %s' % pkg)
134*4882a593Smuzhiyun                _copy_package(d, pkg)
135*4882a593Smuzhiyun
136*4882a593Smuzhiyundef _extract_in_tmpdir(d, pkg):
137*4882a593Smuzhiyun    """"
138*4882a593Smuzhiyun    Returns path to a temp directory where the package was
139*4882a593Smuzhiyun    extracted without dependencies.
140*4882a593Smuzhiyun    """
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun    from oeqa.utils.package_manager import get_package_manager
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun    pkg_path = os.path.join(d.getVar('TEST_INSTALL_TMP_DIR'), pkg)
145*4882a593Smuzhiyun    pm = get_package_manager(d, pkg_path)
146*4882a593Smuzhiyun    extract_dir = pm.extract(pkg)
147*4882a593Smuzhiyun    shutil.rmtree(pkg_path)
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun    return extract_dir
150*4882a593Smuzhiyun
151*4882a593Smuzhiyundef _copy_package(d, pkg):
152*4882a593Smuzhiyun    """
153*4882a593Smuzhiyun    Copy the RPM, DEB or IPK package to dst_dir
154*4882a593Smuzhiyun    """
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun    from oeqa.utils.package_manager import get_package_manager
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun    pkg_path = os.path.join(d.getVar('TEST_INSTALL_TMP_DIR'), pkg)
159*4882a593Smuzhiyun    dst_dir = d.getVar('TEST_PACKAGED_DIR')
160*4882a593Smuzhiyun    pm = get_package_manager(d, pkg_path)
161*4882a593Smuzhiyun    pkg_info = pm.package_info(pkg)
162*4882a593Smuzhiyun    file_path = pkg_info[pkg]['filepath']
163*4882a593Smuzhiyun    shutil.copy2(file_path, dst_dir)
164*4882a593Smuzhiyun    shutil.rmtree(pkg_path)
165*4882a593Smuzhiyun
166*4882a593Smuzhiyundef install_package(test_case):
167*4882a593Smuzhiyun    """
168*4882a593Smuzhiyun    Installs package in DUT if required.
169*4882a593Smuzhiyun    """
170*4882a593Smuzhiyun    needed_packages = test_needs_package(test_case)
171*4882a593Smuzhiyun    if needed_packages:
172*4882a593Smuzhiyun        _install_uninstall_packages(needed_packages, test_case, True)
173*4882a593Smuzhiyun
174*4882a593Smuzhiyundef uninstall_package(test_case):
175*4882a593Smuzhiyun    """
176*4882a593Smuzhiyun    Uninstalls package in DUT if required.
177*4882a593Smuzhiyun    """
178*4882a593Smuzhiyun    needed_packages = test_needs_package(test_case)
179*4882a593Smuzhiyun    if needed_packages:
180*4882a593Smuzhiyun        _install_uninstall_packages(needed_packages, test_case, False)
181*4882a593Smuzhiyun
182*4882a593Smuzhiyundef test_needs_package(test_case):
183*4882a593Smuzhiyun    """
184*4882a593Smuzhiyun    Checks if a test case requires to install/uninstall packages.
185*4882a593Smuzhiyun    """
186*4882a593Smuzhiyun    test_file = getCaseFile(test_case)
187*4882a593Smuzhiyun    json_file = _get_json_file(test_file)
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun    if json_file:
190*4882a593Smuzhiyun        test_method = getCaseMethod(test_case)
191*4882a593Smuzhiyun        needed_packages = _get_needed_packages(json_file, test_method)
192*4882a593Smuzhiyun        if needed_packages:
193*4882a593Smuzhiyun            return needed_packages
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun    return None
196*4882a593Smuzhiyun
197*4882a593Smuzhiyundef _install_uninstall_packages(needed_packages, test_case, install=True):
198*4882a593Smuzhiyun    """
199*4882a593Smuzhiyun    Install/Uninstall packages in the DUT without using a package manager
200*4882a593Smuzhiyun    """
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun    if isinstance(needed_packages, dict):
203*4882a593Smuzhiyun        packages = [needed_packages]
204*4882a593Smuzhiyun    elif isinstance(needed_packages, list):
205*4882a593Smuzhiyun        packages = needed_packages
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun    for package in packages:
208*4882a593Smuzhiyun        pkg = package['pkg']
209*4882a593Smuzhiyun        rm = package.get('rm', False)
210*4882a593Smuzhiyun        extract = package.get('extract', True)
211*4882a593Smuzhiyun        src_dir = os.path.join(test_case.tc.extract_dir, pkg)
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun        # Install package
214*4882a593Smuzhiyun        if install and extract:
215*4882a593Smuzhiyun            test_case.tc.target.copyDirTo(src_dir, '/')
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun        # Uninstall package
218*4882a593Smuzhiyun        elif not install and rm:
219*4882a593Smuzhiyun            test_case.tc.target.deleteDirStructure(src_dir, '/')
220