poky/meta/lib/oe/lsb.py
Joshua Lock 81afedc905 lib/oe/lsb: attempt to ensure consistent distro id regardless of source
The LSB Distributor ID and os-release NAME differ for most of the
distributions tested by the Yocto Project (CentOS, Debian, Fedora,
openSUSE and Ubuntu) however for all but openSUSE the os-release ID
matches the LSB Distributor ID when both are lowered before
comparison.

Therefore, in order to improve the consistency of identification of
a distribution, switch to using the os-release ID and converting
the ID value to lowercase.

Table showing comparison of LSB Distributor ID to os-release fields NAME
and ID for current Yocto Project supported host distributions:

Distribution | Version | Distributor ID   | NAME             | ID       |
-------------------------------------------------------------------------
CentOS       | 7       | CentOS           | CentOS Linux     | centos   |
Debian       | 8       | Debian           | Debian GNU/Linux | debian   |
Fedora       | 23      | Fedora           | Fedora           | fedora   |
Fedora       | 24      | Fedora           | Fedora           | fedora   |
openSUSE     | 13.2    | openSUSE project | openSUSE         | opensuse |
openSUSE     | 42.1    | SUSE LINUX       | openSUSE Leap    | opensuse |
Ubuntu       | 14.04   | Ubuntu           | Ubuntu           | ubuntu   |
Ubuntu       | 16.04   | Ubuntu           | Ubuntu           | ubuntu   |

[YOCTO #10591]

(From OE-Core rev: 8689e5618d45c2119134ea64754430c06a93ea09)

Signed-off-by: Joshua Lock <joshua.g.lock@intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-15 15:19:54 +00:00

114 lines
3.4 KiB
Python

def release_dict_osr():
""" Populate a dict with pertinent values from /etc/os-release """
if not os.path.exists('/etc/os-release'):
return None
data = {}
with open('/etc/os-release') as f:
for line in f:
try:
key, val = line.rstrip().split('=', 1)
except ValueError:
continue
if key == 'ID':
data['DISTRIB_ID'] = val.strip('"')
if key == 'VERSION_ID':
data['DISTRIB_RELEASE'] = val.strip('"')
if len(data.keys()) != 2:
return None
return data
def release_dict_lsb():
""" Return the output of lsb_release -ir as a dictionary """
from subprocess import PIPE
try:
output, err = bb.process.run(['lsb_release', '-ir'], stderr=PIPE)
except bb.process.CmdError as exc:
return None
lsb_map = { 'Distributor ID': 'DISTRIB_ID',
'Release': 'DISTRIB_RELEASE'}
lsb_keys = lsb_map.keys()
data = {}
for line in output.splitlines():
if line.startswith("-e"):
line = line[3:]
try:
key, value = line.split(":\t", 1)
except ValueError:
continue
if key in lsb_keys:
data[lsb_map[key]] = value
if len(data.keys()) != 2:
return None
return data
def release_dict_file():
""" Try to gather release information manually when other methods fail """
data = None
try:
if os.path.exists('/etc/lsb-release'):
data = {}
with open('/etc/lsb-release') as f:
for line in f:
key, value = line.split("=", 1)
data[key] = value.strip()
elif os.path.exists('/etc/redhat-release'):
data = {}
with open('/etc/redhat-release') as f:
distro = f.readline().strip()
import re
match = re.match(r'(.*) release (.*) \((.*)\)', distro)
if match:
data['DISTRIB_ID'] = match.group(1)
data['DISTRIB_RELEASE'] = match.group(2)
elif os.path.exists('/etc/SuSE-release'):
data = {}
data['DISTRIB_ID'] = 'SUSE LINUX'
with open('/etc/SuSE-release') as f:
for line in f:
if line.startswith('VERSION = '):
data['DISTRIB_RELEASE'] = line[10:].rstrip()
break
except IOError:
return None
return data
def distro_identifier(adjust_hook=None):
"""Return a distro identifier string based upon lsb_release -ri,
with optional adjustment via a hook"""
import re
# Try /etc/os-release first, then the output of `lsb_release -ir` and
# finally fall back on parsing various release files in order to determine
# host distro name and version.
distro_data = release_dict_osr()
if not distro_data:
distro_data = release_dict_lsb()
if not distro_data:
distro_data = release_dict_file()
distro_id = distro_data['DISTRIB_ID']
release = distro_data['DISTRIB_RELEASE']
if adjust_hook:
distro_id, release = adjust_hook(distro_id, release)
if not distro_id:
return "Unknown"
# Filter out any non-alphanumerics
distro_id = re.sub(r'\W', '', distro_id)
if release:
id_str = '{0}-{1}'.format(distro_id.lower(), release)
else:
id_str = distro_id
return id_str.replace(' ','-').replace('/','-')