def restoreDatabase(version): """ Restores a database to a previous version (backup file of version must still exist) :param version: Version to restore to :return: True if restore succeeds, False if it fails """ from medusa import helpers logger.log(u"Restoring database before trying upgrade again") if not helpers.restore_versioned_file(dbFilename(suffix='v' + str(version)), version): logger.log_error_and_exit(u"Database restore failed, abort upgrading database") return False else: return True
def migrate_config(self): """ Calls each successive migration until the config is the same version as SB expects """ if self.config_version > self.expected_config_version: logger.log_error_and_exit( u"""Your config version (%i) has been incremented past what this version of the application supports (%i). If you have used other forks or a newer version of the application, your config file may be unusable due to their modifications.""" % (self.config_version, self.expected_config_version) ) app.CONFIG_VERSION = self.config_version while self.config_version < self.expected_config_version: next_version = self.config_version + 1 if next_version in self.migration_names: migration_name = ': ' + self.migration_names[next_version] else: migration_name = '' log.info(u'Backing up config before upgrade') if not helpers.backup_versioned_file(app.CONFIG_FILE, self.config_version): logger.log_error_and_exit(u'Config backup failed, abort upgrading config') else: log.info(u'Proceeding with upgrade') # do the migration, expect a method named _migrate_v<num> log.info(u'Migrating config up to version {version} {migration_name}', {'version': next_version, 'migration_name': migration_name}) getattr(self, '_migrate_v' + str(next_version))() self.config_version = next_version # save new config after migration app.CONFIG_VERSION = self.config_version log.info(u'Saving config file to disk') app.instance.save_config()
def daemonize(self): """ Fork off as a daemon """ # pylint: disable=protected-access # An object is accessed for a non-existent member. # Access to a protected member of a client class # Make a non-session-leader child process try: pid = os.fork() # @UndefinedVariable - only available in UNIX if pid != 0: os._exit(0) except OSError as error: sys.stderr.write( 'fork #1 failed: {error_num}: {error_message}\n'.format( error_num=error.errno, error_message=error.strerror)) sys.exit(1) os.setsid() # @UndefinedVariable - only available in UNIX # https://github.com/SickRage/sickrage-issues/issues/2969 # http://www.microhowto.info/howto/cause_a_process_to_become_a_daemon_in_c.html#idp23920 # https://www.safaribooksonline.com/library/view/python-cookbook/0596001673/ch06s08.html # Previous code simply set the umask to whatever it was because it was ANDing instead of OR-ing # Daemons traditionally run with umask 0 anyways and this should not have repercussions os.umask(0) # Make the child a session-leader by detaching from the terminal try: pid = os.fork() # @UndefinedVariable - only available in UNIX if pid != 0: os._exit(0) except OSError as error: sys.stderr.write( 'fork #2 failed: Error {error_num}: {error_message}\n'.format( error_num=error.errno, error_message=error.strerror)) sys.exit(1) # Write pid if self.create_pid: pid = os.getpid() logger.log('Writing PID: {pid} to {filename}'.format( pid=pid, filename=self.pid_file)) try: with io.open(self.pid_file, 'w') as f_pid: f_pid.write('%s\n' % pid) except EnvironmentError as error: logger.log_error_and_exit( 'Unable to write PID file: {filename} Error {error_num}: {error_message}' .format(filename=self.pid_file, error_num=error.errno, error_message=error.strerror)) # Redirect all output sys.stdout.flush() sys.stderr.flush() devnull = getattr(os, 'devnull', '/dev/null') stdin = file(devnull) stdout = file(devnull, 'a+') stderr = file(devnull, 'a+') os.dup2(stdin.fileno(), getattr(sys.stdin, 'device', sys.stdin).fileno()) os.dup2(stdout.fileno(), getattr(sys.stdout, 'device', sys.stdout).fileno()) os.dup2(stderr.fileno(), getattr(sys.stderr, 'device', sys.stderr).fileno())