#!/usr/bin/env python import sys import os import time import cPickle from optparse import OptionParser from twisted.internet import reactor from twisted.web import xmlrpc from twisted.web import server from twisted.web import resource from twisted.spread import pb from twisted.python import log from twisted.cred import checkers, portal from zope.interface import implements from job_database import JobDatabase from job import Job # This class is needed to be able to send our Job class over Perspective Broker class ReceiverJob(pb.RemoteCopy, Job): pass pb.setUnjellyableForClass(Job, ReceiverJob) class dsaged(pb.Root): def __init__(self, jobdb): """Initializes the XMLRPC Server. Parameters: jobdb -- pass in the Database object """ # start our logging facility # log.startLogging(open('distributed_sage.log', 'a')) log.startLogging(sys.stdout) self.jobdb = jobdb def get_job(self, n): """Returns a list of job(s) dictionaries to the client. Parameters: n -- number of jobs, default = 1 """ print "Someone is getting %s job(s)!" % (str(n)) jobs = self.jobdb.get_active_jobs(n=n) print type(jobs) if jobs == None: return ['2**100'] return jobs def submit_job(self, job): """Submits a Job""" print "[dsaged] Someone submitted a job: %s" % (job) return self.jobdb.submit_job(job) def get_job_list(self): pass def show_active_jobs(self): """Returns a list of active jobs""" return self.jobdb.list_active_jobs() def show_active_clients(self): """Returns a list of active clients""" pass def log_msg(self, msg): """Logs message to distributed_sage.log Parameters: msg -- string to log """ if isinstance(msg) != str: msg = str(msg) log.msg(msg) class UserPerspective(pb.Avatar): def __init__(self, dsaged): self.dsaged = dsaged def perspective_get_job(self, n): return self.dsaged.get_job(n) class AdminPerspective(UserPerspective): def __init__(self, dsaged): self.dsaged = dsaged print "admin connected" def perspective_submit_job(self, Job): return self.dsaged.submit_job(Job) class Realm(object): implements(portal.IRealm) def __init__(self, dsaged): self.dsaged = dsaged def requestAvatar(self, avatarId, mind, *interfaces): if not pb.IPerspective in interfaces: raise NotImplementedError, "No supported avatar interface." else: if avatarId == 'admin': avatar = AdminPerspective(self.dsaged) else: avatar = UserPerspective(self.dsaged) return pb.IPerspective, avatar, lambda: None def usage(): """Prints usage help.""" # usage options usage = ['usage: %progr [options]\n', 'required options: --jobdir\n\n', 'Bug reports to '] parser = OptionParser(usage=''.join(usage)) parser.add_option("-j", "--jobdir", dest="dir", help="directory containing jobs") (options, args) = parser.parse_args() if options.dir == None: parser.print_help() sys.exit(0) parser.error("Please specify a valid job directory with the --jobdir flag.") sys.path.append(os.path.abspath(options.dir)) return options def main(): """Main execution loop of the server.""" options = usage() jobdb = JobDatabase('distributed_sage.db') p = portal.Portal(Realm(dsaged(jobdb))) p.registerChecker(checkers.OnDiskUsernamePasswordDatabase('user_database.db')) reactor.listenTCP(8082, pb.PBServerFactory(p)) reactor.run() if __name__ == "__main__": main()