diff --git a/install b/install index 7164867..1fdbf92 100755 --- a/install +++ b/install @@ -1,7 +1,11 @@ #!/usr/bin/python3.8 import json +import os import pathlib import platform +import subprocess as sp +import sys +from shutil import copyfile import psutil from src.backend.lib.display import TerminalDisplay @@ -39,28 +43,201 @@ class Configuration: 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 check_ps(service_list): - breakpoint() - ps = psutil - passed = [] - for p in ps.process_iter(attrs=["name", "exe", "cmdline"]): - for s in service_list: - if s == p.name: - passed.append(s) - return - if len(passed) == len(service_list): - return True + 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 failed + 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): + 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 + for r in _dirs: + copyfile(_file, r) + return True + + def make_nginx_config(self, answers): + breakpoint() + nginx_conf_str = """ + # pyshelf_nginx.conf + upstream django {server 127.0.0.1:8001;} + 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;} + } + """ % ( + answers + ) config = Configuration().open_file() +installer = None +messages = [] +# 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 = ["postgresql", "nginx", "httpd"] -req = RequiredServices.check_ps(service_list) +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) + copy_config = SystemInstaller().copy_config() + 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", + ] + if copy_config: + messages = messages + ["pyShelf site config copied to sites_enabled"] + +# Display end screen +TerminalDisplay().clear() +TerminalDisplay().h_rule() +for message in messages: + print(message) +TerminalDisplay().h_rule() diff --git a/pyshelf_nginx.conf b/pyshelf_nginx.conf index 9820f27..f106c86 100644 --- a/pyshelf_nginx.conf +++ b/pyshelf_nginx.conf @@ -1,6 +1,5 @@ -# mysite_nginx.conf +# pyshelf_nginx.conf -# the upstream component nginx needs to connect to upstream django { # server unix:///path/to/your/mysite/mysite.sock; # for a file socket server 127.0.0.1:8001; # for a web port socket (we'll use this first) @@ -8,33 +7,32 @@ upstream django { # configuration of the server server { - # the port your site will be served on listen 8000; - # the domain name it will serve for server_name 127.0.0.1; # substitute your machine's IP address or FQDN charset utf-8; - - # max upload size client_max_body_size 75M; # adjust to taste # Django media location /media { - alias /home/raelon/Projects/pyShelf/frontend/interface/media; # your Django project's media files - amend as required + # your Django project's media files - amend as required + alias /home/raelon/Projects/pyShelf/frontend/interface/media; } location /static { - alias /home/raelon/Projects/pyShelf/frontend/interface/static; # your Django project's static files - amend as required + # your Django project's static files - amend as required + alias /home/raelon/Projects/pyShelf/frontend/interface/static; } location /books { + # Absolute location of your ebook files internal; alias /home/raelon/Projects/pyShelf/books; - # Absolute location of your ebook files } # Finally, send all non-media requests to the Django server. location / { + # the uwsgi_params file you installed uwsgi_pass django; - include /home/raelon/Projects/pyShelf/uwsgi_params; # the uwsgi_params file you installed + include /home/raelon/Projects/pyShelf/uwsgi_params; } } diff --git a/src/backend/lib/display.py b/src/backend/lib/display.py index 966beea..627f02f 100644 --- a/src/backend/lib/display.py +++ b/src/backend/lib/display.py @@ -1,5 +1,7 @@ from __future__ import unicode_literals + import os + from prompt_toolkit import prompt as prm @@ -16,39 +18,60 @@ class TerminalDisplay: def installer(self): questions = [ { - "message": "Input the absolute path to your ebooks\nEnter for default \"~/Books\" > ", + "message": 'Input the absolute path to your ebooks\nEnter for default "~/Books" > ', "options": "", "name": "BOOKPATH", "answer": None, - "default": self.home+"/Books" + "default": self.home + "/Books", }, { - "message": "Input your PostgreSQL server ip\nEnter for default \"localhost\" > ", + "message": 'Input your PostgreSQL server ip\nEnter for default "localhost" > ', "options": "localhost", "name": "DB_HOST", "answer": None, - "default": "localhost" + "default": "localhost", }, { - "message": "Input your PostgreSQL server port\nEnter for default \"5432\" > ", + "message": 'Input your PostgreSQL server port\nEnter for default "5432" > ', "options": "5432", "name": "DB_PORT", "answer": None, - "default": "5432" + "default": "5432", }, { - "message": "Input your PostgreSQL user name\nEnter for default \"pyshelf\" > ", + "message": 'Input your PostgreSQL user name\nEnter for default "pyshelf" > ', "options": "pyshelf", "name": "USER", "answer": None, - "default": "pyshelf" + "default": "pyshelf", }, { - "message": "Input your PostgreSQL password\nEnter for default \"pyshelf\" > ", + "message": 'Input your PostgreSQL password\nEnter for default "pyshelf" > ', "options": "pyshelf", "name": "PASSWORD", "answer": None, - "default": "pyshelf" + "default": "pyshelf", + }, + { + "message": 'Web ui hostname/ip\nEnter for default "localhost" > ', + "options": "localhost", + "name": "hostname", + "answer": None, + "default": "localhost", + }, + { + "message": 'Web ui port\nEnter for default "8000" > ', + "options": "8000", + "name": "webport", + "answer": None, + "default": "8000", + }, + { + "message": 'wsgi port\nEnter for default "8001"\n"You should probably leave this alone, unless you know what you\'re doing" > ', + "options": "8001", + "name": "wsgiport", + "answer": None, + "default": "8001", }, ] return self.prompt(questions)