def new_app_api(): ''' for creating new apps ''' r = rediscli() job_queue = schema.MonacoJobQueue(r) monaco = schema.Monaco() monaco.refresh(r) if request.form['name'] in monaco.app_ids_by_service: abort(400) job = { 'command': 'new', } for k in schema.App.HASH_KEYS: if k in request.form: job[k] = request.form[k] if not 'persist' in request.form: job['persist'] = False else: job['persist'] = True if not 'slavelb' in request.form: job['slavelb'] = False else: job['slavelb'] = True jid = job_queue.pushback_job(job) if not jid: # just retry in app abort(503) return jsonify(jid=jid)
def master_latency(): ''' This endpoint sends a ping job to the master, returning runtime info/liveness If the request is a POST, this will also push the latency to graphite ''' r = rediscli() wait = 60 # 60s of waiting for job_queue to empty job_queue = schema.MonacoJobQueue(r) job = {'command': 'ping'} while not job_queue.empty: time.sleep(1) wait -= 1 if wait == 0: return make_response(('Job queue not empty', 500)) jid = job_queue.pushback_job(job) start_time = time.time() if not jid: # couldn't get job in queue? return make_response(('Failed to add job', 500)) status = job_queue.status(jid, r) wait = 60 # 60s of waiting for master to ping while status['status'] != 'finished': if time.time() > start_time + wait: return make_response(('Timeout waiting for ping', 500)) time.sleep(0.1) status = job_queue.status(jid, r) end_time = time.time() job_queue.delete_job(jid, r) return jsonify({ 'start': start_time, 'computed_duration': end_time - start_time, 'timestamp': status['timestamp'], 'output': status['output'] })
def new_proxy_api(): ''' for creating new proxies ''' r = rediscli() job_queue = schema.MonacoJobQueue(r) monaco = schema.Monaco() monaco.refresh(r) if request.form['name'] in monaco.twem_ids_by_name: abort(400) job = { 'command': 'new_proxy', } for k in schema.MonacoTwem.HASH_KEYS: if k in request.form: job[k] = request.form[k] job['servers'] = [] for app_id in request.values.getlist('servers'): if app_id in monaco.app_ids: job['servers'].append(app_id) else: abort(400) job['extservers'] = [] ipport = re.compile( '^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}):([0-9]{4,5})$') serverport = re.compile('^([a-zA-Z0-9_-]*):([0-9]{4,5})$') for extserver in request.values.getlist('extservers'): if ipport.match(extserver): job['extservers'].append(extserver) elif serverport.match(extserver): job['extservers'].append(extserver) else: abort(400) job['hash'] = 'murmur' jid = job_queue.pushback_job(job) return jsonify(jid=jid)
def migrate_app(): ''' api endpoint to migrate an app ''' r = rediscli() job_queue = schema.MonacoJobQueue(r) job = { 'command': 'migrate', 'app_id': request.form['app_id'], 'node_id_from': request.form['node_id_from'], 'node_id_to': request.form['node_id_to'], } jid = job_queue.pushback_job(job) return jsonify(jid=jid)
def job_api(jid): ''' REST api for getting status, and clearing variables from job ''' try: r = rediscli() job_queue = schema.MonacoJobQueue(r) if request.method == 'GET': job = job_queue.status(jid) if job['status'] == 'finished': # if the job completed, clear the associated redis structs # logs are maintained on the Monaco Nodes, no loss of data job_queue.delete_job(jid) return jsonify(job) if request.method == 'DELETE': job_queue.delete_job(jid) return 'OK' except Exception: abort(404) abort(400)
def jobs_api(): ''' returns top-level info about jobs in json format ''' r = rediscli() job_queue = schema.MonacoJobQueue(r) return jsonify({'pending_jobs': job_queue.pending_jobs()})
def app_api(app_id): ''' App API: GET: 200 - gets info about app in json format 404 - app_id does not exist 403 - you aint allowed HEAD: 200 - app_id exists 404 - app_id does not exist POST: 200 - sent update command to master 400 - app_id does not exist 403 - you aint allowed DELETE: 200 - sent delete command to master 404 - app_id does not exist 403 - you aint allowed ''' r = rediscli() job_queue = schema.MonacoJobQueue(r) monaco = schema.Monaco() monaco.refresh(r) app_id = str(app_id) if request.method == 'HEAD': if not app_id in monaco.app_ids: abort(404) return 'OK' if request.method == 'GET': if not app_id in monaco.app_ids: abort(404) dbapp = schema.App(app_id=app_id) dbapp.refresh(r) app_info = { 'app_id': dbapp.app_id, 'port': dbapp.port, 'nodes': [], 'unused_nodes': [], } for k in dbapp.HASH_KEYS: if hasattr(dbapp, k): app_info[k] = getattr(dbapp, k) for node_id, role in dbapp.nodes.iteritems(): node = schema.MonacoNode(node_id=node_id) node.refresh(r) app_info['nodes'].append({ 'host': node.hostname, 'node_id': node_id, 'role': role }) app_info['unused_nodes'] = [ node_id for node_id in monaco.node_ids if not node_id in dbapp.nodes ] return jsonify(app_info) if request.method == 'POST': if app_id in monaco.app_ids: dbapp = schema.App(app_id=app_id) dbapp.refresh(r) if request.form['name'] != monaco.service_by_app_id[app_id]: monaco.rename_app(app_id, request.form['name'], r) job = { 'command': 'update', 'app_id': app_id, } for k in schema.App.HASH_KEYS: if k in request.form: job[k] = request.form[k] if 'persist' in job: job['persist'] = True else: job['persist'] = False if 'slavelb' in job: job['slavelb'] = True else: job['slavelb'] = False jid = job_queue.pushback_job(job) return jsonify(jid=jid) else: # can't create with an app_id pre-specified. abort(400) if request.method == 'DELETE': if not app_id in monaco.app_ids: abort(404) dbapp = schema.App(app_id=app_id) dbapp.refresh(r) job = { 'command': 'delete', 'app_id': app_id, } jid = job_queue.pushback_job(job) return jsonify(jid=jid)
def proxy_api(twem_id): ''' Twemproxy API: GET: 200 - gets info about twem in json format 404 - twem_id does not exist 403 - you aint allowed HEAD: 200 - twem_id exists 404 - twem_id does not exist POST: 200 - sent update command to master 400 - twem_id does not exist 403 - you aint allowed DELETE: 200 - sent delete command to master 404 - twem_id does not exist 403 - you aint allowed ''' r = rediscli() job_queue = schema.MonacoJobQueue(r) monaco = schema.Monaco() monaco.refresh(r) twem_id = str(twem_id) if request.method == 'HEAD': if not twem_id in monaco.twem_ids: abort(404) return 'OK' if request.method == 'GET': if not twem_id in monaco.twem_ids: abort(404) twem = schema.MonacoTwem(twem_id=twem_id) twem.refresh(r) data = {} for key in schema.MonacoTwem.HASH_KEYS: if hasattr(twem, key): data[key] = getattr(twem, key) data['servers'] = twem.servers data['extservers'] = twem.extservers return jsonify(data) if request.method == 'POST': if twem_id in monaco.twem_ids: twem = schema.MonacoTwem(twem_id=twem_id) twem.refresh(r) job = { 'command': 'update_proxy', 'twem_id': twem_id, } for key in schema.MonacoTwem.HASH_KEYS: if key in request.form: job[key] = request.form[key] if 'servers' in request.form: job['servers'] = [] for app_id in request.values.getlist('servers'): if app_id in monaco.app_ids: job['servers'].append(app_id) else: abort(400) if 'extservers' in request.form: job['extservers'] = [] ipport = re.compile( '^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}):([0-9]{4,5})$' ) serverport = re.compile('^([a-zA-Z0-9-_]*):([0-9]{4,5})$') for extserver in request.values.getlist('extservers'): if ipport.match(extserver): job['extservers'].append(extserver) elif serverport.match(extserver): job['extservers'].append(extserver) else: abort(400) jid = job_queue.pushback_job(job) return jsonify(jid=jid) else: # can't create. use POST:/api/proxy abort(400) if request.method == 'DELETE': if not twem_id in monaco.twem_ids: abort(404) twem = schema.MonacoTwem(twem_id=twem_id) twem.refresh(r) job = { 'command': 'delete_proxy', 'twem_id': twem_id, } jid = job_queue.pushback_job(job) return jsonify(jid=jid) return 'OK'