#!/usr/local/bin/python import sqlite3, os from bottle import route, run, redirect, template, static_file, request database = 'cluster.sqlite' main_tpl = 'tpl/main.tpl' add_node_tpl = 'tpl/add_node.tpl' add_task_tpl = 'tpl/add_task.tpl' edit_node_tpl = 'tpl/edit_node.tpl' delete_node_tpl = 'tpl/delete_node.tpl' delete_task_tpl = 'tpl/delete_task.tpl' view_revision_tpl = 'tpl/view_revision.tpl' pre_tpl = 'tpl/pre.tpl' default = 'menu.ipxe' @route('/static/:path#.+#', name='static') def static(path): return static_file(path, root='static') @route('/') def main(): return redirect('/static/%s' %default) @route('/admin') def ipxe(): if os.path.exists(database): conn = sqlite3.connect(database) c = conn.cursor() c.execute("SELECT * FROM nodes") result_nodes = c.fetchall() c.execute("SELECT * FROM tasks") result_tasks = c.fetchall() c.close output = template(main_tpl,rows_nodes=result_nodes,rows_tasks=result_tasks) return output else: conn = sqlite3.connect(database) conn.execute("CREATE TABLE nodes (id INTEGER PRIMARY KEY, host char(254) NOT NULL, mac char(20) NOT NULL, ip char(20) NOT NULL, boot char(50) NOT NULL, status char(50))") conn.execute("CREATE TABLE tasks (id INTEGER PRIMARY KEY, revision char(20) NOT NULL, host char(254), status char(20))") conn.commit() return redirect('/admin') @route('/admin/delete_node/:id', method='GET') def delete(id): if request.GET.get('delete','').strip(): conn = sqlite3.connect(database) c = conn.cursor() c.execute("DELETE FROM nodes WHERE id LIKE '%s'" %id) conn.commit() return redirect('/admin') else: conn = sqlite3.connect(database) c = conn.cursor() c.execute("SELECT host, mac, ip FROM nodes WHERE id=?",(id,)) current_data = c.fetchone() c.close return template(delete_node_tpl,id=id,host=current_data[0],mac=current_data[1],ip=current_data[2]) @route('/admin/edit_node/:id', method='GET') def edit(id): if request.GET.get('save','').strip(): host = request.GET.get('host','').strip() mac = request.GET.get('mac','').strip() ip = request.GET.get('ip','').strip() boot = request.GET.get('boot','').strip() conn = sqlite3.connect(database) c = conn.cursor() c.execute("UPDATE nodes SET host = ?, mac = ?, ip = ?, boot = ? WHERE id LIKE ?", (host,mac,ip,boot,id)) conn.commit() return redirect('/admin') else: conn = sqlite3.connect(database) c = conn.cursor() c.execute("SELECT host,mac,ip,boot FROM nodes WHERE id LIKE ?",(str(id))) current_data = c.fetchone() c.close return template(edit_node_tpl,old=current_data,id=id) @route('/admin/change_boot/:host/:new', method='GET') def change_boot(host,new): conn = sqlite3.connect(database) c = conn.cursor() c.execute("UPDATE nodes SET boot = ? WHERE host LIKE ?", (new,host)) conn.commit() return redirect('/admin') @route('/admin/add_node', method='GET') def add(): if request.GET.get('add','').strip(): host = request.GET.get('host','').strip() mac = request.GET.get('mac','').strip() ip = request.GET.get('ip','').strip() boot = request.GET.get('boot','').strip() status = "?" conn = sqlite3.connect(database) c = conn.cursor() c.execute("INSERT INTO nodes (host, mac, ip, boot, status) VALUES (?,?,?,?,?)", (host,mac,ip,boot,status)) conn.commit() c.close() return redirect('/admin') else: return template(add_node_tpl) @route('/admin/add_task', method='GET') def add(): if request.GET.get('add','').strip(): revision = request.GET.get('revision','').strip() conn = sqlite3.connect(database) c = conn.cursor() c.execute("INSERT INTO tasks (revision,status) VALUES (?,?)", (revision,"new",)) conn.commit() c.close() return redirect('/admin') else: return template(add_task_tpl) @route('/admin/delete_task/:id', method='GET') def delete(id): if request.GET.get('delete','').strip(): conn = sqlite3.connect(database) c = conn.cursor() c.execute("DELETE FROM tasks WHERE id LIKE '%s'" %id) conn.commit() return redirect('/admin') else: conn = sqlite3.connect(database) c = conn.cursor() c.execute("SELECT revision, host, status FROM tasks WHERE id=?",(id,)) current_data = c.fetchone() c.close return template(delete_task_tpl,id=id,revision=current_data[0],host=current_data[1],status=current_data[2]) @route('/admin/change_task_status/:revision/:new_status', method='GET') def change_task_status(revision,new_status): conn = sqlite3.connect(database) c = conn.cursor() c.execute("UPDATE tasks SET status = ? WHERE revision LIKE ?", (new_status,revision)) conn.commit() return redirect('/admin') @route('/admin/change_node_status/:hostname/:new_status', method='GET') def change_node_status(hostname,new_status): conn = sqlite3.connect(database) c = conn.cursor() c.execute("UPDATE nodes SET status = ? WHERE host LIKE ?", (new_status,hostname)) conn.commit() return redirect('/admin') @route('/admin/take_task/:mac', method='GET') def take_task(mac): conn = sqlite3.connect(database) c = conn.cursor() c.execute("SELECT host from nodes WHERE mac LIKE '%s'" %mac) result = c.fetchone() host = result[0] c.execute("SELECT revision from tasks WHERE status LIKE 'new' ORDER by ID LIMIT 1") result = c.fetchone() revision = result[0] c.execute("UPDATE tasks SET host = ? WHERE revision LIKE ?", (host,revision)) boot = "wait.ipxe" c.execute("UPDATE nodes SET boot = ? WHERE host LIKE ?", (boot,host)) conn.commit() create_env = '/cluster/new_task.sh '+revision+' '+host+' &' os.system(create_env) c.close return redirect('/static/wait.ipxe') @route('/menu/:mac', method='GET') def static(mac): conn = sqlite3.connect(database) c = conn.cursor() c.execute("SELECT boot FROM nodes WHERE mac LIKE '%s'" %mac) result = c.fetchone() c.close return redirect('/static/%s' %result[0]) @route('/log/rev/:revision/:lines', method='GET') def log(revision,lines): path = '/cluster/log/%s/log' %revision with open(path, "r") as f: content = "".join(f.readlines()[-int(lines):]) return template(pre_tpl,content=content) @route('/admin/view_revision/:id', method='GET') def static(id): conn = sqlite3.connect(database) c = conn.cursor() c.execute("SELECT revision FROM tasks WHERE id=?",(id,)) current_data = c.fetchone() c.close return template(view_revision_tpl,revision=current_data[0]) run(host='0.0.0.0', port=8080, debug=True)