def saveAndShutdown(restart=False): halt() saveAll() logger.log(u"Killing cherrypy") cherrypy.engine.exit() if CREATEPID: logger.log(u"Removing pidfile " + str(PIDFILE)) os.remove(PIDFILE) ''' if restart: install_type = versionCheckScheduler.action.install_type popen_list = [sys.executable, MY_FULLNAME] if popen_list: popen_list += MY_ARGS if '--nolaunch' not in popen_list: popen_list += ['--nolaunch'] logger.log(u"Restarting Sick Beard with " + str(popen_list)) subprocess.Popen(popen_list, cwd=os.getcwd()) ''' os._exit(0)
def saveAll(): global showList # save config logger.log(u"Saving config file to disk") save_config()
def create_https_certificates(ssl_cert, ssl_key): """ Create self-signed HTTPS certificares and store in paths 'ssl_cert' and 'ssl_key' """ try: from OpenSSL import crypto from lib.certgen import createKeyPair, createCertRequest, createCertificate, TYPE_RSA, serial except: logger.log(u"pyopenssl module missing, please install for https access", logger.WARNING) return False # Create the CA Certificate cakey = createKeyPair(TYPE_RSA, 1024) careq = createCertRequest(cakey, CN='Certificate Authority') cacert = createCertificate(careq, (careq, cakey), serial, (0, 60*60*24*365*10)) # ten years cname = 'Metaweb' pkey = createKeyPair(TYPE_RSA, 1024) req = createCertRequest(pkey, CN=cname) cert = createCertificate(req, (cacert, cakey), serial, (0, 60*60*24*365*10)) # ten years # Save the key and certificate to disk try: open(ssl_key, 'w').write(crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey)) open(ssl_cert, 'w').write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)) except: logger.log(u"Error creating SSL key and certificate", logger.ERROR) return False return True
def saveGeneral(self, admin_user=None, general_user=None): if len(results) > 0: for x in results: logger.log(x, logger.ERROR) ui.notifications.error('Error(s) Saving Configuration', '<br />\n'.join(results)) else: ui.notifications.message('Configuration Saved', ek.ek(os.path.join, sickbeard.CONFIG_FILE) )
def initialize(consoleLogging=True): with INIT_LOCK: global LOG_DIR, WEB_PORT, WEB_LOG, WEB_ROOT, WEB_USERNAME, WEB_PASSWORD, WEB_HOST, WEB_IPV6, \ ENABLE_HTTPS, HTTPS_CERT, HTTPS_KEY, GIT_PATH, showUpdateScheduler, __INITIALIZED__ if __INITIALIZED__: return False socket.setdefaulttimeout(SOCKET_TIMEOUT) CheckSection('General') LOG_DIR = check_setting_str(CFG, 'General', 'log_dir', 'Logs') if not helpers.makeDir(LOG_DIR): logger.log(u"!!! No log folder, logging to screen only!", logger.ERROR) try: WEB_PORT = check_setting_int(CFG, 'General', 'web_port', 8081) except: WEB_PORT = 8081 if WEB_PORT < 21 or WEB_PORT > 65535: WEB_PORT = 8081 WEB_HOST = check_setting_str(CFG, 'General', 'web_host', '0.0.0.0') WEB_IPV6 = bool(check_setting_int(CFG, 'General', 'web_ipv6', 0)) WEB_ROOT = check_setting_str(CFG, 'General', 'web_root', '').rstrip("/") WEB_LOG = bool(check_setting_int(CFG, 'General', 'web_log', 0)) WEB_USERNAME = check_setting_str(CFG, 'General', 'web_username', '') WEB_PASSWORD = check_setting_str(CFG, 'General', 'web_password', '') ENABLE_HTTPS = bool(check_setting_int(CFG, 'General', 'enable_https', 0)) HTTPS_CERT = check_setting_str(CFG, 'General', 'https_cert', 'server.crt') HTTPS_KEY = check_setting_str(CFG, 'General', 'https_key', 'server.key') ROOT_DIRS = check_setting_str(CFG, 'General', 'root_dirs', '') if not re.match(r'\d+\|[^|]+(?:\|[^|]+)*', ROOT_DIRS): ROOT_DIRS = '' GIT_PATH = check_setting_str(CFG, 'General', 'git_path', '') logger.mw_log_instance.initLogging(consoleLogging=consoleLogging) mcconfig.mc_config.getConfig() WEB_USERNAME = mcconfig.mc_config.config['web_admin_user'] WEB_PASSWORD = mcconfig.mc_config.config['web_admin_pwd'] #mcconfig.mc_config.saveConfig() #versionCheckScheduler = scheduler.Scheduler(versionChecker.CheckVersion(), # cycleTime=datetime.timedelta(hours=12), # threadName="CHECKVERSION", # runImmediately=True) __INITIALIZED__ = True return True
def saveConfig(self): try: with open("/tmp/test", 'w') as f: for name, value in self.config.items(): line = name + '="' + value + '"\n' f.write(line) return True except BaseException as e: logger.log(u"Error saving config: %s" % e) return False
def getConfig(self): try: with open("/tmp/mc-config", 'r') as f: tmp = f.read().split('\n') pairs = [] for i in tmp: pairs.append(i.split('=')) #conf[pair[0]] = pair[1].strip('"') pairs.pop() self.config = {k: v.strip('"') for k, v in pairs} except BaseException as e: logger.log(u"Error getting config: %s" % e)
def restart(soft=True): if soft: halt() saveAll() #logger.log(u"Restarting cherrypy") #cherrypy.engine.restart() logger.log(u"Re-initializing all data") initialize() else: saveAndShutdown(restart=True)
def check_setting_int(config, cfg_name, item_name, def_val): try: my_val = int(config[cfg_name][item_name]) except: my_val = def_val try: config[cfg_name][item_name] = my_val except: config[cfg_name] = {} config[cfg_name][item_name] = my_val logger.log(item_name + " -> " + str(my_val), logger.DEBUG) return my_val
def fixStupidEncodings(x, silent=False): if type(x) == str: try: return x.decode('UTF-8') except UnicodeDecodeError: logger.log(u"Unable to decode value: " + repr(x), logger.ERROR) return None elif type(x) == unicode: return x else: logger.log(u"Unknown value passed in, ignoring it: " + str(type(x)) + " (" + repr(x) + ":" + repr(type(x)) + ")", logger.DEBUG if silent else logger.ERROR) return None return None
def rename_file(old_path, new_name): old_path_list = ek.ek(os.path.split, old_path) old_file_ext = os.path.splitext(old_path_list[1])[1] new_path = ek.ek(os.path.join, old_path_list[0], sanitizeFileName(new_name) + old_file_ext) logger.log(u"Renaming from " + old_path + " to " + new_path) try: ek.ek(os.rename, old_path, new_path) except (OSError, IOError), e: logger.log(u"Failed renaming " + old_path + " to " + new_path + ": " + ex(e), logger.ERROR) return False
def change_HTTPS_KEY(https_key): if https_key == '': metaweb.HTTPS_KEY = '' return True if os.path.normpath(metaweb.HTTPS_KEY) != os.path.normpath(https_key): if helpers.makeDir(os.path.dirname(os.path.abspath(https_key))): metaweb.HTTPS_KEY = os.path.normpath(https_key) logger.log(u"Changed https key path to " + https_key) else: return False return True
def change_HTTPS_CERT(https_cert): if https_cert == '': metaweb.HTTPS_CERT = '' return True if os.path.normpath(metaweb.HTTPS_CERT) != os.path.normpath(https_cert): if helpers.makeDir(os.path.dirname(os.path.abspath(https_cert))): metaweb.HTTPS_CERT = os.path.normpath(https_cert) logger.log(u"Changed https cert path to " + https_cert) else: return False return True
def check_setting_str(config, cfg_name, item_name, def_val, log=True): try: my_val = config[cfg_name][item_name] except: my_val = def_val try: config[cfg_name][item_name] = my_val except: config[cfg_name] = {} config[cfg_name][item_name] = my_val if log: logger.log(item_name + " -> " + my_val, logger.DEBUG) else: logger.log(item_name + " -> ******", logger.DEBUG) return my_val
def change_LOG_DIR(log_dir): if os.path.normpath(metaweb.LOG_DIR) != os.path.normpath(log_dir): if helpers.makeDir(log_dir): metaweb.LOG_DIR = os.path.normpath(log_dir) logger.mw_log_instance.initLogging() logger.log(u"Initialized new log file in " + log_dir) cherry_log = os.path.join(metaweb.LOG_DIR, "cherrypy.log") cherrypy.config.update({'log.access_file': cherry_log}) logger.log(u"Changed cherry log file to " + cherry_log) else: return False return True
def http_error_401_hander(status, message, traceback, version): """ Custom handler for 401 error """ if status != "401 Unauthorized": logger.log(u"CherryPy caught an error: %s %s" % (status, message), logger.ERROR) logger.log(traceback, logger.DEBUG) return r""" <html> <head> <title>%s</title> </head> <body> <br/> <font color="#0000FF">Error %s: You need to provide a valid username and password.</font> </body> </html> """ % ( "Access denied", status, )
def fixSetGroupID(childPath): if os.name == 'nt' or os.name == 'ce': return parentPath = ek.ek(os.path.dirname, childPath) parentStat = os.stat(parentPath) parentMode = stat.S_IMODE(parentStat[stat.ST_MODE]) if parentMode & stat.S_ISGID: parentGID = parentStat[stat.ST_GID] childGID = os.stat(childPath)[stat.ST_GID] if childGID == parentGID: return try: ek.ek(os.chown, childPath, -1, parentGID) logger.log(u"Respecting the set-group-ID bit on the parent directory for %s" % (childPath), logger.DEBUG) except OSError: logger.log(u"Failed to respect the set-group-ID bit on the parent directory for %s (setting group ID %i)" % (childPath, parentGID), logger.ERROR)
def halt (): global __INITIALIZED__, started with INIT_LOCK: if __INITIALIZED__: logger.log(u"Aborting all threads") # abort all the threads #versionCheckScheduler.abort = True #logger.log(u"Waiting for the VERSIONCHECKER thread to exit") #try: # versionCheckScheduler.thread.join(10) #except: # pass __INITIALIZED__ = False
def chmodAsParent(childPath): if os.name == 'nt' or os.name == 'ce': return parentPath = ek.ek(os.path.dirname, childPath) if not parentPath: logger.log(u"No parent path provided in "+childPath+", unable to get permissions from it", logger.DEBUG) return parentMode = stat.S_IMODE(os.stat(parentPath)[stat.ST_MODE]) if ek.ek(os.path.isfile, childPath): childMode = fileBitFilter(parentMode) else: childMode = parentMode try: ek.ek(os.chmod, childPath, childMode) logger.log(u"Setting permissions for %s to %o as parent directory has %o" % (childPath, childMode, parentMode), logger.DEBUG) except OSError: logger.log(u"Failed to set permission for %s to %o" % (childPath, childMode), logger.ERROR)
def initWebServer(options={}): options.setdefault("port", 8081) options.setdefault("host", "0.0.0.0") options.setdefault("log_dir", None) options.setdefault("username", "") options.setdefault("password", "") options.setdefault("web_root", "/") assert isinstance(options["port"], int) assert "data_root" in options def http_error_401_hander(status, message, traceback, version): """ Custom handler for 401 error """ if status != "401 Unauthorized": logger.log(u"CherryPy caught an error: %s %s" % (status, message), logger.ERROR) logger.log(traceback, logger.DEBUG) return r""" <html> <head> <title>%s</title> </head> <body> <br/> <font color="#0000FF">Error %s: You need to provide a valid username and password.</font> </body> </html> """ % ( "Access denied", status, ) def http_error_404_hander(status, message, traceback, version): """ Custom handler for 404 error, redirect back to main page """ return ( r""" <html> <head> <title>404</title> <script type="text/javascript" charset="utf-8"> <!-- location.href = "%s" //--> </script> </head> <body> <br/> </body> </html> """ % "/" ) # cherrypy setup enable_https = options["enable_https"] https_cert = options["https_cert"] https_key = options["https_key"] if enable_https: # If either the HTTPS certificate or key do not exist, make some self-signed ones. if not (https_cert and os.path.exists(https_cert)) or not (https_key and os.path.exists(https_key)): if not create_https_certificates(https_cert, https_key): logger.log(u"Unable to create cert/key files, disabling HTTPS") metaweb.ENABLE_HTTPS = False enable_https = False if not (os.path.exists(https_cert) and os.path.exists(https_key)): logger.log(u"Disabled HTTPS because of missing CERT and KEY files", logger.WARNING) metaweb.ENABLE_HTTPS = False enable_https = False options_dict = { "server.socket_port": options["port"], "server.socket_host": options["host"], "log.screen": False, "error_page.401": http_error_401_hander, #'error_page.404': http_error_404_hander, } if enable_https: options_dict["server.ssl_certificate"] = https_cert options_dict["server.ssl_private_key"] = https_key protocol = "https" else: protocol = "http" logger.log(u"Starting MetaWeb on " + protocol + "://" + str(options["host"]) + ":" + str(options["port"]) + "/") cherrypy.config.update(options_dict) # setup cherrypy logging if options["log_dir"] and os.path.isdir(options["log_dir"]): cherrypy.config.update({"log.access_file": os.path.join(options["log_dir"], "cherrypy.log")}) logger.log("Using %s for cherrypy log" % cherrypy.config["log.access_file"]) conf = { "/": {"tools.staticdir.root": options["data_root"], "tools.encode.on": True, "tools.encode.encoding": "utf-8"}, "/images": {"tools.staticdir.on": True, "tools.staticdir.dir": "images"}, "/js": {"tools.staticdir.on": True, "tools.staticdir.dir": "js"}, "/css": {"tools.staticdir.on": True, "tools.staticdir.dir": "css"}, } app = cherrypy.tree.mount(WebInterface(), options["web_root"], conf) # auth if options["username"] != "" and options["password"] != "": checkpassword = cherrypy.lib.auth_basic.checkpassword_dict({options["username"]: options["password"]}) app.merge( { "/": { "tools.auth_basic.on": True, "tools.auth_basic.realm": "MetaWeb", "tools.auth_basic.checkpassword": checkpassword, }, "/api": {"tools.auth_basic.on": False}, "/api/builder": { "tools.auth_basic.on": True, "tools.auth_basic.realm": "MetaWeb", "tools.auth_basic.checkpassword": checkpassword, }, } ) cherrypy.server.start() cherrypy.server.wait()
def invoke_command(to_call, *args, **kwargs): global invoked_command def delegate(): to_call(*args, **kwargs) invoked_command = delegate logger.log(u"Placed invoked command: " + repr(invoked_command) + " for " + repr(to_call) + " with " + repr(args) + " and " + repr(kwargs), logger.DEBUG)
# Make the child a session-leader by detaching from the terminal try: pid = os.fork() if pid != 0: sys.exit(0) except OSError, e: raise RuntimeError("2nd fork failed: %s [%d]" % (e.strerror, e.errno)) dev_null = file('/dev/null', 'r') os.dup2(dev_null.fileno(), sys.stdin.fileno()) if metaweb.CREATEPID: pid = str(os.getpid()) logger.log(u"Writing PID " + pid + " to " + str(metaweb.PIDFILE)) file(metaweb.PIDFILE, 'w').write("%s\n" % pid) def main(): # do some preliminary stuff metaweb.MY_FULLNAME = os.path.normpath(os.path.abspath(__file__)) metaweb.MY_NAME = os.path.basename(metaweb.MY_FULLNAME) metaweb.PROG_DIR = os.path.dirname(metaweb.MY_FULLNAME) metaweb.DATA_DIR = metaweb.PROG_DIR metaweb.MY_ARGS = sys.argv[1:] metaweb.CREATEPID = False metaweb.DAEMON = False # need console logging consoleLogging = (not hasattr(sys, "frozen")) or (metaweb.MY_NAME.lower().find('-console') > 0) # rename the main thread threading.currentThread().name = "MAIN"
def sig_handler(signum=None, frame=None): if type(signum) != type(None): logger.log(u"Signal %i caught, saving and exiting..." % int(signum)) saveAndShutdown()
def main(): # do some preliminary stuff metaweb.MY_FULLNAME = os.path.normpath(os.path.abspath(__file__)) metaweb.MY_NAME = os.path.basename(metaweb.MY_FULLNAME) metaweb.PROG_DIR = os.path.dirname(metaweb.MY_FULLNAME) metaweb.DATA_DIR = metaweb.PROG_DIR metaweb.MY_ARGS = sys.argv[1:] metaweb.CREATEPID = False metaweb.DAEMON = False # need console logging consoleLogging = (not hasattr(sys, "frozen")) or (metaweb.MY_NAME.lower().find('-console') > 0) # rename the main thread threading.currentThread().name = "MAIN" try: opts, args = getopt.getopt(sys.argv[1:], "qdp::", ['quiet', 'daemon', 'port=', 'pidfile=', 'config=', 'datadir=']) except getopt.GetoptError: print "Available options: --quiet, --daemon, --port, --pidfile, --config, --datadir" sys.exit() forcedPort = None for o, a in opts: # for now we'll just silence the logging if o in ('-q', '--quiet'): consoleLogging = False # use a different port if o in ('-p', '--port'): forcedPort = int(a) # Run as a daemon if o in ('-d', '--daemon'): consoleLogging = False metaweb.DAEMON = True # config file if o in ('--config',): metaweb.CONFIG_FILE = os.path.abspath(a) # datadir if o in ('--datadir',): metaweb.DATA_DIR = os.path.abspath(a) # write a pidfile if requested if o in ('--pidfile',): metaweb.PIDFILE = str(a) # if the pidfile already exists, metaweb may still be running, so exit if os.path.exists(metaweb.PIDFILE): sys.exit("PID file " + metaweb.PIDFILE + " already exists. Exiting.") # a pidfile is only useful in daemon mode # also, test to make sure we can write the file properly if metaweb.DAEMON: metaweb.CREATEPID = True try: file(metaweb.PIDFILE, 'w').write("pid\n") except IOError, e: raise SystemExit("Unable to write PID file: %s [%d]" % (e.strerror, e.errno)) else: logger.log(u"Not running in daemon mode. PID file creation disabled.")