class BEConnection( object ): """ This is the basic backend connection object. You probably don't want to use this directly. """ logmodule = 'Python Backend Connection' def __init__(self, backend, port, localname=None, blockshutdown=False, timeout=10.0): self.connected = False self.log = MythLog(self.logmodule) self._socklock = allocate_lock() self.host = backend self.port = port self.hostname = None self.deadline = timeout self.blockshutdown = blockshutdown self.localname = localname if self.localname is None: self.localname = socket.gethostname() try: self.connect() except socket.error, e: self.log.logTB(MythLog.SOCKET|MythLog.EXTRA) self.connected = False self.log(MythLog.IMPORTANT|MythLog.SOCKET, "Couldn't connect to backend [%s]:%d" \ % (self.host, self.port)) raise MythBEError(MythError.PROTO_CONNECTION, self.host, self.port) except:
class BEConnection( object ): """ This is the basic backend connection object. You probably don't want to use this directly. """ logmodule = 'Python Backend Connection' def __init__(self, backend, port, localname=None, blockshutdown=False, timeout=10.0): self.connected = False self.log = MythLog(self.logmodule) self._socklock = allocate_lock() self.host = backend self.port = port self.hostname = None self.deadline = timeout self.blockshutdown = blockshutdown self.localname = localname if self.localname is None: self.localname = socket.gethostname() try: self.connect() except socket.error, e: self.log.logTB(MythLog.SOCKET) self.connected = False self.log(MythLog.GENERAL, MythLog.CRIT, "Couldn't connect to backend [%s]:%d" \ % (self.host, self.port)) raise MythBEError(MythError.PROTO_CONNECTION, self.host, self.port) except:
def __init__(self, backend, port, localname=None, blockshutdown=False, timeout=10.0): self.connected = False self.log = MythLog(self.logmodule) self._socklock = allocate_lock() self.host = backend self.port = port self.hostname = None self.deadline = timeout self.blockshutdown = blockshutdown self.localname = localname if self.localname is None: self.localname = socket.gethostname() try: self.connect() except socket.error, e: self.log.logTB(MythLog.SOCKET) self.connected = False self.log(MythLog.GENERAL, MythLog.CRIT, "Couldn't connect to backend [%s]:%d" \ % (self.host, self.port)) raise MythBEError(MythError.PROTO_CONNECTION, self.host, self.port)
def formatJob(self, cmd): """ Program.formatPath(cmd) -> formatted command string 'cmd' string is formatted as per MythJobQueue syntax """ for tag in ('chanid', 'title', 'subtitle', 'description', 'hostname', 'category', 'recgroup', 'playgroup', 'parentid', 'findid', 'recstatus', 'rectype'): cmd = cmd.replace('%%%s%%' % tag.upper(), str(self[tag])) cmd = cmd.replace('%ORIGINALAIRDATE%', self.airdate.isoformat()) for (tag, data) in (('STARTTIME', 'recstartts'), ('ENDTIME', 'recendts'), ('PROGSTART', 'starttime'), ('PROGEND', 'endtime')): t = self[data] cmd = cmd.replace('%%%s%%' % tag, t.mythformat()) cmd = cmd.replace('%%%sISO%%' % tag, t.isoformat()) cmd = cmd.replace('%%%sISOUTC%%' % tag, \ (t+timedelta(0,altzone)).isoformat()) cmd = cmd.replace('%VERBOSELEVEL%', MythLog._parsemask()) cmd = cmd.replace('%RECID%', str(self.recordid)) path = FileOps(self.hostname, db=self._db).fileExists(\ self.filename.rsplit('/',1)[1], self.storagegroup) cmd = cmd.replace('%DIR%', path.rsplit('/', 1)[0]) cmd = cmd.replace('%FILE%', path.rsplit('/', 1)[1]) cmd = cmd.replace('%REACTIVATE%', str(OldRecorded(\ (self.chanid, self.recstartts),db=self._db).reactivate)) return cmd
def __init__(self, path=None, setting=None, db=None, useshell=True): DBCache.__init__(self, db=db) self.log = MythLog(self.logmodule, db=self) self.path = None if setting is not None: # pull setting from database, substitute from argument if needed host = self.gethostname() self.path = self.settings[host][setting] if (self.path is None) and (path is None): raise MythDBError(MythError.DB_SETTING, setting, host) if self.path is None: # setting not given, use path from argument if path is None: raise MythError('Invalid input to System()') self.path = path cmd = self.path.split()[0] if self.path.startswith('/'): # test full given path if not os.access(cmd, os.F_OK): raise MythFileError('Defined executable path does not exist.') else: # search command from PATH for folder in os.environ['PATH'].split(':'): if os.access(os.path.join(folder, cmd), os.F_OK): self.path = os.path.join(folder, self.path) break else: raise MythFileError('Defined executable path does not exist.') self.returncode = 0 self.stderr = '' self.useshell = useshell
def __init__(self, backend=None, port=None, db=None): if backend and port: XMLConnection.__init__(self, backend, port) self.db = db return self.db = DBCache(db) self.log = MythLog('Python XML Connection') if backend is None: # use master backend backend = self.db.settings.NULL.MasterServerIP if re.match('(?:\d{1,3}\.){3}\d{1,3}',backend): # process ip address with self.db.cursor(self.log) as cursor: if cursor.execute("""SELECT hostname FROM settings WHERE value='BackendServerIP' AND data=%s""", backend) == 0: raise MythDBError(MythError.DB_SETTING, backend+': BackendServerIP') self.host = cursor.fetchone()[0] self.port = int(self.db.settings[self.host].BackendStatusPort) else: # assume given a hostname self.host = backend self.port = int(self.db.settings[self.host].BackendStatusPort) if not self.port: # try a truncated hostname self.host = backend.split('.')[0] self.port = int(self.db.setting[self.host].BackendStatusPort) if not self.port: raise MythDBError(MythError.DB_SETTING, backend+': BackendStatusPort')
def __init__(self, backend, port, localname=None, blockshutdown=False, timeout=10.0): self.connected = False self.log = MythLog(self.logmodule) self._socklock = allocate_lock() self.host = backend self.port = port self.hostname = None self.deadline = timeout self.blockshutdown = blockshutdown self.localname = localname if self.localname is None: self.localname = socket.gethostname() try: self.connect() except socket.error, e: self.log.logTB(MythLog.SOCKET|MythLog.EXTRA) self.connected = False self.log(MythLog.IMPORTANT|MythLog.SOCKET, "Couldn't connect to backend [%s]:%d" \ % (self.host, self.port)) raise MythBEError(MythError.PROTO_CONNECTION, self.host, self.port)
def __init__(self, host, port, deadline=10.0, test=True): self.isConnected = False self.host = host self.port = int(port) self.log = MythLog('Python Frontend Connection') self._deadline = deadline self.connect(test)
def formatJob(self, cmd): """ Program.formatPath(cmd) -> formatted command string 'cmd' string is formatted as per MythJobQueue syntax """ for tag in ('chanid','title','subtitle','description','hostname', 'category','recgroup','playgroup','parentid','findid', 'recstatus','rectype'): cmd = cmd.replace('%%%s%%' % tag.upper(), str(self[tag])) cmd = cmd.replace('%ORIGINALAIRDATE%', self.airdate.isoformat()) for (tag, data) in (('STARTTIME','recstartts'),('ENDTIME','recendts'), ('PROGSTART','starttime'),('PROGEND','endtime')): t = self[data] cmd = cmd.replace('%%%s%%' % tag, t.mythformat()) cmd = cmd.replace('%%%sISO%%' % tag, t.isoformat()) cmd = cmd.replace('%%%sISOUTC%%' % tag, \ (t+timedelta(0,altzone)).isoformat()) cmd = cmd.replace('%VERBOSELEVEL%', MythLog._parsemask()) cmd = cmd.replace('%RECID%', str(self.recordid)) path = FileOps(self.hostname, db=self._db).fileExists(\ self.filename.rsplit('/',1)[1], self.storagegroup) cmd = cmd.replace('%DIR%', path.rsplit('/',1)[0]) cmd = cmd.replace('%FILE%',path.rsplit('/',1)[1]) cmd = cmd.replace('%REACTIVATE%', str(OldRecorded(\ (self.chanid, self.recstartts),db=self._db).reactivate)) return cmd
def __init__(self, backend=None, noshutdown=False, db=None, opts=None): self.db = DBCache(db) self.log = MythLog(self.logmodule, db=self.db) self.hostname = None if opts is None: self.opts = BEConnection.BEConnOpts(noshutdown) else: self.opts = opts if backend is None: # no backend given, use master self.host = self.db.settings.NULL.MasterServerIP else: if self._reip.match(backend): # given backend is IP address self.host = backend else: # given backend is hostname, pull address from database self.hostname = backend self.host = self.db.settings[backend].BackendServerIP if not self.host: raise MythDBError(MythError.DB_SETTING, 'BackendServerIP', backend) if self.hostname is None: # reverse lookup hostname from address with self.db.cursor(self.log) as cursor: if cursor.execute( """SELECT hostname FROM settings WHERE value='BackendServerIP' AND data=?""", [self.host]) == 0: # no match found raise MythDBError(MythError.DB_SETTING, 'BackendServerIP', self.host) self.hostname = cursor.fetchone()[0] # lookup port from database self.port = int(self.db.settings[self.hostname].BackendServerPort) if not self.port: raise MythDBError(MythError.DB_SETTING, 'BackendServerPort', self.port) self._uuid = uuid4() self._ident = '%s:%d' % (self.host, self.port) if self._ident in self._shared: # existing connection found # register and reconnect if necessary self.be = self._shared[self._ident] self.be.registeruser(self._uuid, self.opts) self.be.reconnect() else: # no existing connection, create new self.be = BEConnection(self.host, self.port, \ self.db.gethostname(), self.opts) self.be.registeruser(self._uuid, self.opts) self._shared[self._ident] = self.be
def __init__(self, dbconn): self.log = MythLog('Python Database Connection') self.tablefields = None self.settings = None self.dbconn = dbconn self._refs = {} self.log(MythLog.DATABASE, "Attempting connection", '\n'.join(["'%s': '%s'" % (k, v) for k, v in dbconn.items()])) try: _Connection_Pool.__init__(self) except: raise MythDBError(MythError.DB_CONNECTION, dbconn)
def __init__(self, backend, port, localname=None, \ opts=None, deadline=10.0): """ BEConnection(backend, type, db=None) -> backend socket connection 'backend' can be either a hostname or IP address, or will default to the master backend if None. """ self._regusers = weakref.WeakValueDictionary() self._regevents = weakref.WeakValueDictionary() self._socklock = allocate_lock() self.connected = False self.threadrunning = False self.log = MythLog(self.logmodule) self.host = backend self.port = port self.hostname = None self.deadline = deadline self.localname = localname if self.localname is None: self.localname = socket.gethostname() self.opts = opts if self.opts is None: self.opts = self.BEConnOpts() self.eventqueue = Queue.Queue() try: self.connect() except socket.error, e: self.log.logTB(MythLog.SOCKET|MythLog.EXTRA) self.connected = False self.log(MythLog.IMPORTANT|MythLog.SOCKET, "Couldn't connect to backend %s:%d" \ % (self.host, self.port)) raise MythBEError(MythError.PROTO_CONNECTION, self.host, self.port)
def __init__(self, dbconn): self.log = MythLog('Python Database Connection') self.tablefields = None self.settings = None self._pool = [] self._inuse = {} self._stack = {} self._refs = {} self._poolsize = self._defpoolsize self.dbconn = dbconn try: self.log(MythLog.DATABASE, "Attempting connection", '\n'.join(["'%s': '%s'" % (k,v) for k,v in dbconn.items()])) for i in range(self._poolsize): self._pool.append(self.connect()) except: raise MythDBError(MythError.DB_CONNECTION, dbconn)
def __init__(self): self.log = MythLog('Python M-Search') port = 1900 addr = '239.255.255.250' self.dest = (addr, port) self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) listening = False while listening == False: try: self.sock.bind(('', port)) self.addr = (addr, port) listening = True except socket.error, e: if port < 1910: port += 1 else: raise MythError(MythError.SOCKET, e)
def formatJob(self, cmd): """ Program.formatPath(cmd) -> formatted command string 'cmd' string is formatted as per MythJobQueue syntax """ for tag in ( "chanid", "title", "subtitle", "description", "hostname", "category", "recgroup", "playgroup", "parentid", "findid", "recstatus", "rectype", ): cmd = cmd.replace("%%%s%%" % tag.upper(), str(self[tag])) cmd = cmd.replace("%ORIGINALAIRDATE%", self.airdate.isoformat()) for (tag, data) in ( ("STARTTIME", "recstartts"), ("ENDTIME", "recendts"), ("PROGSTART", "starttime"), ("PROGEND", "endtime"), ): t = self[data] cmd = cmd.replace("%%%s%%" % tag, t.mythformat()) cmd = cmd.replace("%%%sISO%%" % tag, t.isoformat()) cmd = cmd.replace("%%%sISOUTC%%" % tag, (t + timedelta(0, altzone)).isoformat()) cmd = cmd.replace("%VERBOSELEVEL%", MythLog._parselevel()) cmd = cmd.replace("%RECID%", str(self.recordid)) path = FileOps(self.hostname, db=self._db).fileExists(self.filename.rsplit("/", 1)[1], self.storagegroup) cmd = cmd.replace("%DIR%", path.rsplit("/", 1)[0]) cmd = cmd.replace("%FILE%", path.rsplit("/", 1)[1]) cmd = cmd.replace("%REACTIVATE%", str(OldRecorded((self.chanid, self.recstartts), db=self._db).reactivate)) return cmd
class BEConnection( object ): """ This is the basic backend connection object. You probably dont want to use this directly. """ logmodule = 'Python Backend Connection' class BEConnOpts( OrdDict ): def __init__(self, noshutdown=False, systemevents=False, generalevents=False): OrdDict.__init__(self, (('noshutdown',noshutdown), ('systemevents',systemevents), ('generalevents',generalevents))) def __and__(self, other): res = self.__class__() for key in self._field_order: if self[key] & other[key]: res[key] = True return res def __or__(self, other): res = self.__class__() for key in self._field_order: if self[key] | other[key]: res[key] = True return res def __xor__(self, other): res = self.__class__() for key in self._field_order: if self[key] ^ other[key]: res[key] = True return res def __init__(self, backend, port, localname=None, \ opts=None, deadline=10.0): """ BEConnection(backend, type, db=None) -> backend socket connection 'backend' can be either a hostname or IP address, or will default to the master backend if None. """ self._regusers = weakref.WeakValueDictionary() self._regevents = weakref.WeakValueDictionary() self._socklock = allocate_lock() self.connected = False self.threadrunning = False self.log = MythLog(self.logmodule) self.host = backend self.port = port self.hostname = None self.deadline = deadline self.localname = localname if self.localname is None: self.localname = socket.gethostname() self.opts = opts if self.opts is None: self.opts = self.BEConnOpts() self.eventqueue = Queue.Queue() try: self.connect() except socket.error, e: self.log.logTB(MythLog.SOCKET|MythLog.EXTRA) self.connected = False self.log(MythLog.IMPORTANT|MythLog.SOCKET, "Couldn't connect to backend %s:%d" \ % (self.host, self.port)) raise MythBEError(MythError.PROTO_CONNECTION, self.host, self.port) except:
def __init__(self, *args, **kwargs): socket.socket.__init__(self, *args, **kwargs) self.log = MythLog('Python Socket') self.setdeadline(10.0)
def __init__(self, db): self.db = db self.log = MythLog('Schema Update (%s)' % self._schema_name)
def __init__(self, backend=None, blockshutdown=False, events=False, db=None): self.db = DBCache(db) self.log = MythLog(self.logmodule, db=self.db) self.hostname = None self.sendcommands = True self.blockshutdown = blockshutdown self.receiveevents = events if backend is None: # no backend given, use master self.host = self.db.settings.NULL.MasterServerIP else: backend = backend.strip('[]') if self._reip.match(backend): # given backend is IP address self.host = backend elif check_ipv6(backend): # given backend is IPv6 address self.host = backend else: # given backend is hostname, pull address from database self.hostname = backend self.host = self.db.settings[backend].BackendServerIP if not self.host: raise MythDBError(MythError.DB_SETTING, 'BackendServerIP', backend) if self.hostname is None: # reverse lookup hostname from address with self.db.cursor(self.log) as cursor: if cursor.execute( """SELECT hostname FROM settings WHERE value='BackendServerIP' AND data=?""", [self.host]) == 0: # no match found raise MythDBError(MythError.DB_SETTING, 'BackendServerIP', self.host) self.hostname = cursor.fetchone()[0] # lookup port from database self.port = int(self.db.settings[self.hostname].BackendServerPort) if not self.port: raise MythDBError(MythError.DB_SETTING, 'BackendServerPort', self.port) self._ident = '%s:%d' % (self.host, self.port) if self._ident in self._shared: # existing connection found self._conn = self._shared[self._ident] if self.sendcommands: if self._conn.command is None: self._conn.command = self._newcmdconn() elif self.blockshutdown: # upref block of shutdown # issue command to backend if needed self._conn.blockshutdown += 1 if self._conn.blockshutdown == 1: self._conn.command.blockShutdown() if self.receiveevents: if self._conn.event is None: self._conn.event = self._neweventconn() else: # no existing connection, create new self._conn = self._ConnHolder() if self.sendcommands: self._conn.command = self._newcmdconn() if self.blockshutdown: self._conn.blockshutdown = 1 if self.receiveevents: self._conn.event = self._neweventconn() self._shared[self._ident] = self._conn self._events = self._listhandlers() for func in self._events: self.registerevent(func)
def ftopen(file, mode, forceremote=False, nooverwrite=False, db=None, \ chanid=None, starttime=None, download=False): """ ftopen(file, mode, forceremote=False, nooverwrite=False, db=None) -> FileTransfer object -> file object Method will attempt to open file locally, falling back to remote access over mythprotocol if necessary. 'forceremote' will force a FileTransfer object if possible. 'file' takes a standard MythURI: myth://<group>@<host>:<port>/<path> 'mode' takes a 'r' or 'w' 'nooverwrite' will refuse to open a file writable, if a local file is found. """ db = DBCache(db) log = MythLog('Python File Transfer', db=db) reuri = re.compile(\ 'myth://((?P<group>.*)@)?(?P<host>[\[\]a-zA-Z0-9_\-\.]*)(:[0-9]*)?/(?P<file>.*)') reip = re.compile('(?:\d{1,3}\.){3}\d{1,3}') if mode not in ('r', 'w'): raise TypeError("File I/O must be of type 'r' or 'w'") if chanid and starttime: protoopen = lambda host, file, storagegroup: \ RecordFileTransfer(host, file, storagegroup,\ mode, chanid, starttime, db) elif download: protoopen = lambda host, lfile, storagegroup: \ DownloadFileTransfer(host, lfile, storagegroup, \ mode, file, db) else: protoopen = lambda host, file, storagegroup: \ FileTransfer(host, file, storagegroup, mode, db) # process URI (myth://<group>@<host>[:<port>]/<path/to/file>) match = reuri.match(file) if match is None: raise MythError('Invalid FileTransfer input string: ' + file) host = match.group('host') filename = match.group('file') sgroup = match.group('group') if sgroup is None: sgroup = 'Default' # get full system name host = host.strip('[]') if reip.match(host) or check_ipv6(host): with db.cursor(log) as cursor: if cursor.execute( """SELECT hostname FROM settings WHERE value='BackendServerIP' AND data=%s""", host) == 0: raise MythDBError(MythError.DB_SETTING, \ 'BackendServerIP', backend) host = cursor.fetchone()[0] # user forced to remote access if forceremote: if (mode == 'w') and (filename.find('/') != -1): raise MythFileError(MythError.FILE_FAILED_WRITE, file, 'attempting remote write outside base path') if nooverwrite and FileOps(host, db=db).fileExists(filename, sgroup): raise MythFileError(MythError.FILE_FAILED_WRITE, file, 'refusing to overwrite existing file') return protoopen(host, filename, sgroup) if mode == 'w': # check for pre-existing file path = FileOps(host, db=db).fileExists(filename, sgroup) sgs = list(db.getStorageGroup(groupname=sgroup)) if path is not None: if nooverwrite: raise MythFileError(MythError.FILE_FAILED_WRITE, file, 'refusing to overwrite existing file') for sg in sgs: if sg.dirname in path: if sg.local: return open(sg.dirname + filename, mode) else: return protoopen(host, filename, sgroup) # prefer local storage for new files for i, v in reversed(list(enumerate(sgs))): if not v.local: sgs.pop(i) else: st = os.statvfs(v.dirname) v.free = st[0] * st[3] if len(sgs) > 0: # choose path with most free space sg = sorted(sgs, key=lambda sg: sg.free, reverse=True)[0] # create folder if it does not exist if filename.find('/') != -1: path = sg.dirname + filename.rsplit('/', 1)[0] if not os.access(path, os.F_OK): os.makedirs(path) log(log.FILE, log.INFO, 'Opening local file (w)', sg.dirname + filename) return open(sg.dirname + filename, mode) # fallback to remote write else: if filename.find('/') != -1: raise MythFileError( MythError.FILE_FAILED_WRITE, file, 'attempting remote write outside base path') return protoopen(host, filename, sgroup) else: # search for file in local directories sg = findfile(filename, sgroup, db) if sg is not None: # file found, open local log(log.FILE, log.INFO, 'Opening local file (r)', sg.dirname + filename) return open(sg.dirname + filename, mode) else: # file not found, open remote return protoopen(host, filename, sgroup)
class BEConnection( object ): """ This is the basic backend connection object. You probably dont want to use this directly. """ logmodule = 'Python Backend Connection' class BEConnOpts( OrdDict ): def __init__(self, noshutdown=False, systemevents=False, generalevents=False): OrdDict.__init__(self, (('noshutdown',noshutdown), ('systemevents',systemevents), ('generalevents',generalevents))) def __and__(self, other): res = self.__class__() for key in self._field_order: if self[key] & other[key]: res[key] = True return res def __or__(self, other): res = self.__class__() for key in self._field_order: if self[key] | other[key]: res[key] = True return res def __xor__(self, other): res = self.__class__() for key in self._field_order: if self[key] ^ other[key]: res[key] = True return res def __init__(self, backend, port, localname=None, \ opts=None, deadline=10.0): """ BEConnection(backend, type, db=None) -> backend socket connection 'backend' can be either a hostname or IP address, or will default to the master backend if None. """ self._regusers = weakref.WeakValueDictionary() self._regevents = weakref.WeakValueDictionary() self._socklock = allocate_lock() self.connected = False self.threadrunning = False self.log = MythLog(self.logmodule) self.host = backend self.port = port self.hostname = None self.deadline = deadline self.localname = localname if self.localname is None: self.localname = socket.gethostname() self.opts = opts if self.opts is None: self.opts = self.BEConnOpts() self.eventqueue = Queue.Queue() try: self.connect() except socket.error, e: self.log.logTB(MythLog.SOCKET|MythLog.EXTRA) self.connected = False self.log(MythLog.IMPORTANT|MythLog.SOCKET, "Couldn't connect to backend %s:%d" \ % (self.host, self.port)) raise MythBEError(MythError.PROTO_CONNECTION, self.host, self.port)
def __init__(self, host, port): self.host, self.port = host, int(port) self.log = MythLog('Python XML Connection')