123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- import os,sys,logging
- import signal,time, atexit
- from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
- import xmlrpclib,sqlite3
- import bb.server.xmlrpc
- import prserv
- import prserv.db
- if sys.hexversion < 0x020600F0:
- print("Sorry, python 2.6 or later is required.")
- sys.exit(1)
- class Handler(SimpleXMLRPCRequestHandler):
- def _dispatch(self,method,params):
- try:
- value=self.server.funcs[method](*params)
- except:
- import traceback
- traceback.print_exc()
- raise
- return value
- PIDPREFIX = "/tmp/PRServer_%s_%s.pid"
- class PRServer(SimpleXMLRPCServer):
- pidfile="/tmp/PRServer.pid"
- def __init__(self, dbfile, logfile, interface, daemon=True):
- ''' constructor '''
- SimpleXMLRPCServer.__init__(self, interface,
- requestHandler=SimpleXMLRPCRequestHandler,
- logRequests=False, allow_none=True)
- self.dbfile=dbfile
- self.daemon=daemon
- self.logfile=logfile
- self.host, self.port = self.socket.getsockname()
- self.db=prserv.db.PRData(dbfile)
- self.table=self.db["PRMAIN"]
- self.pidfile=PIDPREFIX % interface
- self.register_function(self.getPR, "getPR")
- self.register_function(self.quit, "quit")
- self.register_function(self.ping, "ping")
- self.register_function(self.export, "export")
- self.register_function(self.importone, "importone")
- self.register_introspection_functions()
-
- def export(self, version=None, pkgarch=None, checksum=None, colinfo=True):
- try:
- return self.table.export(version, pkgarch, checksum, colinfo)
- except sqlite3.Error as exc:
- logging.error(str(exc))
- return None
- def importone(self, version, pkgarch, checksum, value):
- return self.table.importone(version, pkgarch, checksum, value)
- def ping(self):
- return not self.quit
- def getPR(self, version, pkgarch, checksum):
- try:
- return self.table.getValue(version, pkgarch, checksum)
- except prserv.NotFoundError:
- logging.error("can not find value for (%s, %s)",version, checksum)
- return None
- except sqlite3.Error as exc:
- logging.error(str(exc))
- return None
- def quit(self):
- self.quit=True
- return
- def _serve_forever(self):
- self.quit = False
- self.timeout = 0.5
- while not self.quit:
- self.handle_request()
- logging.info("PRServer: stopping...")
- self.server_close()
- return
- def start(self):
- if self.daemon is True:
- logging.info("PRServer: try to start daemon...")
- self.daemonize()
- else:
- atexit.register(self.delpid)
- pid = str(os.getpid())
- pf = file(self.pidfile, 'w+')
- pf.write("%s\n" % pid)
- pf.write("%s\n" % self.host)
- pf.write("%s\n" % self.port)
- pf.close()
- logging.info("PRServer: start success! DBfile: %s, IP: %s, PORT: %d" %
- (self.dbfile, self.host, self.port))
- self._serve_forever()
- def delpid(self):
- os.remove(self.pidfile)
- def daemonize(self):
- """
- See Advanced Programming in the UNIX, Sec 13.3
- """
- try:
- pid = os.fork()
- if pid > 0:
- #parent return instead of exit to give control
- return
- except OSError as e:
- raise Exception("%s [%d]" % (e.strerror, e.errno))
- os.setsid()
- """
- fork again to make sure the daemon is not session leader,
- which prevents it from acquiring controlling terminal
- """
- try:
- pid = os.fork()
- if pid > 0: #parent
- sys.exit(0)
- except OSError as e:
- raise Exception("%s [%d]" % (e.strerror, e.errno))
- os.umask(0)
- os.chdir("/")
- sys.stdout.flush()
- sys.stderr.flush()
- si = file('/dev/null', 'r')
- so = file(self.logfile, 'a+')
- se = so
- os.dup2(si.fileno(),sys.stdin.fileno())
- os.dup2(so.fileno(),sys.stdout.fileno())
- os.dup2(se.fileno(),sys.stderr.fileno())
- # write pidfile
- atexit.register(self.delpid)
- pid = str(os.getpid())
- pf = file(self.pidfile, 'w')
- pf.write("%s\n" % pid)
- pf.close()
- logging.info("PRServer: starting daemon success! DBfile: %s, IP: %s, PORT: %s, PID: %s" %
- (self.dbfile, self.host, self.port, pid))
- self._serve_forever()
- exit(0)
- class PRServerConnection():
- def __init__(self, host, port):
- self.connection = bb.server.xmlrpc._create_server(host, port)
- self.host = host
- self.port = port
- def terminate(self):
- # Don't wait for server indefinitely
- import socket
- socket.setdefaulttimeout(2)
- try:
- self.connection.quit()
- except Exception as exc:
- sys.stderr.write("%s\n" % str(exc))
- def getPR(self, version, pkgarch, checksum):
- return self.connection.getPR(version, pkgarch, checksum)
- def ping(self):
- return self.connection.ping()
- def export(self,version=None, pkgarch=None, checksum=None, colinfo=True):
- return self.connection.export(version, pkgarch, checksum, colinfo)
-
- def importone(self, version, pkgarch, checksum, value):
- return self.connection.importone(version, pkgarch, checksum, value)
- def start_daemon(dbfile, logfile, interface):
- try:
- pf = file(PRServer.pidfile,'r')
- pid = int(pf.readline().strip())
- pf.close()
- except IOError:
- pid = None
- if pid:
- sys.stderr.write("pidfile %s already exist. Daemon already running?\n"
- % PRServer.pidfile)
- return 1
- server = PRServer(os.path.abspath(dbfile), os.path.abspath(logfile), interface)
- server.start()
- return 0
- def stop_daemon(host, port):
- pidfile = PIDPREFIX % (host, port)
- try:
- pf = file(pidfile,'r')
- pid = int(pf.readline().strip())
- pf.close()
- except IOError:
- pid = None
- if not pid:
- sys.stderr.write("pidfile %s does not exist. Daemon not running?\n"
- % pidfile)
- return 1
- PRServerConnection(host, port).terminate()
- time.sleep(0.5)
- try:
- while 1:
- os.kill(pid,signal.SIGTERM)
- time.sleep(0.1)
- except OSError as e:
- err = str(e)
- if err.find("No such process") > 0:
- if os.path.exists(PRServer.pidfile):
- os.remove(PRServer.pidfile)
- else:
- raise Exception("%s [%d]" % (e.strerror, e.errno))
- return 0
- def ping(host, port):
- print PRServerConnection(host,port).ping()
- return 0
|