Files
openGauss-OM/script/os_platform/linux_distro.py
2024-05-07 07:48:59 +00:00

306 lines
12 KiB
Python

# -*- coding:utf-8 -*-
#############################################################################
# Portions Copyright (c) 2020 Huawei Technologies Co.,Ltd.
# Portions Copyright (c) 2007 Agendaless Consulting and Contributors.
#
# openGauss is licensed under Mulan PSL v2.
# You can use this software according to the terms
# and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#
# http://license.coscl.org.cn/MulanPSL2
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
# ----------------------------------------------------------------------------
# Description : os version info.
#############################################################################
import os
import re
import select
import sys
from os_platform.common import _supported_dists,SUPPORT_WHOLE_PLATFORM_LIST,\
SUPPORT_USER_DEFINED_OS_LIST
ISCONFIGURETRUE = "# isConfigure = TRUE"
ISCONFIGUREFALSE = "# isConfigure = FALSE"
SESSIONTIMEOUT = 300
class LinuxDistro(object):
"""
replace expired func linux_distribution
"""
@staticmethod
def _parse_release_file(num1_line):
"""
Default to empty 'version' and 'id' strings. Both defaults are used
when 'num1_line' is empty. 'id' defaults to empty when an id can not
be deduced.
"""
version = ''
id_num = ''
# Parse the first line
_hw_publish_version = re.compile(r'(.+)'
' release '
'([\d.]+)'
'[^(]*(?:\((.+)\))?')
implication = _hw_publish_version.match(num1_line)
if implication is not None:
# LSB format: "distro release x.x (codename)"
return tuple(implication.groups())
# Pre-LSB format: "distro x.x (codename)"
_publish_version = re.compile(r'([^0-9]+)'
'(?: release )?'
'([\d.]+)'
'[^(]*(?:\((.+)\))?')
implication = _publish_version.match(num1_line)
if implication is not None:
return tuple(implication.groups())
line = num1_line.strip().split()
if line:
version = line[0]
if len(line) > 1:
id_num = line[1]
return '', version, id_num
@staticmethod
def parse_linux_osid(filename):
"""
Tries to determine the name of the Linux OS distribution name.
The function first looks for a distribution release file in
/etc and then reverts to _dist_try_harder() in case no
suitable files are found.
Returns a tuple (distname,version,id) which default to the
args given as parameters.
"""
valid_info = []
lines_to_choose = []
with open(filename, 'r') as file:
for line in file:
line = line.strip()
# Ignore comment lines starting with # and empty lines
if line and not line.startswith('#'):
# Separate the release name, version with spaces
distro, version = line.split()
valid_info.append({
'os': distro,
'version': version
})
lines_to_choose.append(line.strip())
if len(lines_to_choose) == 1 or len(lines_to_choose) == 0:
return valid_info
for i, line in enumerate(lines_to_choose, 1):
print(f"{i}. {line}")
while True:
try:
choice = int(input("Please enter the serial number of the option:"))
if (1 <= choice and choice <= len(lines_to_choose)):
chosen_line = lines_to_choose[choice - 1]
valid_info = valid_info[choice - 1]
with open(filename, 'r+') as file:
lines = file.readlines()
file.seek(0)
file.truncate()
for line in lines:
if line.strip().startswith('#') or line.strip() == '':
file.write(line)
continue
elif chosen_line in line:
file.write(line)
else:
file.write('#' + line)
LinuxDistro.write_is_configure_true(filename, ISCONFIGURETRUE)
break
else:
print("Invalid input: Please re-enter")
except ValueError:
print("Invalid input: Please re-enter")
return valid_info
@staticmethod
def write_is_configure_true(file_path, target_line):
# open the file and read all the lines
with open(file_path, 'r') as file:
lines = file.readlines()
# Check if any row contains target content
has_target_line = any(target_line in line for line in lines)
# If there is no target row, insert the target row before row 21
if not has_target_line:
lines.insert(20, target_line + '\n')
# Write the modified content back to the file
with open(file_path, 'w') as file:
file.writelines(lines)
@staticmethod
def parse_linux_distributions(filename):
"""
Tries to determine the name of the Linux OS distribution name.
The function first looks for a distribution release file in
/etc and then reverts to _dist_try_harder() in case no
Returns a tuple (distname,version,id) which default to the
args given as parameters.
"""
is_configure = True
valid_info = LinuxDistro.parse_linux_osid(filename)
if len(valid_info) == 1:
LinuxDistro.write_is_configure_true(filename, ISCONFIGURETRUE)
with open(filename, 'r') as file:
for line in file:
if ISCONFIGURETRUE in line or ISCONFIGUREFALSE in line:
is_configure = False
# Remind the user if new content is added to the file
if len(valid_info) == 0 and is_configure:
print(f"File '{filename}' has not been configured yet,"
"do you still need to configure it?"
"Enter 'yes' or 'no' to configure "
"the file: ", end='', flush=True)
rlist, _, _ = select.select([sys.stdin], [], [], SESSIONTIMEOUT)
if rlist:
user_input = input().lower()
else:
user_input = "no"
while True:
if user_input in ('y', 'yes'):
LinuxDistro.write_is_configure_true(filename, ISCONFIGURETRUE)
os_name = input("Please enter an operating system name:")
version = input("Please enter the version number:")
with open(filename, 'a') as file:
file.write(f"\n{os_name} {version}\n")
valid_info = LinuxDistro.parse_linux_osid(filename)
break
elif user_input in ('n', 'no'):
LinuxDistro.write_is_configure_true(filename, ISCONFIGUREFALSE)
break
else:
LinuxDistro.write_is_configure_true(filename, ISCONFIGUREFALSE)
break
return valid_info
@staticmethod
def select_linux_distribution(valid_info):
# If there is no legal information, return None
if not valid_info:
return None
# If there is only one line of legal information, return directly
if len(valid_info) == 1:
return valid_info[0]
@staticmethod
def linux_distribution(distname='', version='', idNum='',
supported_dists=_supported_dists,
full_distribution_name=0):
"""
Tries to determine the name of the Linux OS distribution name.
The function first looks for a distribution release file in
/etc and then reverts to _dist_try_harder() in case no
suitable files are found.
supported_dists may be given to define the set of Linux
distributions to look for. It defaults to a list of currently
supported Linux distributions identified by their release file
name.
If full_distribution_name is true (default), the full
distribution read from the OS is returned. Otherwise the short
name taken from supported_dists is used.
Returns a tuple (distname,version,id) which default to the
args given as parameters.
"""
is_flag_osid = False
is_flag_oscorrect = False
try:
etc_dir = os.listdir('/etc')
except os.error:
# Probably not a Unix system
return distname, version, idNum
etc_dir.sort()
gFile = None
_release_filename = re.compile(r'(\w+)[-_](release|version)')
for file in etc_dir:
if os.path.islink('/etc/' + file):
continue
m = _release_filename.match(file)
if m is not None:
_distname, dummy = m.groups()
if _distname in supported_dists:
gFile = file
distname = _distname
break
if distname == "UnionTech":
distname = "uos"
# Read the first line
if gFile is not None:
with open('/etc/' + gFile, 'r') as f:
firstline = f.readline()
_distname, _version, _id = LinuxDistro._parse_release_file(firstline)
if _distname and full_distribution_name:
distname = _distname
for dist in SUPPORT_WHOLE_PLATFORM_LIST:
if dist.lower == _distname.lower:
is_flag_oscorrect = True
if _version:
version = _version
if _id:
idNum = _id
if is_flag_oscorrect == True:
return distname, version, idNum
if is_flag_oscorrect == False:
# Read system information from configuration file
# Call the function and pass in the filename
osid_path = os.path.realpath(
os.path.join(os.path.realpath(__file__), "../../osid.conf"))
if os.path.exists(osid_path):
file_data = LinuxDistro.parse_linux_distributions(osid_path)
# Output the parsed content
selected_data = LinuxDistro.select_linux_distribution(file_data)
if selected_data:
is_flag_osid = True
else:
print(f"The file '{osid_path}' does not exist.")
if is_flag_osid:
if selected_data['os']:
distname = selected_data['os']
SUPPORT_USER_DEFINED_OS_LIST.append(distname)
SUPPORT_USER_DEFINED_OS_LIST.append(distname.lower())
if selected_data['version']:
version = selected_data['version']
return distname, version, idNum