def _pre_check_req_system(self): """ Pre-check the system if it meets requirements in the README.md. Required: Linux or Windows or Mac. """ log(MODULE_NAME, "DEBUG", "Checking platform...") if platform.system() == "Linux": self.computer_info["platform"] = "Linux" elif platform.system() in ["Windows", "Win32"]: self.computer_info["platform"] = "Windows" elif platform.system() == "Mac": self.computer_info["platform"] = "Mac" else: log( "computer_pre_check", "FATAL", "The computer's platform doesn't met the requirements.\n" "MCSH requires Windows, Mac or Linux to run.") crash({ "description": "Computer didn't pass pre-check.", "exception": "Platform mismatch " "(Current={}, Required=Linux,Windows,Mac)".format( platform.system()), "computer_info": None })
def _get_cpu_count(self): """ Get the CPU counts. """ log(MODULE_NAME, "DEBUG", "Getting CPU counts...") self.crash_report_system_info["CPU Count"] = psutil.cpu_count() self.computer_info["cpu"] = psutil.cpu_count()
def _get_python_version(self): """ Get the Python version. """ log(MODULE_NAME, "DEBUG", "Getting python version...") self.crash_report_system_info["Python version"] = sys.version.replace( '\n', '').replace('\r', '')
def debugging_enable(): if debugging_check(suppress_warning=True): log(MODULE_NAME, "ERROR", "Debugging already enabled!") else: with open("MCSH/config/debug.enabled", "w+") as f: f.write("enabled") f.close() log(MODULE_NAME, "INFO", "Successfully enabled debugging!")
def __init__(self): """ computer_info: A detailed computer information. crash_report_system_info: To be used in 'System Detailed' in crash reports. """ log(MODULE_NAME, "DEBUG", "Initializing computer_info...") self.crash_report_system_info = {} self.computer_info = {}
def _init_computer_info(self): """ Initialize computer info module. """ log(MODULE_NAME, "DEBUG", "Initializing computer info instance...") computer_info_instance = ComputerInfo() computer_info_instance.get_computer_info() self.computer_info = computer_info_instance.computer_info self.crash_info = computer_info_instance.crash_report_system_info
def startup_guide(): """ The entrance of the startup guide. Included parts: Language, Check pre.req., Generate config, Evaluate computer. """ log(MODULE_NAME, "DEBUG", "Initializing first-time setup guide...") # Pre-requirements check _choose_colours()
def _get_argv(self): """ Get the arguments (argv). """ log(MODULE_NAME, "DEBUG", "Getting arguments...") try: self.crash_report_system_info["Startup Arguments"] = sys.argv[1:] except: log(MODULE_NAME, "DEBUG", "No arguments were called.") self.crash_report_system_info["Startup Arguments"] = "None/Unknown"
def debugging_disable(): try: os.remove("MCSH/config/debug.enabled") log(MODULE_NAME, "INFO", "Successfully removed debugging file!") except: log( MODULE_NAME, "FATAL", "Failed to remove debugging file. (Is the file already removed?)\n" "Please go to MCSH/config and remove the debug.enabled file " "by yourself.")
def debugging_crash(crash_info): if not debugging_check(): return else: log(MODULE_NAME + "_crash", "DEBUG", "Crashing...") crash({ "description": "Manually triggered crash", "exception": "UNKNOWN (Manually triggered crash)", "computer_info": crash_info })
def debugging_parse(parser_arguments): log(MODULE_NAME, "DEBUG", "Parsing debug arguments...") from MCSH.consts import config_instance if parser_arguments.debugging_crash: debugging_crash(config_instance.crash_info) elif parser_arguments.debugging_enable: debugging_enable() elif parser_arguments.debugging_disable: debugging_disable() else: return False
def debugging_check(suppress_warning=False): if os.path.exists("MCSH/config/debug.enabled"): log(MODULE_NAME, "DEBUG", "Debugging file exists. Continuing...") return True else: if not suppress_warning: log( MODULE_NAME, "WARNING", "You're trying to execute a command that could cause bad things " "(including crashing, deleting all the files, etc.)\n" "This command is meant for debugging only, and it should NOT be executed " "by an end user.\n" "If you insist on executing this command, enable the debugging features by " "typing 'mcsh-cli.py --debugging-enable' before continuing.") return False
def _get_memory(self): """ Get the memory size. """ log(MODULE_NAME, "DEBUG", "Getting memory size...") mem = psutil.virtual_memory() self.crash_report_system_info["Memory"] = "{mem_used} bytes ({mem_used_mb} MB) / " \ "{mem_total} bytes ({mem_total_mb} MB)".format(**{ "mem_used": mem.used, "mem_used_mb": round(mem.used / 1024 / 1024), "mem_total": mem.total, "mem_total_mb": round(mem.total / 1024 / 1024) }) self.computer_info["memory_total"] = round(mem.total / 1024 / 1024 / 1024)
def __init__(self, flag_first_time_start=False): """ Initialize configurations. """ log(MODULE_NAME, "DEBUG", "Initializing config instance...") # Set all variables to none self.program_config_file = None self.program_config = None self.parser = None self.parser_args = None self.operations = None self.parse_sequence = None self.execute_command = None self.computer_info = None self.crash_info = None self.debug = False self.first_time_start = flag_first_time_start # Call functions for initializing. self._init_computer_info() self._init_debug() self._init_program_config() log( MODULE_NAME, "DEBUG", "-- Config Summary --\n" "program_config: {}\n" "computer_info: {}\n" "crash_info: {}\n" "first_time_startup: {}\n" "DEBUG: {}".format(self.program_config, self.computer_info, self.crash_info, self.first_time_start, self.debug)) log(MODULE_NAME, "DEBUG", "Starting parser...") self._init_parser() self._config_parser()
def parser_parse(self): """ Parse the args the user had entered. """ log(MODULE_NAME, "DEBUG", "Parsing arguments...") self.parser_args = self.parser.parse_args() # DEBUGGING ARGUMENTS debug_args_selected = debugging_parse(self.parser_args) # Normal Parsing for i in self.parse_sequence: if eval("self.parser_args." + i) is True: self.execute_command = i break elif eval("self.parser_args." + i) is not None and eval("self.parser_args." + i) is not False: self.execute_command = i + "({})".format( eval("self.parser_args." + i)) break if self.execute_command is None and debug_args_selected is False: log(MODULE_NAME, "ERROR", "No command specified.") self.parser.print_usage() log( MODULE_NAME, "DEBUG", "-- Parser Summary --\n" "parser_args: {}\n" "execute_command: {}\n" "parse_sequence: {}".format(self.parser_args, self.execute_command, self.parse_sequence))
def _init_program_config(self): """ Read program config json. """ log(MODULE_NAME, "DEBUG", "Reading program config...") if self.first_time_start: self._generate_config() try: self.program_config_file = open("MCSH/config/MCSH.json") self.program_config = json.loads(self.program_config_file.read()) self.program_config_file.close() except Exception: log( "initialize_config", "WARNING", "The file {file_name} ({file_path}) is missing or corrupted. " "Trying to generate a new one...".format( **{ "file_name": "MCSH.json", "file_path": "MCSH/config/MCSH.json" })) self._generate_config() self._init_program_config()
def get_computer_info(self): """ The main function of this module. Gets all the information. """ log(MODULE_NAME, "DEBUG", "get_computer_info called -- getting infos...") self._pre_check_req_python() self._pre_check_req_system() self._get_MCSH_version() self._get_operating_system() self._get_python_version() self._get_memory() self._get_cpu_count() self._get_argv() getCPUSpeed = self._get_cpu_speed() if not getCPUSpeed \ or self.crash_report_system_info["CPU Speed (Ghz)"] == "Unable to read" \ or self.computer_info["cpu_freq"] is None: log( "get_computer_info", "WARNING", "Can't determine CPU speed " "(Probably using platforms except Linux, Windows or Mac). " "'Performance Tester' will be unavailable.")
def _pre_check_req_python(self): """ Check if the Python version meets requirements. (3.7+) If not, raise an Exception. """ log(MODULE_NAME, "DEBUG", "Checking python version...") if sys.version_info.major >= 3 and sys.version_info.minor >= 7: log(MODULE_NAME, "DEBUG", "Version is right (>=3.7). Continuing...") else: log( "computer_pre_check", "FATAL", "Python version doesn't meet requirements. Requires 3.7 or higher." ) crash({ "description": "Computer didn't pass pre-check.", "exception": "Python version mismatch " "(Current={}.{}, Required=3.7+)".format( sys.version_info.major, sys.version_info.minor), "computer_info": None })
def init(): """ Initializes all modules. """ # Logger Module global config_instance initialize_logger() log(MODULE_NAME, "DEBUG", "Pre-initializing...") # If it's first time to run this program if not os.path.exists("./MCSH/logs") or not os.path.exists( "./MCSH/config/MCSH.json"): log(MODULE_NAME, "DEBUG", "Detected first time to use this program -- starting up guide...") config_instance = Config(flag_first_time_start=True) log(MODULE_NAME, "DEBUG", "Inserting CFG instance to INSTANCES...") insert_cfg_instance(config_instance) startup_guide() else: # Config Module log(MODULE_NAME, "DEBUG", "Initializing config module...") config_instance = Config() log(MODULE_NAME, "DEBUG", "Inserting CFG instance to INSTANCES...") insert_cfg_instance(config_instance) log(MODULE_NAME, "DEBUG", "Config initialised -- parsing arguments...") config_instance.parser_parse()
def _get_operating_system(self): """ Get the detailed operating system. """ log(MODULE_NAME, "DEBUG", "Getting operating system version...") self.crash_report_system_info["Operating System"] = platform.platform()
def _config_parser(self): """ Config commands for the parser. """ if self.first_time_start: return log(MODULE_NAME, "DEBUG", "Adding parser commands...") self.operations.add_argument("--version", action="version", version=MCSH_version, help="Display the version of MCSH.") self.operations.add_argument("--help", action="help", help="Show this help message.") self.operations.add_argument("--list", action="store_true", help="List all installed server(s).") self.operations.add_argument("--install", action="store_true", default=False, help="Install a server.") self.operations.add_argument("--remove", nargs="+", metavar="ServerName", help="Remove server(s).") self.operations.add_argument("--reinstall", nargs=1, metavar="ServerName", help="Reinstall a server.") self.operations.add_argument("--autoupdate", action="store_true", help="Update all server(s) in the list.") self.operations.add_argument( "--upgrade", action="store_true", help="Upgrade all server(s) to current version, including MCSH.\n" "WARNING: Under very early development, strongly unrecommended.") self.operations.add_argument( "--download", action="store_true", help="Download a specified server program.") self.operations.add_argument( "--repolist", action="store_true", help="List all server(s) in the repository.") self.operations.add_argument( "--reposearch", nargs=1, metavar="ServerName", help="Search for server(s) in the repository.") self.operations.add_argument( "--reposhow", nargs=1, metavar="ServerName", help="Show the specific server detail in the repository.") # Commands used JUST FOR DEBUGGING self.debug_operations.add_argument( "--debugging-crash", action="store_true", help=("Crash the program." if self.debug else argparse.SUPPRESS)) self.debug_operations.add_argument( "--debugging-enable", action="store_true", help=("Enable debugging features." if self.debug else argparse.SUPPRESS)) self.debug_operations.add_argument( "--debugging-disable", action="store_true", help=("Disable debugging features." if self.debug else argparse.SUPPRESS))
def _evaluate_computer(): log(MODULE_NAME, "DEBUG", "[Step 3/4] Evaluating computer...")
def _get_MCSH_version(self): """ Get the MCSH version. """ log(MODULE_NAME, "DEBUG", "Getting MCSH version...") self.crash_report_system_info["MCSH Version"] = MCSH_version
def _get_cpu_speed(self): """ WARNING: This function contains registry operation in Windows. Please, don't change anything unless you know what you're doing! Linux: Read speed from /proc/cpuinfo. Windows: Read speed from HKLM/HARDWARE/DESCRIPTION/System/CentralProcessor/0 """ log(MODULE_NAME, "DEBUG", "Getting CPU speed...") try: if platform.system() == "Linux": log(MODULE_NAME, "DEBUG", "Linux platform - getting from /proc/cpuinfo...") for line in fileinput.input("/proc/cpuinfo"): if 'MHz' in line: value = float(line.split(":")[1].strip()) speed = round(value / 1024, 1) self.crash_report_system_info[ "CPU Speed (Ghz)"] = speed self.computer_info["cpu_freq"] = speed return True elif platform.system() in ["Windows", "Win32"]: log( MODULE_NAME, "DEBUG", "Windows platform -- getting from HARDWARE\DESCRIPTION...") key = winreg.OpenKey( winreg.HKEY_LOCAL_MACHINE, r"HARDWARE\DESCRIPTION\System\CentralProcessor\0") speed, typeOfElement = winreg.QueryValueEx(key, "~MHz") speed = round(float(speed) / 1024, 1) self.crash_report_system_info["CPU Speed (Ghz)"] = speed self.computer_info["cpu_freq"] = speed return True elif platform.system() == "Darwin": log(MODULE_NAME, "DEBUG", "Mac platform -- getting from system_profiler...") command = 'system_profiler SPHardwareDataType | grep "Processor Speed" | cut -d ":" -f2' proc = subprocess.Popen([command], shell=True, stdout=subprocess.PIPE) output = proc.communicate()[0] output = output.decode() speed = output.lstrip().rstrip('\n') self.crash_report_system_info["CPU Speed (Ghz)"] = speed self.computer_info["cpu_freq"] = speed return True else: log(MODULE_NAME, "DEBUG", "Unknown platform -- cannot read...") self.crash_report_system_info[ "CPU Speed (Ghz)"] = "Unable to read" self.computer_info["cpu_freq"] = None return False except: log(MODULE_NAME, "DEBUG", "Unknown error occurred -- cannot read...") self.crash_report_system_info["CPU Speed (Ghz)"] = "Unable to read" self.computer_info["cpu_freq"] = None return False