xref: /openbmc/openbmc/poky/meta/lib/oe/lsb.py (revision f3f93bb8)
1#
2# SPDX-License-Identifier: GPL-2.0-only
3#
4
5def get_os_release():
6    """Get all key-value pairs from /etc/os-release as a dict"""
7    from collections import OrderedDict
8
9    data = OrderedDict()
10    if os.path.exists('/etc/os-release'):
11        with open('/etc/os-release') as f:
12            for line in f:
13                try:
14                    key, val = line.rstrip().split('=', 1)
15                except ValueError:
16                    continue
17                data[key.strip()] = val.strip('"')
18    return data
19
20def release_dict_osr():
21    """ Populate a dict with pertinent values from /etc/os-release """
22    data = {}
23    os_release = get_os_release()
24    if 'ID' in os_release:
25        data['DISTRIB_ID'] = os_release['ID']
26    if 'VERSION_ID' in os_release:
27        data['DISTRIB_RELEASE'] = os_release['VERSION_ID']
28
29    return data
30
31def release_dict_lsb():
32    """ Return the output of lsb_release -ir as a dictionary """
33    from subprocess import PIPE
34
35    try:
36        output, err = bb.process.run(['lsb_release', '-ir'], stderr=PIPE)
37    except bb.process.CmdError as exc:
38        return {}
39
40    lsb_map = { 'Distributor ID': 'DISTRIB_ID',
41                'Release': 'DISTRIB_RELEASE'}
42    lsb_keys = lsb_map.keys()
43
44    data = {}
45    for line in output.splitlines():
46        if line.startswith("-e"):
47            line = line[3:]
48        try:
49            key, value = line.split(":\t", 1)
50        except ValueError:
51            continue
52        if key in lsb_keys:
53            data[lsb_map[key]] = value
54
55    if len(data.keys()) != 2:
56        return None
57
58    return data
59
60def release_dict_file():
61    """ Try to gather release information manually when other methods fail """
62    data = {}
63    try:
64        if os.path.exists('/etc/lsb-release'):
65            data = {}
66            with open('/etc/lsb-release') as f:
67                for line in f:
68                    key, value = line.split("=", 1)
69                    data[key] = value.strip()
70        elif os.path.exists('/etc/redhat-release'):
71            data = {}
72            with open('/etc/redhat-release') as f:
73                distro = f.readline().strip()
74            import re
75            match = re.match(r'(.*) release (.*) \((.*)\)', distro)
76            if match:
77                data['DISTRIB_ID'] = match.group(1)
78                data['DISTRIB_RELEASE'] = match.group(2)
79        elif os.path.exists('/etc/SuSE-release'):
80            data = {}
81            data['DISTRIB_ID'] = 'SUSE LINUX'
82            with open('/etc/SuSE-release') as f:
83                for line in f:
84                    if line.startswith('VERSION = '):
85                        data['DISTRIB_RELEASE'] = line[10:].rstrip()
86                        break
87
88    except IOError:
89        return {}
90    return data
91
92def distro_identifier(adjust_hook=None):
93    """Return a distro identifier string based upon lsb_release -ri,
94       with optional adjustment via a hook"""
95
96    import re
97
98    # Try /etc/os-release first, then the output of `lsb_release -ir` and
99    # finally fall back on parsing various release files in order to determine
100    # host distro name and version.
101    distro_data = release_dict_osr()
102    if not distro_data:
103        distro_data = release_dict_lsb()
104    if not distro_data:
105        distro_data = release_dict_file()
106
107    distro_id = distro_data.get('DISTRIB_ID', '')
108    release = distro_data.get('DISTRIB_RELEASE', '')
109
110    if adjust_hook:
111        distro_id, release = adjust_hook(distro_id, release)
112    if not distro_id:
113        return "unknown"
114    # Filter out any non-alphanumerics and convert to lowercase
115    distro_id = re.sub(r'\W', '', distro_id).lower()
116
117    if release:
118        id_str = '{0}-{1}'.format(distro_id, release)
119    else:
120        id_str = distro_id
121    return id_str.replace(' ','-').replace('/','-')
122