def qfront(self): """pop the top job off of the queue that is in a queued 'Q' state""" db = DAL(config.uri, auto_import=True, migrate=False, folder=config.dbdir) myorder = db.jobs.priority #myorder = db.jobs.priority | db.jobs.id row = db(db.jobs.state==STATE_QUEUED).select(orderby=myorder).first() db.close() if row: return row.id else: return None
def __init__(self): # if any jobs marked in run state when scheduler starts # replace their state with X to mark that they have been shutdown db = DAL(config.uri, auto_import=True, migrate=False, folder=config.dbdir) myset = db(db.jobs.state == 'R') myset.update(state='X') db.commit() self.sem = BoundedSemaphore(config.np) self.mutex = Lock()
def start(self,jid): """start running a job by creating a new process""" db = DAL(config.uri, auto_import=True, migrate=False, folder=config.dbdir) uid = db.jobs(jid).uid user = db.users(uid).user app = db.jobs(jid).app cid = db.jobs(jid).cid np = db.jobs(jid).np if np > 1: # use mpi command = db.jobs(jid).command command = config.mpirun + " -np " + str(np) + " " + command else: # dont use mpi command = db.jobs(jid).command # redirect output to appname.out file outfn = app + ".out" cmd = command + ' > ' + outfn + ' 2>&1 ' print "cmd:", cmd run_dir = os.path.join(user_dir, user, app, cid) # if number procs available fork new process with command for i in range(np): self.sem.acquire() p = Process(target=self.start_job, args=(run_dir,cmd,app,jid,np,myjobs)) p.start() for i in range(np): self.sem.release()
def __init__(self): # if any jobs marked in run state when scheduler starts # replace their state with X to mark that they have been shutdown db = DAL(config.uri, auto_import=True, migrate=False, folder=config.dbdir) myset = db(db.jobs.state == STATE_RUN) myset.update(state=STATE_STOPPED) db.commit() self.sem = BoundedSemaphore(config.np) self.mutex = Lock() # set time zone try: os.environ['TZ'] = config.time_zone time.tzset() except: pass
def stop_expired_jobs(self): """shutdown jobs that exceed their time limit""" db = DAL(config.uri, auto_import=True, migrate=False, folder=config.dbdir) rows = db(db.jobs.state==STATE_RUN).select() for row in rows: if row: walltime = int(row.walltime) time_submit = time.mktime(datetime.datetime.strptime( row.time_submit, "%a %b %d %H:%M:%S %Y").timetuple()) now = time.mktime(datetime.datetime.now().timetuple()) runtime = now - time_submit if runtime > walltime: print "INFO: scheduler stopped job", row.id, "REASON: reached timeout" self.stop(row.id) db.close()
def start(self,jid): """start running a job by creating a new process""" global p, jobs myjobs = [] db = DAL(config.uri, auto_import=True, migrate=False, folder=config.dbdir) user = db.jobs(jid).user app = db.jobs(jid).app cid = db.jobs(jid).cid np = db.jobs(jid).np if np > 1: # use mpi command = db.apps(name=app).command command = config.mpirun + " -np " + str(np) + " " + command else: # dont use mpi command = db.apps(name=app).command exe = os.path.join(config.apps_dir,app,app) outfn = app + ".out" cmd = command + ' >& ' + outfn run_dir = os.path.join(config.user_dir,user,app,cid) # if number procs available fork new process with command for i in range(np): self.sem.acquire() p = Process(target=self.start_job, args=(run_dir,cmd,app,jid,np,)) myjobs.append(p) print len(myjobs), myjobs p.start() for i in range(np): self.sem.release()
def _set_state(self,jid,state): """update state of job""" self.mutex.acquire() db = DAL(config.uri, auto_import=True, migrate=False, folder=config.dbdir) db.jobs[jid] = dict(state=state) db.commit() db.close() self.mutex.release()
def qdel(self,jid): """delete job jid from the queue""" #try: db = DAL(config.uri, auto_import=True, migrate=False, folder=config.dbdir) del db.jobs[jid] db.commit() db.close()
def qsub(self,app,cid,user,np,pry,desc=""): """queue job ... really just set state to 'Q'.""" db = DAL(config.uri, auto_import=True, migrate=False, folder=config.dbdir) jid = db.jobs.insert(user=user, app=app, cid=cid, state=STATE_QUEUED, description=desc, time_submit=time.asctime(), np=np, priority=pry) db.commit() db.close() return str(jid)
def __init__(self, uri=config.uri, migrate=False): #self.db = DAL(uri, auto_import=True, migrate=migrate, folder=config.dbdir) self.db = DAL(uri, migrate=migrate, folder=config.dbdir) # must define these here because need to use the db instance self.users = self.db.define_table('users', Field('id', 'integer'), Field('user', 'string'), Field('passwd', 'string'), Field('email', 'string'), Field('priority', 'integer')) self.apps = self.db.define_table('apps', Field('id', 'integer'), Field('name', 'string'), Field('description', 'string'), Field('category', 'string'), Field('language', 'string'), Field('input_format', 'string'), Field('command', 'string'), Field('preprocess', 'string'), Field('postprocess', 'string'), Field('uid', 'integer')) self.jobs = self.db.define_table('jobs', Field('id', 'integer'), Field('user', 'string'), Field('app', 'string'), Field('cid', 'string'), Field('state', 'string'), Field('time_submit', 'string'), Field('description', 'string'), Field('np', 'integer'), Field('priority', 'integer'), Field('shared', 'string')) self.plots = self.db.define_table('plots', Field('id', 'integer'), Field('appid', self.db.apps), Field('ptype', 'string'), Field('title', 'string'), Field('options', 'string'), Field('datadef', 'string')) self.datasource = self.db.define_table('datasource', Field('id', 'integer'), Field('pltid', 'integer'), Field('label', 'string'), Field('ptype', 'string'), Field('color', 'string'), Field('filename', 'string'), Field('cols', 'string'), Field('line_range', 'string')) self.aws_creds = self.db.define_table('aws_creds', Field('id', 'integer'), Field('key', 'string'), Field('secret', 'string'), Field('account_id', 'string'), Field('uid', 'integer')) self.aws_instances = self.db.define_table('aws_instances', Field('id', 'integer'), Field('region', 'string'), Field('instance', 'string'), Field('itype', 'string'), Field('rate', 'double'), Field('uid', 'integer')) self.containers = self.db.define_table('containers', Field('id', 'integer'), Field('containerid', 'string'), Field('image', 'string'), Field('command', 'string'), Field('uid', 'integer')) self.disciplines = self.db.define_table('disciplines', Field('name'))
import tornado.ioloop import tornado.web from gluino import wrapper, DAL, Field, SQLFORM, cache, IS_NOT_EMPTY import time # configure the gluino wrapper wrapper.debug = True wrapper.http = lambda code, message: tornado.web.HTTPError(code) wrapper.redirect = lambda status, url: tornado.web.RequestHandler.redirect(url) # create database and table db = DAL('sqlite://storage.sqlite') db.define_table('person', Field('name', requires=IS_NOT_EMPTY())) # define action def index(request): vars = wrapper.extract_vars(request.arguments) form = SQLFORM(db.person) if form.accepts(vars): message = 'hello %s' % form.vars.name else: message = 'hello anonymous' people = db(db.person).select() now = cache.ram('time', lambda: time.ctime(), 10) return locals() class MainHandler(tornado.web.RequestHandler): @wrapper(view='templates/index.html', dbs=[db]) def get(self):
def __init__(self, uri=config.uri, migrate=False): self.db = DAL(uri, migrate=migrate, folder=config.dbdir) # must define these here because need to use the db instance self.groups = self.db.define_table('groups', Field('id', 'integer'), Field('name', 'string')) self.users = self.db.define_table('users', Field('id', 'integer'), Field('user', 'string'), Field('passwd', 'string'), Field('email', 'string'), Field('new_shared_jobs', 'integer'), Field('priority', 'integer'), Field('gid', self.db.groups, ondelete="SET NULL")) self.user_meta = self.db.define_table('user_meta', Field('id', 'integer'), Field('uid', self.db.users), Field('new_shared_jobs', 'integer'), Field('theme', 'string')) self.apps = self.db.define_table('apps', Field('id', 'integer'), Field('name', 'string'), Field('description', 'string'), Field('category', 'string'), Field('language', 'string'), Field('input_format', 'string'), Field('command', 'string'), Field('assets', 'string'), Field('preprocess', 'string'), Field('postprocess', 'string')) self.app_user = self.db.define_table('app_user', Field('id', 'integer'), Field('appid', 'integer'), Field('uid', 'integer')) self.jobs = self.db.define_table('jobs', Field('id', 'integer'), Field('uid', self.db.users), Field('app', 'string'), Field('cid', 'string'), Field('gid', self.db.groups), Field('command', 'string'), Field('state', 'string'), Field('time_submit', 'string'), Field('walltime', 'string'), Field('description', 'string'), Field('np', 'integer'), Field('priority', 'integer'), Field('starred', 'string'), Field('shared', 'string')) self.plots = self.db.define_table('plots', Field('id', 'integer'), # need to turn on unique in the future, but will cause migration probs for old DBs # this is needed for running "spc update" b/c primary keys are not specified in spc.json Field('appid', self.db.apps), # unique=True), Field('ptype', 'string'), Field('title', 'string'), Field('options', 'string')) self.datasource = self.db.define_table('datasource', Field('id', 'integer'), Field('label', 'string'), # unique=True), Field('pltid', self.db.plots), Field('filename', 'string'), Field('cols', 'string'), Field('line_range', 'string'), Field('data_def', 'string')) self.aws_creds = self.db.define_table('aws_creds', Field('id', 'integer'), Field('key', 'string'), Field('secret', 'string'), Field('account_id', 'string'), Field('uid', self.db.users)) self.aws_instances = self.db.define_table('aws_instances', Field('id', 'integer'), Field('region', 'string'), Field('instance', 'string'), Field('itype', 'string'), Field('rate', 'double'), Field('uid', self.db.users)) self.disciplines = self.db.define_table('disciplines', Field('name'))
#!/usr/bin/env python import threading, time, os import config from gluino import DAL, Field import subprocess, signal #inspired from: #http://taher-zadeh.com/a-simple-and-dirty-batch-job-scheduler-daemon-in-python/ db = DAL(config.uri, auto_import=False, migrate=False, folder=config.dbdir) apps = db.define_table('apps', Field('id','integer'), Field('name','string'), Field('description','string'), Field('category','string'), Field('language','string'), Field('input_format','string'), Field('command','string')) jobs = db.define_table('jobs', Field('id','integer'), Field('user','string'), Field('app','string'), Field('cid','string'), Field('state','string'), Field('time_submit','string'), Field('description','string'), Field('priority','integer'), Field('np','integer')) class scheduler(object): """simple single process scheduler""" def __init__(self):
from wsgiref.util import setup_testing_defaults from wsgiref.simple_server import make_server from gluino import wrapper, DAL, Field, SQLFORM, cache, IS_NOT_EMPTY import time import cgi import traceback # configure the gluino wrapper wrapper.debug = True # create database and table db = DAL("sqlite://storage.sqlite") db.define_table("person", Field("name", requires=IS_NOT_EMPTY())) # define action @wrapper(view="templates/index.html", dbs=[db]) def index(environ, vars): vars = wrapper.extract_vars(vars) form = SQLFORM(db.person) if form.accepts(vars): message = "hello %s" % form.vars.name else: message = "hello anonymous" people = db(db.person).select() now = cache.ram("time", lambda: time.ctime(), 10) return locals() # A minimalist example dispatcher # This is very naive ... bit gives the idea...
from gluino import DAL, Field import config #db = DAL(config.uri, auto_import=True, migrate=False, folder=config.dbdir) db = DAL(config.uri, migrate=False, folder=config.dbdir) users = db.define_table('users', Field('id', 'integer'), Field('user', 'string'), Field('passwd', 'string'), Field('email', 'string'), Field('priority', 'integer')) # this is also defined in scheduler.py # need to fix in the future apps = db.define_table('apps', Field('id', 'integer'), Field('name', 'string'), Field('description', 'string'), Field('category', 'string'), Field('language', 'string'), Field('input_format', 'string'), Field('command', 'string'), Field('preprocess', 'string'), Field('postprocess', 'string'), Field('uid', 'integer')) # this is also defined in scheduler.py # need to fix in the future jobs = db.define_table('jobs', Field('id', 'integer'), Field('user', 'string'), Field('app', 'string'), Field('cid', 'string'), Field('state', 'string'), Field('time_submit', 'string'), Field('description', 'string'), Field('np', 'integer'), Field('priority', 'integer'), Field('shared', 'string')) plots = db.define_table('plots', Field('id', 'integer'), Field('appid', db.apps), Field('ptype', 'string'), Field('title', 'string'), Field('options', 'string'),
from bottle import run, route, request, get, post, static_file, redirect from gluino import wrapper, DAL, Field, SQLFORM, cache, IS_NOT_EMPTY import time # configure the gluino wrapper wrapper.debug = True wrapper.redirect = lambda status,url: redirect(url) # create database and table db=DAL('sqlite://storage.sqlite') db.define_table('person',Field('name',requires=IS_NOT_EMPTY())) # define action @get('/index') @post('/index') @wrapper(view='templates/index.html',dbs=[db]) def index(): vars = wrapper.extract_vars(request.forms) form = SQLFORM(db.person) if form.accepts(vars): message = 'hello %s' % form.vars.name else: message = 'hello anonymous' people = db(db.person).select() now = cache.ram('time',lambda:time.ctime(),10) return locals() # handle static files @route('/static/<filename>') def server_static(filename): return static_file(filename, root='static')
def qstat(self): """return the number of jobs in a queued 'Q' state""" db = DAL(config.uri, auto_import=True, migrate=False, folder=config.dbdir) return db(db.jobs.state==STATE_QUEUED).count() db.close()