def check_github(auto_update=False, notify=False): plexpy.COMMITS_BEHIND = 0 if plexpy.CONFIG.GIT_TOKEN: headers = {'Authorization': 'token {}'.format(plexpy.CONFIG.GIT_TOKEN)} else: headers = {} # Get the latest version available from github logger.info('Retrieving latest version information from GitHub') url = 'https://api.github.com/repos/%s/%s/commits/%s' % ( plexpy.CONFIG.GIT_USER, plexpy.CONFIG.GIT_REPO, plexpy.CONFIG.GIT_BRANCH) version = request.request_json(url, headers=headers, timeout=20, validator=lambda x: type(x) == dict) if version is None: logger.warn( 'Could not get the latest version from GitHub. Are you running a local development version?' ) return plexpy.CURRENT_VERSION plexpy.LATEST_VERSION = version['sha'] logger.debug("Latest version is %s", plexpy.LATEST_VERSION) # See how many commits behind we are if not plexpy.CURRENT_VERSION: logger.info( 'You are running an unknown version of Tautulli. Run the updater to identify your version' ) return plexpy.LATEST_VERSION if plexpy.LATEST_VERSION == plexpy.CURRENT_VERSION: logger.info('Tautulli is up to date') return plexpy.LATEST_VERSION logger.info( 'Comparing currently installed version with latest GitHub version') url = 'https://api.github.com/repos/%s/%s/compare/%s...%s' % ( plexpy.CONFIG.GIT_USER, plexpy.CONFIG.GIT_REPO, plexpy.LATEST_VERSION, plexpy.CURRENT_VERSION) commits = request.request_json(url, headers=headers, timeout=20, whitelist_status_code=404, validator=lambda x: type(x) == dict) if commits is None: logger.warn('Could not get commits behind from GitHub.') return plexpy.LATEST_VERSION try: plexpy.COMMITS_BEHIND = int(commits['behind_by']) logger.debug("In total, %d commits behind", plexpy.COMMITS_BEHIND) except KeyError: logger.info( 'Cannot compare versions. Are you running a local development version?' ) plexpy.COMMITS_BEHIND = 0 if plexpy.COMMITS_BEHIND > 0: logger.info('New version is available. You are %s commits behind' % plexpy.COMMITS_BEHIND) url = 'https://api.github.com/repos/%s/%s/releases' % ( plexpy.CONFIG.GIT_USER, plexpy.CONFIG.GIT_REPO) releases = request.request_json(url, timeout=20, whitelist_status_code=404, validator=lambda x: type(x) == list) if releases is None: logger.warn('Could not get releases from GitHub.') return plexpy.LATEST_VERSION if plexpy.CONFIG.GIT_BRANCH == 'master': release = next((r for r in releases if not r['prerelease']), releases[0]) elif plexpy.CONFIG.GIT_BRANCH == 'beta': release = next( (r for r in releases if not r['tag_name'].endswith('-nightly')), releases[0]) elif plexpy.CONFIG.GIT_BRANCH == 'nightly': release = next((r for r in releases), releases[0]) else: release = releases[0] plexpy.LATEST_RELEASE = release['tag_name'] if notify: plexpy.NOTIFY_QUEUE.put({ 'notify_action': 'on_plexpyupdate', 'plexpy_download_info': release, 'plexpy_update_commit': plexpy.LATEST_VERSION, 'plexpy_update_behind': plexpy.COMMITS_BEHIND }) if auto_update: logger.info('Running automatic update.') plexpy.shutdown(restart=True, update=True) elif plexpy.COMMITS_BEHIND == 0: logger.info('Tautulli is up to date') return plexpy.LATEST_VERSION
def check_github(scheduler=False, notify=False, use_cache=False): plexpy.COMMITS_BEHIND = 0 if plexpy.CONFIG.GIT_TOKEN: headers = {'Authorization': 'token {}'.format(plexpy.CONFIG.GIT_TOKEN)} else: headers = {} version = github_cache('version', use_cache=use_cache) if not version: # Get the latest version available from github logger.info('Retrieving latest version information from GitHub') url = 'https://api.github.com/repos/%s/%s/commits/%s' % ( plexpy.CONFIG.GIT_USER, plexpy.CONFIG.GIT_REPO, plexpy.CONFIG.GIT_BRANCH) version = request.request_json(url, headers=headers, timeout=20, validator=lambda x: type(x) == dict) github_cache('version', github_data=version) if version is None: logger.warn( 'Could not get the latest version from GitHub. Are you running a local development version?' ) return plexpy.CURRENT_VERSION plexpy.LATEST_VERSION = version['sha'] logger.debug("Latest version is %s", plexpy.LATEST_VERSION) # See how many commits behind we are if not plexpy.CURRENT_VERSION: logger.info( 'You are running an unknown version of Tautulli. Run the updater to identify your version' ) return plexpy.LATEST_VERSION if plexpy.LATEST_VERSION == plexpy.CURRENT_VERSION: logger.info('Tautulli is up to date') return plexpy.LATEST_VERSION commits = github_cache('commits', use_cache=use_cache) if not commits: logger.info( 'Comparing currently installed version with latest GitHub version') # Need to compare CURRENT << LATEST to get a list of commits url = 'https://api.github.com/repos/%s/%s/compare/%s...%s' % ( plexpy.CONFIG.GIT_USER, plexpy.CONFIG.GIT_REPO, plexpy.CURRENT_VERSION, plexpy.LATEST_VERSION) commits = request.request_json(url, headers=headers, timeout=20, whitelist_status_code=404, validator=lambda x: type(x) == dict) github_cache('commits', github_data=commits) if commits is None: logger.warn('Could not get commits behind from GitHub.') return plexpy.LATEST_VERSION try: ahead_by = int(commits['ahead_by']) logger.debug("In total, %d commits behind", ahead_by) # Do not count [skip ci] commits for Docker or Snap on the nightly branch if (plexpy.DOCKER or plexpy.SNAP) and plexpy.CONFIG.GIT_BRANCH == 'nightly': for commit in reversed(commits['commits']): if '[skip ci]' not in commit['commit']['message']: plexpy.LATEST_VERSION = commit['sha'] break ahead_by -= 1 install = 'Docker container' if plexpy.DOCKER else 'Snap package' logger.debug("%s %d commits behind", install, ahead_by) plexpy.COMMITS_BEHIND = ahead_by except KeyError: logger.info( 'Cannot compare versions. Are you running a local development version?' ) plexpy.COMMITS_BEHIND = 0 if plexpy.COMMITS_BEHIND > 0: logger.info('New version is available. You are %s commits behind' % plexpy.COMMITS_BEHIND) releases = github_cache('releases', use_cache=use_cache) if not releases: url = 'https://api.github.com/repos/%s/%s/releases' % ( plexpy.CONFIG.GIT_USER, plexpy.CONFIG.GIT_REPO) releases = request.request_json( url, timeout=20, whitelist_status_code=404, validator=lambda x: type(x) == list) github_cache('releases', github_data=releases) if releases is None: logger.warn('Could not get releases from GitHub.') return plexpy.LATEST_VERSION if plexpy.CONFIG.GIT_BRANCH == 'master': release = next((r for r in releases if not r['prerelease']), releases[0]) elif plexpy.CONFIG.GIT_BRANCH == 'beta': release = next( (r for r in releases if not r['tag_name'].endswith('-nightly')), releases[0]) elif plexpy.CONFIG.GIT_BRANCH == 'nightly': release = next((r for r in releases), releases[0]) else: release = releases[0] plexpy.LATEST_RELEASE = release['tag_name'] if notify: plexpy.NOTIFY_QUEUE.put({ 'notify_action': 'on_plexpyupdate', 'plexpy_download_info': release, 'plexpy_update_commit': plexpy.LATEST_VERSION, 'plexpy_update_behind': plexpy.COMMITS_BEHIND }) if plexpy.PYTHON2: logger.warn( 'Tautulli is running using Python 2. Unable to run automatic update.' ) elif scheduler and plexpy.CONFIG.PLEXPY_AUTO_UPDATE and \ not plexpy.DOCKER and not plexpy.SNAP and not plexpy.FROZEN: logger.info('Running automatic update.') plexpy.shutdown(restart=True, update=True) elif plexpy.COMMITS_BEHIND == 0: logger.info('Tautulli is up to date') return plexpy.LATEST_VERSION
def main(): """ Tautulli application entry point. Parses arguments, setups encoding and initializes the application. """ # Fixed paths to Tautulli if hasattr(sys, 'frozen'): plexpy.FULL_PATH = os.path.abspath(sys.executable) else: plexpy.FULL_PATH = os.path.abspath(__file__) plexpy.PROG_DIR = os.path.dirname(plexpy.FULL_PATH) plexpy.ARGS = sys.argv[1:] # From sickbeard plexpy.SYS_PLATFORM = sys.platform plexpy.SYS_ENCODING = None try: locale.setlocale(locale.LC_ALL, "") plexpy.SYS_LANGUAGE, plexpy.SYS_ENCODING = locale.getdefaultlocale() except (locale.Error, IOError): pass # for OSes that are poorly configured I'll just force UTF-8 if not plexpy.SYS_ENCODING or plexpy.SYS_ENCODING in ('ANSI_X3.4-1968', 'US-ASCII', 'ASCII'): plexpy.SYS_ENCODING = 'UTF-8' # Set up and gather command line arguments parser = argparse.ArgumentParser( description= 'A Python based monitoring and tracking tool for Plex Media Server.') parser.add_argument('-v', '--verbose', action='store_true', help='Increase console logging verbosity') parser.add_argument('-q', '--quiet', action='store_true', help='Turn off console logging') parser.add_argument('-d', '--daemon', action='store_true', help='Run as a daemon') parser.add_argument('-p', '--port', type=int, help='Force Tautulli to run on a specified port') parser.add_argument('--dev', action='store_true', help='Start Tautulli in the development environment') parser.add_argument( '--datadir', help='Specify a directory where to store your data files') parser.add_argument('--config', help='Specify a config file to use') parser.add_argument('--nolaunch', action='store_true', help='Prevent browser from launching on startup') parser.add_argument( '--pidfile', help='Create a pid file (only relevant when running as a daemon)') parser.add_argument( '--nofork', action='store_true', help='Start Tautulli as a service, do not fork when restarting') args = parser.parse_args() if args.verbose: plexpy.VERBOSE = True if args.quiet: plexpy.QUIET = True # Do an intial setup of the logger. logger.initLogger(console=not plexpy.QUIET, log_dir=False, verbose=plexpy.VERBOSE) try: plexpy.SYS_TIMEZONE = tzlocal.get_localzone() except (pytz.UnknownTimeZoneError, LookupError, ValueError) as e: logger.error("Could not determine system timezone: %s" % e) plexpy.SYS_TIMEZONE = pytz.UTC plexpy.SYS_UTC_OFFSET = datetime.datetime.now( plexpy.SYS_TIMEZONE).strftime('%z') if os.getenv('TAUTULLI_DOCKER', False) == 'True': plexpy.DOCKER = True if args.dev: plexpy.DEV = True logger.debug(u"Tautulli is running in the dev environment.") if args.daemon: if sys.platform == 'win32': sys.stderr.write( "Daemonizing not supported under Windows, starting normally\n") else: plexpy.DAEMON = True plexpy.QUIET = True if args.nofork: plexpy.NOFORK = True logger.info( "Tautulli is running as a service, it will not fork when restarted." ) if args.pidfile: plexpy.PIDFILE = str(args.pidfile) # If the pidfile already exists, plexpy may still be running, so # exit if os.path.exists(plexpy.PIDFILE): try: with open(plexpy.PIDFILE, 'r') as fp: pid = int(fp.read()) os.kill(pid, 0) except IOError as e: raise SystemExit("Unable to read PID file: %s", e) except OSError: logger.warn("PID file '%s' already exists, but PID %d is " \ "not running. Ignoring PID file." % (plexpy.PIDFILE, pid)) else: # The pidfile exists and points to a live PID. plexpy may # still be running, so exit. raise SystemExit("PID file '%s' already exists. Exiting." % plexpy.PIDFILE) # The pidfile is only useful in daemon mode, make sure we can write the # file properly if plexpy.DAEMON: plexpy.CREATEPID = True try: with open(plexpy.PIDFILE, 'w') as fp: fp.write("pid\n") except IOError as e: raise SystemExit("Unable to write PID file: %s", e) else: logger.warn("Not running in daemon mode. PID file creation " \ "disabled.") # Determine which data directory and config file to use if args.datadir: plexpy.DATA_DIR = args.datadir else: plexpy.DATA_DIR = plexpy.PROG_DIR if args.config: config_file = args.config else: config_file = os.path.join(plexpy.DATA_DIR, config.FILENAME) # Try to create the DATA_DIR if it doesn't exist if not os.path.exists(plexpy.DATA_DIR): try: os.makedirs(plexpy.DATA_DIR) except OSError: raise SystemExit('Could not create data directory: ' + plexpy.DATA_DIR + '. Exiting....') # Make sure the DATA_DIR is writeable if not os.access(plexpy.DATA_DIR, os.W_OK): raise SystemExit('Cannot write to the data directory: ' + plexpy.DATA_DIR + '. Exiting...') # Put the database in the DATA_DIR plexpy.DB_FILE = os.path.join(plexpy.DATA_DIR, database.FILENAME) # Move 'plexpy.db' to 'tautulli.db' if os.path.isfile(os.path.join(plexpy.DATA_DIR, 'plexpy.db')) and \ not os.path.isfile(os.path.join(plexpy.DATA_DIR, plexpy.DB_FILE)): try: os.rename(os.path.join(plexpy.DATA_DIR, 'plexpy.db'), plexpy.DB_FILE) except OSError as e: raise SystemExit("Unable to rename plexpy.db to tautulli.db: %s", e) if plexpy.DAEMON: plexpy.daemonize() # Read config and start logging plexpy.initialize(config_file) # Start the background threads plexpy.start() # Force the http port if neccessary if args.port: plexpy.HTTP_PORT = args.port logger.info('Using forced web server port: %i', plexpy.HTTP_PORT) else: plexpy.HTTP_PORT = int(plexpy.CONFIG.HTTP_PORT) # Check if pyOpenSSL is installed. It is required for certificate generation # and for CherryPy. if plexpy.CONFIG.ENABLE_HTTPS: try: import OpenSSL except ImportError: logger.warn("The pyOpenSSL module is missing. Install this " \ "module to enable HTTPS. HTTPS will be disabled.") plexpy.CONFIG.ENABLE_HTTPS = False # Try to start the server. Will exit here is address is already in use. webstart.start() # Windows system tray icon if os.name == 'nt' and plexpy.CONFIG.WIN_SYS_TRAY: plexpy.win_system_tray() logger.info("Tautulli is ready!") # Open webbrowser if plexpy.CONFIG.LAUNCH_BROWSER and not args.nolaunch and not plexpy.DEV: plexpy.launch_browser(plexpy.CONFIG.HTTP_HOST, plexpy.HTTP_PORT, plexpy.HTTP_ROOT) # Wait endlessy for a signal to happen while True: if not plexpy.SIGNAL: try: time.sleep(1) except KeyboardInterrupt: plexpy.SIGNAL = 'shutdown' else: logger.info('Received signal: %s', plexpy.SIGNAL) if plexpy.SIGNAL == 'shutdown': plexpy.shutdown() elif plexpy.SIGNAL == 'restart': plexpy.shutdown(restart=True) elif plexpy.SIGNAL == 'checkout': plexpy.shutdown(restart=True, checkout=True) else: plexpy.shutdown(restart=True, update=True) plexpy.SIGNAL = None
def main(): """ PlexPy application entry point. Parses arguments, setups encoding and initializes the application. """ # Fixed paths to PlexPy if hasattr(sys, 'frozen'): plexpy.FULL_PATH = os.path.abspath(sys.executable) else: plexpy.FULL_PATH = os.path.abspath(__file__) plexpy.PROG_DIR = os.path.dirname(plexpy.FULL_PATH) plexpy.ARGS = sys.argv[1:] # From sickbeard plexpy.SYS_PLATFORM = sys.platform plexpy.SYS_ENCODING = None try: locale.setlocale(locale.LC_ALL, "") plexpy.SYS_ENCODING = locale.getpreferredencoding() except (locale.Error, IOError): pass # for OSes that are poorly configured I'll just force UTF-8 if not plexpy.SYS_ENCODING or plexpy.SYS_ENCODING in ('ANSI_X3.4-1968', 'US-ASCII', 'ASCII'): plexpy.SYS_ENCODING = 'UTF-8' # Set up and gather command line arguments parser = argparse.ArgumentParser( description= 'A Python based monitoring and tracking tool for Plex Media Server.') parser.add_argument('-v', '--verbose', action='store_true', help='Increase console logging verbosity') parser.add_argument('-q', '--quiet', action='store_true', help='Turn off console logging') parser.add_argument('-d', '--daemon', action='store_true', help='Run as a daemon') parser.add_argument('-p', '--port', type=int, help='Force PlexPy to run on a specified port') parser.add_argument('--dev', action='store_true', help='Start PlexPy in the development environment') parser.add_argument( '--datadir', help='Specify a directory where to store your data files') parser.add_argument('--config', help='Specify a config file to use') parser.add_argument('--nolaunch', action='store_true', help='Prevent browser from launching on startup') parser.add_argument( '--pidfile', help='Create a pid file (only relevant when running as a daemon)') parser.add_argument( '--nofork', action='store_true', help='Start PlexPy as a service, do not fork when restarting') args = parser.parse_args() if args.verbose: plexpy.VERBOSE = True if args.quiet: plexpy.QUIET = True # Do an intial setup of the logger. logger.initLogger(console=not plexpy.QUIET, log_dir=False, verbose=plexpy.VERBOSE) if args.dev: plexpy.DEV = True logger.debug(u"PlexPy is running in the dev environment.") if args.daemon: if sys.platform == 'win32': sys.stderr.write( "Daemonizing not supported under Windows, starting normally\n") else: plexpy.DAEMON = True plexpy.QUIET = True if args.nofork: plexpy.NOFORK = True logger.info( "PlexPy is running as a service, it will not fork when restarted.") if args.pidfile: plexpy.PIDFILE = str(args.pidfile) # If the pidfile already exists, plexpy may still be running, so # exit if os.path.exists(plexpy.PIDFILE): try: with open(plexpy.PIDFILE, 'r') as fp: pid = int(fp.read()) os.kill(pid, 0) except IOError as e: raise SystemExit("Unable to read PID file: %s", e) except OSError: logger.warn("PID file '%s' already exists, but PID %d is " \ "not running. Ignoring PID file." % (plexpy.PIDFILE, pid)) else: # The pidfile exists and points to a live PID. plexpy may # still be running, so exit. raise SystemExit("PID file '%s' already exists. Exiting." % plexpy.PIDFILE) # The pidfile is only useful in daemon mode, make sure we can write the # file properly if plexpy.DAEMON: plexpy.CREATEPID = True try: with open(plexpy.PIDFILE, 'w') as fp: fp.write("pid\n") except IOError as e: raise SystemExit("Unable to write PID file: %s", e) else: logger.warn("Not running in daemon mode. PID file creation " \ "disabled.") # Determine which data directory and config file to use if args.datadir: plexpy.DATA_DIR = args.datadir else: plexpy.DATA_DIR = plexpy.PROG_DIR if args.config: config_file = args.config else: config_file = os.path.join(plexpy.DATA_DIR, config.FILENAME) # Try to create the DATA_DIR if it doesn't exist if not os.path.exists(plexpy.DATA_DIR): try: os.makedirs(plexpy.DATA_DIR) except OSError: raise SystemExit('Could not create data directory: ' + plexpy.DATA_DIR + '. Exiting....') # Make sure the DATA_DIR is writeable if not os.access(plexpy.DATA_DIR, os.W_OK): raise SystemExit('Cannot write to the data directory: ' + plexpy.DATA_DIR + '. Exiting...') # Put the database in the DATA_DIR plexpy.DB_FILE = os.path.join(plexpy.DATA_DIR, database.FILENAME) if plexpy.DAEMON: plexpy.daemonize() # Read config and start logging plexpy.initialize(config_file) # Start the background threads plexpy.start() # Open connection for websocket if plexpy.CONFIG.MONITORING_USE_WEBSOCKET: try: web_socket.start_thread() except: logger.warn(u"Websocket :: Unable to open connection.") # Fallback to polling plexpy.POLLING_FAILOVER = True plexpy.initialize_scheduler() # Force the http port if neccessary if args.port: http_port = args.port logger.info('Using forced web server port: %i', http_port) else: http_port = int(plexpy.CONFIG.HTTP_PORT) # Check if pyOpenSSL is installed. It is required for certificate generation # and for CherryPy. if plexpy.CONFIG.ENABLE_HTTPS: try: import OpenSSL except ImportError: logger.warn("The pyOpenSSL module is missing. Install this " \ "module to enable HTTPS. HTTPS will be disabled.") plexpy.CONFIG.ENABLE_HTTPS = False # Try to start the server. Will exit here is address is already in use. web_config = { 'http_port': http_port, 'http_host': plexpy.CONFIG.HTTP_HOST, 'http_root': plexpy.CONFIG.HTTP_ROOT, 'http_environment': plexpy.CONFIG.HTTP_ENVIRONMENT, 'http_proxy': plexpy.CONFIG.HTTP_PROXY, 'enable_https': plexpy.CONFIG.ENABLE_HTTPS, 'https_cert': plexpy.CONFIG.HTTPS_CERT, 'https_key': plexpy.CONFIG.HTTPS_KEY, 'http_username': plexpy.CONFIG.HTTP_USERNAME, 'http_password': plexpy.CONFIG.HTTP_PASSWORD, 'http_basic_auth': plexpy.CONFIG.HTTP_BASIC_AUTH } webstart.initialize(web_config) # Open webbrowser if plexpy.CONFIG.LAUNCH_BROWSER and not args.nolaunch and not plexpy.DEV: plexpy.launch_browser(plexpy.CONFIG.HTTP_HOST, http_port, plexpy.CONFIG.HTTP_ROOT) # Wait endlessy for a signal to happen while True: if not plexpy.SIGNAL: try: time.sleep(1) except KeyboardInterrupt: plexpy.SIGNAL = 'shutdown' else: logger.info('Received signal: %s', plexpy.SIGNAL) if plexpy.SIGNAL == 'shutdown': plexpy.shutdown() elif plexpy.SIGNAL == 'restart': plexpy.shutdown(restart=True) else: plexpy.shutdown(restart=True, update=True) plexpy.SIGNAL = None
def main(): """ PlexPy application entry point. Parses arguments, setups encoding and initializes the application. """ # Fixed paths to PlexPy if hasattr(sys, 'frozen'): plexpy.FULL_PATH = os.path.abspath(sys.executable) else: plexpy.FULL_PATH = os.path.abspath(__file__) plexpy.PROG_DIR = os.path.dirname(plexpy.FULL_PATH) plexpy.ARGS = sys.argv[1:] # From sickbeard plexpy.SYS_PLATFORM = sys.platform plexpy.SYS_ENCODING = None try: locale.setlocale(locale.LC_ALL, "") plexpy.SYS_ENCODING = locale.getpreferredencoding() except (locale.Error, IOError): pass # for OSes that are poorly configured I'll just force UTF-8 if not plexpy.SYS_ENCODING or plexpy.SYS_ENCODING in ('ANSI_X3.4-1968', 'US-ASCII', 'ASCII'): plexpy.SYS_ENCODING = 'UTF-8' # Set up and gather command line arguments parser = argparse.ArgumentParser( description='A Python based monitoring and tracking tool for Plex Media Server.') parser.add_argument( '-v', '--verbose', action='store_true', help='Increase console logging verbosity') parser.add_argument( '-q', '--quiet', action='store_true', help='Turn off console logging') parser.add_argument( '-d', '--daemon', action='store_true', help='Run as a daemon') parser.add_argument( '-p', '--port', type=int, help='Force PlexPy to run on a specified port') parser.add_argument( '--dev', action='store_true', help='Start PlexPy in the development environment') parser.add_argument( '--datadir', help='Specify a directory where to store your data files') parser.add_argument( '--config', help='Specify a config file to use') parser.add_argument( '--nolaunch', action='store_true', help='Prevent browser from launching on startup') parser.add_argument( '--pidfile', help='Create a pid file (only relevant when running as a daemon)') args = parser.parse_args() if args.verbose: plexpy.VERBOSE = True if args.quiet: plexpy.QUIET = True # Do an intial setup of the logger. logger.initLogger(console=not plexpy.QUIET, log_dir=False, verbose=plexpy.VERBOSE) if args.dev: plexpy.DEV = True logger.debug(u"PlexPy is running in the dev environment.") if args.daemon: if sys.platform == 'win32': sys.stderr.write( "Daemonizing not supported under Windows, starting normally\n") else: plexpy.DAEMON = True plexpy.QUIET = True if args.pidfile: plexpy.PIDFILE = str(args.pidfile) # If the pidfile already exists, plexpy may still be running, so # exit if os.path.exists(plexpy.PIDFILE): raise SystemExit("PID file '%s' already exists. Exiting." % plexpy.PIDFILE) # The pidfile is only useful in daemon mode, make sure we can write the # file properly if plexpy.DAEMON: plexpy.CREATEPID = True try: with open(plexpy.PIDFILE, 'w') as fp: fp.write("pid\n") except IOError as e: raise SystemExit("Unable to write PID file: %s", e) else: logger.warn("Not running in daemon mode. PID file creation " \ "disabled.") # Determine which data directory and config file to use if args.datadir: plexpy.DATA_DIR = args.datadir else: plexpy.DATA_DIR = plexpy.PROG_DIR if args.config: config_file = args.config else: config_file = os.path.join(plexpy.DATA_DIR, config.FILENAME) # Try to create the DATA_DIR if it doesn't exist if not os.path.exists(plexpy.DATA_DIR): try: os.makedirs(plexpy.DATA_DIR) except OSError: raise SystemExit( 'Could not create data directory: ' + plexpy.DATA_DIR + '. Exiting....') # Make sure the DATA_DIR is writeable if not os.access(plexpy.DATA_DIR, os.W_OK): raise SystemExit( 'Cannot write to the data directory: ' + plexpy.DATA_DIR + '. Exiting...') # Put the database in the DATA_DIR plexpy.DB_FILE = os.path.join(plexpy.DATA_DIR, database.FILENAME) if plexpy.DAEMON: plexpy.daemonize() # Read config and start logging plexpy.initialize(config_file) # Start the background threads plexpy.start() # Open connection for websocket if plexpy.CONFIG.MONITORING_USE_WEBSOCKET: try: web_socket.start_thread() except: logger.warn(u"Websocket :: Unable to open connection.") # Fallback to polling plexpy.POLLING_FAILOVER = True plexpy.initialize_scheduler() # Force the http port if neccessary if args.port: http_port = args.port logger.info('Using forced web server port: %i', http_port) else: http_port = int(plexpy.CONFIG.HTTP_PORT) # Check if pyOpenSSL is installed. It is required for certificate generation # and for CherryPy. if plexpy.CONFIG.ENABLE_HTTPS: try: import OpenSSL except ImportError: logger.warn("The pyOpenSSL module is missing. Install this " \ "module to enable HTTPS. HTTPS will be disabled.") plexpy.CONFIG.ENABLE_HTTPS = False # Try to start the server. Will exit here is address is already in use. web_config = { 'http_port': http_port, 'http_host': plexpy.CONFIG.HTTP_HOST, 'http_root': plexpy.CONFIG.HTTP_ROOT, 'http_environment': plexpy.CONFIG.HTTP_ENVIRONMENT, 'http_proxy': plexpy.CONFIG.HTTP_PROXY, 'enable_https': plexpy.CONFIG.ENABLE_HTTPS, 'https_cert': plexpy.CONFIG.HTTPS_CERT, 'https_key': plexpy.CONFIG.HTTPS_KEY, 'http_username': plexpy.CONFIG.HTTP_USERNAME, 'http_password': plexpy.CONFIG.HTTP_PASSWORD, 'http_basic_auth': plexpy.CONFIG.HTTP_BASIC_AUTH } webstart.initialize(web_config) # Open webbrowser if plexpy.CONFIG.LAUNCH_BROWSER and not args.nolaunch and not plexpy.DEV: plexpy.launch_browser(plexpy.CONFIG.HTTP_HOST, http_port, plexpy.CONFIG.HTTP_ROOT) # Wait endlessy for a signal to happen while True: if not plexpy.SIGNAL: try: time.sleep(1) except KeyboardInterrupt: plexpy.SIGNAL = 'shutdown' else: logger.info('Received signal: %s', plexpy.SIGNAL) if plexpy.SIGNAL == 'shutdown': plexpy.shutdown() elif plexpy.SIGNAL == 'restart': plexpy.shutdown(restart=True) else: plexpy.shutdown(restart=True, update=True) plexpy.SIGNAL = None
def wait(): logger.info("Tautulli is ready!") # Wait endlessly for a signal to happen while True: if not plexpy.SIGNAL: try: time.sleep(1) except KeyboardInterrupt: plexpy.SIGNAL = 'shutdown' else: logger.info('Received signal: %s', plexpy.SIGNAL) if plexpy.SIGNAL == 'shutdown': plexpy.shutdown() elif plexpy.SIGNAL == 'restart': plexpy.shutdown(restart=True) elif plexpy.SIGNAL == 'checkout': plexpy.shutdown(restart=True, checkout=True) elif plexpy.SIGNAL == 'reset': plexpy.shutdown(restart=True, reset=True) elif plexpy.SIGNAL == 'update': plexpy.shutdown(restart=True, update=True) else: logger.error('Unknown signal. Shutting down...') plexpy.shutdown() plexpy.SIGNAL = None