#!/usr/bin/python3 import json import os import pathlib import platform import pprint import subprocess as sp import sys from shutil import copyfile import psutil from src.backend.lib.display import TerminalDisplay log_file = "installer.log" messages = [] class Configuration: def __init__(self): self._cp = pathlib.Path("config.json") self._data = self.open_file() self.system = platform.system() def open_file(self): """ Try to open and then backup the configuration file. Fail and return false if initial configuration is not found. # TODO: More specific error handling """ try: with open(str(self._cp), "r") as read_file: data = json.load(read_file) with open("config.backup.json", "w") as backup_file: json.dump(data, backup_file) return data except Exception as e: print(e) return False def write_file(self, data): """ Write the provided data to the new configuration file """ with open(str(self._cp), "w") as write_file: json.dump(data, write_file) return True class RequiredServices: def check_ps(self, service_list): """ Check service_list against running processes by calling self.process_list, remove found services from the list and return """ # Get the matched processes _matches = self.process_list().intersection(set(service_list)) for r in _matches: service_list.remove(r) return service_list @staticmethod def process_list(): """ Iterate running processes returning the name of each make it a set and return """ _processes = [] for p in psutil.process_iter(): _processes.append(p.name()) return set(_processes) @staticmethod def web_server_found(service_list): # Determine whether or not both possible webservers are missing _c = 0 for r in service_list: if r == "nginx" or r == "httpd": _c = _c + 1 if _c > 1: return False # Return false if neither are found else: return True # Return true if one is found @staticmethod def db_server_found(service_list): _c = 0 for r in service_list: if r == "postgres": _c = _c + 1 if _c > 0: return False else: return True class SystemInstaller: def __init__(self): self.bin = self.get() self.site_dirs = ["/etc/nginx/sites-available", "/etc/nginx/sites-enabled"] self.nginx_conf = "pyshelf_nginx.conf" def get(self): platfrm = platform.platform().split("-") if platfrm[0].lower() == "linux": installers = [ {"bin": "apt", "options": [], "search": "search", "install": "install"}, {"bin": "pacman", "options": [], "search": "-Ss", "install": "-S"}, {"bin": "yum", "options": [], "search": "search", "install": "install"}, {"bin": "docker", "options": []}, ] _paths = os.environ["PATH"].split(":") for p in _paths: for _installer in installers: _fp = p + "/" + str(_installer["bin"]) if os.path.isfile(_fp): global messages messages = messages + [ "Found system installer binary " + str(_installer["bin"]) ] return _installer def copy_config(self, _file=None, _dirs=None): if _file is None: _file = self.nginx_conf if _dirs is None: _dirs = self.site_dirs outfile = "/%s" % _file.__str__() if os.path.isdir(_dirs[0]): os.system("sudo cp %s %s" % (_file, _dirs[0] + outfile)) else: os.system("sudo mkdir %s" % _dirs[0]) os.system("sudo cp %s %s" % (_file, _dirs[0] + outfile)) try: if os.path.isdir(_dirs[1]): ln_string = str(_dirs[0] + outfile + " " + _dirs[1] + outfile) os.system("sudo ln -s %s" % ln_string) except Exception as e: pass """ for r in _dirs: if os.path.isdir(r): os.system("sudo cp %s %s" % (_file, r+"/"+_file.__str__())) else: os.system("sudo mkdir %s" % r) os.system("sudo cp %s %s" % (_file, r+"/"+_file.__str__())) """ return True def make_nginx_config(self, answers): root = os.path.abspath(".") _fp = "pyshelf_nginx.conf" for r in answers: if r["name"] == "hostname": hostname = r["answer"] elif r["name"] == "webport": port = r["answer"] elif r["name"] == "wsgiport": wsgiport = r["answer"] nginx_conf_str = """ # pyshelf_nginx.conf upstream django {server 127.0.0.1:%s;} server { listen %s; server_name %s; charset utf-8; client_max_body_size 75M; location /media {alias %s/frontend/interface/media;} location /static {alias %s/frontend/interface/static;} location /books {internal; alias %s;} location / {uwsgi_pass django; include %s/uwsgi_params;} } """ % ( wsgiport, port, hostname, root, root, root, root, ) with open(_fp, "w") as write_file: write_file.write(nginx_conf_str) global messages messages = messages + ["Generated new pyshelf_nginx.conf", nginx_conf_str] def log(self): global log_file global messages with open(log_file, "w") as write_file: write_file.write(TerminalDisplay().banner_render()) for message in messages: write_file.write(message + "\n") messages = messages + ["Log file written to " + log_file.__str__()] config = Configuration().open_file() sysinstall = SystemInstaller() installer = sysinstall.bin # Get user configuration options install_answers = TerminalDisplay().installer() for key in install_answers: config[key["name"]] = key["answer"] # Write configuration Configuration().write_file(config) # Start checking for our list of required services service_list = ["postgres", "nginx", "httpd", "test"] req = RequiredServices().check_ps(service_list) # Does user have either nginx || apache? if RequiredServices().web_server_found(req) is False: web_prompt = [ { "message": "You must have either apache or nginx\nwould you like us to try and install nginx now? > ", "options": "nginx", "name": "NGINX", "answer": None, "default": "no", } ] install_prompt = TerminalDisplay().prompt(web_prompt) if install_prompt[0]["answer"] == "yes": if installer is None: installer = SystemInstaller().bin if installer["bin"] == "pacman": package = "nginx-mainline" else: package = "nginx" options = "" for o in installer["options"]: options = options + " " + o cmd = ( "sudo " + installer["bin"] + " " + installer["install"] + " " + options + package ) install_status = os.system(cmd) srvc_start = os.system("sudo systemctl start nginx") messages = messages + [ "Nginx installed and started", "To enable autostart you must run", " sudo systemctl enable nginx", "\n", ] # Does user have postgreSQL? if RequiredServices().db_server_found(req) is False: db_prompt = [ { "message": "You must have PostgreSQL\nwould you like us to try and install it now? > ", "options": "postgres", "name": "postgresql", "answer": None, "default": "no", } ] install_prompt = TerminalDisplay().prompt(db_prompt) if install_prompt[0]["answer"] == "yes": if installer is None: installer = SystemInstaller().bin options = "" for o in installer["options"]: options = options + " " + o package = "postgresql" cmd = ( "sudo " + installer["bin"] + " " + installer["install"] + " " + options + package ) install_status = os.system(cmd) srvc_start = os.system("sudo systemctl start postgresql") messages = messages + [ "PostgreSQL installed and started", "To enable autostart you must run", " sudo systemctl enable nginx", "\n", ] # Post install configurations sysinstall.make_nginx_config(install_answers) copy_config = sysinstall.copy_config() if copy_config: messages = messages + ["pyShelf site config copied to sites_enabled"] # Display end screen sysinstall.log() TerminalDisplay().clear() TerminalDisplay().banner() for message in messages: print(message) print() TerminalDisplay().h_rule()