# -*- 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 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 = True 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 None: return distname, version, idNum 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 elif 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'] if selected_data['version']: version = selected_data['version'] if selected_data['bit']: idNum = selected_data['bit'] return distname, version, idNum