diff --git a/app.py b/app.py index b8fbc3e..15509ac 100644 --- a/app.py +++ b/app.py @@ -37,34 +37,52 @@ def list_vms(): @app.route("/vm/") def vm_details(vmid): - vm = get_vm(proxmox, vmid) - vm['vmid'] = vmid - vm['config'] = get_vm_config(proxmox, vmid) - vm['disks'] = get_vm_disks(proxmox, vmid, config=vm['config']) - vm['interfaces'] = get_vm_interfaces( - proxmox, vm['vmid'], config=vm['config']) - return render_template('vm_details.html', username='com6056', vm=vm) + if int(vmid) in get_user_allowed_vms(proxmox, user): + vm = get_vm(proxmox, vmid) + vm['vmid'] = vmid + vm['config'] = get_vm_config(proxmox, vmid) + vm['disks'] = get_vm_disks(proxmox, vmid, config=vm['config']) + vm['interfaces'] = get_vm_interfaces( + proxmox, vm['vmid'], config=vm['config']) + return render_template('vm_details.html', username='com6056', vm=vm) + else: + return '', 403 -@app.route("/vm_status/", methods=['POST']) -def vm_status(vmid): - action = request.form['action'] - change_vm_status(proxmox, vmid, action) - return redirect("/proxstar/vm/{}".format(vmid)) +@app.route("/vm//power/", methods=['POST']) +def vm_power(vmid, action): + if int(vmid) in get_user_allowed_vms(proxmox, user): + change_vm_power(proxmox, vmid, action) + return '', 200 + else: + return '', 403 -@app.route("/create", methods=['GET', 'POST']) +@app.route("/vm//delete", methods=['POST']) +def delete(vmid): + if int(vmid) in get_user_allowed_vms(proxmox, user): + vmname = get_vm_config(proxmox, vmid)['name'] + delete_vm(proxmox, starrs, vmid) + delete_starrs(starrs, vmname) + return '', 200 + else: + return '', 403 + + +@app.route("/vm/create", methods=['GET', 'POST']) def create(): if request.method == 'GET': usage = get_user_usage(proxmox, 'proxstar') limits = get_user_usage_limits(user) full_limits = check_user_limit(proxmox, user, usage, limits) + percents = get_user_usage_percent(proxmox, usage, limits) return render_template( 'create.html', username='com6056', usage=usage, limits=limits, - full_limits=full_limits) + full_limits=full_limits, + percents=percents) elif request.method == 'POST': name = request.form['name'] cores = request.form['cores'] @@ -82,28 +100,10 @@ def create(): return redirect("/proxstar/vm/{}".format(vmid)) -@app.route("/delete", methods=['POST']) -def delete(): - vmid = request.form['delete'] - vmname = get_vm_config(proxmox, vmid)['name'] - return render_template( - 'confirm_delete.html', username='com6056', vmid=vmid, vmname=vmname) - - -@app.route("/confirm_delete", methods=['POST']) -def confirm_delete(): - vmid = request.form['delete'] - vmname = get_vm_config(proxmox, vmid)['name'] - delete_vm(proxmox, starrs, vmid) - delete_starrs(starrs, vmname) - time.sleep(3) - return redirect("/proxstar") - - @app.route('/novnc/') def send_novnc(path): return send_from_directory('static/novnc-pve/novnc', path) if __name__ == "__main__": - app.run() + app.run(debug=True) diff --git a/proxmox.py b/proxmox.py index 171556e..7f72a23 100644 --- a/proxmox.py +++ b/proxmox.py @@ -16,6 +16,13 @@ def get_vms_for_user(proxmox, user): return proxmox.pools(user).get()['members'] +def get_user_allowed_vms(proxmox, user): + allowed_vms = [] + for vm in get_vms_for_user(proxmox, user): + allowed_vms.append(vm['vmid']) + return allowed_vms + + def get_node_least_mem(proxmox): nodes = proxmox.nodes.get() sorted_nodes = sorted(nodes, key=lambda x: x['mem']) @@ -115,11 +122,12 @@ def get_user_usage(proxmox, user): vms = get_vms_for_user(proxmox, user) for vm in vms: config = get_vm_config(proxmox, vm['vmid']) - if vm['status'] == 'running' or vm['status'] == 'paused': - usage['cpu'] += int(config['cores'] * config.get('sockets', 1)) - usage['mem'] += (int(config['memory']) // 1024) - for disk in get_vm_disks(proxmox, vm['vmid'], config): - usage['disk'] += int(disk[1][:-1]) + if 'status' in vm: + if vm['status'] == 'running' or vm['status'] == 'paused': + usage['cpu'] += int(config['cores'] * config.get('sockets', 1)) + usage['mem'] += (int(config['memory']) // 1024) + for disk in get_vm_disks(proxmox, vm['vmid'], config): + usage['disk'] += int(disk[1][:-1]) return usage @@ -149,6 +157,18 @@ def check_user_usage(proxmox, user, vm_cpu, vm_mem, vm_disk): return 'Exceeds disk limit!' +def get_user_usage_percent(proxmox, usage=None, limits=None): + percents = dict() + if not usage: + usage = get_user_usage(proxmox, user) + if not limits: + limits = get_user_usage_limits(user) + percents['cpu'] = round(int(usage['cpu']) / int(limits['cpu']) * 100) + percents['mem'] = round(int(usage['mem']) / int(limits['mem']) * 100) + percents['disk'] = round(int(usage['disk']) / int(limits['disk']) * 100) + return percents + + def create_vm(proxmox, starrs, user, name, cores, memory, disk): node = proxmox.nodes(get_node_least_mem(proxmox)) vmid = get_free_vmid(proxmox) @@ -171,7 +191,7 @@ def delete_vm(proxmox, starrs, vmid): node.qemu(vmid).delete() -def change_vm_status(proxmox, vmid, action): +def change_vm_power(proxmox, vmid, action): node = proxmox.nodes(get_vm_node(proxmox, vmid)) if action == 'start': node.qemu(vmid).status.start.post() diff --git a/static/css/circle.css b/static/css/circle.css new file mode 100644 index 0000000..dafa67a --- /dev/null +++ b/static/css/circle.css @@ -0,0 +1,1065 @@ +.rect-auto, +.c100.p51 .slice, +.c100.p52 .slice, +.c100.p53 .slice, +.c100.p54 .slice, +.c100.p55 .slice, +.c100.p56 .slice, +.c100.p57 .slice, +.c100.p58 .slice, +.c100.p59 .slice, +.c100.p60 .slice, +.c100.p61 .slice, +.c100.p62 .slice, +.c100.p63 .slice, +.c100.p64 .slice, +.c100.p65 .slice, +.c100.p66 .slice, +.c100.p67 .slice, +.c100.p68 .slice, +.c100.p69 .slice, +.c100.p70 .slice, +.c100.p71 .slice, +.c100.p72 .slice, +.c100.p73 .slice, +.c100.p74 .slice, +.c100.p75 .slice, +.c100.p76 .slice, +.c100.p77 .slice, +.c100.p78 .slice, +.c100.p79 .slice, +.c100.p80 .slice, +.c100.p81 .slice, +.c100.p82 .slice, +.c100.p83 .slice, +.c100.p84 .slice, +.c100.p85 .slice, +.c100.p86 .slice, +.c100.p87 .slice, +.c100.p88 .slice, +.c100.p89 .slice, +.c100.p90 .slice, +.c100.p91 .slice, +.c100.p92 .slice, +.c100.p93 .slice, +.c100.p94 .slice, +.c100.p95 .slice, +.c100.p96 .slice, +.c100.p97 .slice, +.c100.p98 .slice, +.c100.p99 .slice, +.c100.p100 .slice { + clip: rect(auto, auto, auto, auto); +} +.pie, +.c100 .bar, +.c100.p51 .fill, +.c100.p52 .fill, +.c100.p53 .fill, +.c100.p54 .fill, +.c100.p55 .fill, +.c100.p56 .fill, +.c100.p57 .fill, +.c100.p58 .fill, +.c100.p59 .fill, +.c100.p60 .fill, +.c100.p61 .fill, +.c100.p62 .fill, +.c100.p63 .fill, +.c100.p64 .fill, +.c100.p65 .fill, +.c100.p66 .fill, +.c100.p67 .fill, +.c100.p68 .fill, +.c100.p69 .fill, +.c100.p70 .fill, +.c100.p71 .fill, +.c100.p72 .fill, +.c100.p73 .fill, +.c100.p74 .fill, +.c100.p75 .fill, +.c100.p76 .fill, +.c100.p77 .fill, +.c100.p78 .fill, +.c100.p79 .fill, +.c100.p80 .fill, +.c100.p81 .fill, +.c100.p82 .fill, +.c100.p83 .fill, +.c100.p84 .fill, +.c100.p85 .fill, +.c100.p86 .fill, +.c100.p87 .fill, +.c100.p88 .fill, +.c100.p89 .fill, +.c100.p90 .fill, +.c100.p91 .fill, +.c100.p92 .fill, +.c100.p93 .fill, +.c100.p94 .fill, +.c100.p95 .fill, +.c100.p96 .fill, +.c100.p97 .fill, +.c100.p98 .fill, +.c100.p99 .fill, +.c100.p100 .fill { + position: absolute; + border: 0.08em solid #307bbb; + width: 0.84em; + height: 0.84em; + clip: rect(0em, 0.5em, 1em, 0em); + border-radius: 50%; + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -o-transform: rotate(0deg); + transform: rotate(0deg); +} +.pie-fill, +.c100.p51 .bar:after, +.c100.p51 .fill, +.c100.p52 .bar:after, +.c100.p52 .fill, +.c100.p53 .bar:after, +.c100.p53 .fill, +.c100.p54 .bar:after, +.c100.p54 .fill, +.c100.p55 .bar:after, +.c100.p55 .fill, +.c100.p56 .bar:after, +.c100.p56 .fill, +.c100.p57 .bar:after, +.c100.p57 .fill, +.c100.p58 .bar:after, +.c100.p58 .fill, +.c100.p59 .bar:after, +.c100.p59 .fill, +.c100.p60 .bar:after, +.c100.p60 .fill, +.c100.p61 .bar:after, +.c100.p61 .fill, +.c100.p62 .bar:after, +.c100.p62 .fill, +.c100.p63 .bar:after, +.c100.p63 .fill, +.c100.p64 .bar:after, +.c100.p64 .fill, +.c100.p65 .bar:after, +.c100.p65 .fill, +.c100.p66 .bar:after, +.c100.p66 .fill, +.c100.p67 .bar:after, +.c100.p67 .fill, +.c100.p68 .bar:after, +.c100.p68 .fill, +.c100.p69 .bar:after, +.c100.p69 .fill, +.c100.p70 .bar:after, +.c100.p70 .fill, +.c100.p71 .bar:after, +.c100.p71 .fill, +.c100.p72 .bar:after, +.c100.p72 .fill, +.c100.p73 .bar:after, +.c100.p73 .fill, +.c100.p74 .bar:after, +.c100.p74 .fill, +.c100.p75 .bar:after, +.c100.p75 .fill, +.c100.p76 .bar:after, +.c100.p76 .fill, +.c100.p77 .bar:after, +.c100.p77 .fill, +.c100.p78 .bar:after, +.c100.p78 .fill, +.c100.p79 .bar:after, +.c100.p79 .fill, +.c100.p80 .bar:after, +.c100.p80 .fill, +.c100.p81 .bar:after, +.c100.p81 .fill, +.c100.p82 .bar:after, +.c100.p82 .fill, +.c100.p83 .bar:after, +.c100.p83 .fill, +.c100.p84 .bar:after, +.c100.p84 .fill, +.c100.p85 .bar:after, +.c100.p85 .fill, +.c100.p86 .bar:after, +.c100.p86 .fill, +.c100.p87 .bar:after, +.c100.p87 .fill, +.c100.p88 .bar:after, +.c100.p88 .fill, +.c100.p89 .bar:after, +.c100.p89 .fill, +.c100.p90 .bar:after, +.c100.p90 .fill, +.c100.p91 .bar:after, +.c100.p91 .fill, +.c100.p92 .bar:after, +.c100.p92 .fill, +.c100.p93 .bar:after, +.c100.p93 .fill, +.c100.p94 .bar:after, +.c100.p94 .fill, +.c100.p95 .bar:after, +.c100.p95 .fill, +.c100.p96 .bar:after, +.c100.p96 .fill, +.c100.p97 .bar:after, +.c100.p97 .fill, +.c100.p98 .bar:after, +.c100.p98 .fill, +.c100.p99 .bar:after, +.c100.p99 .fill, +.c100.p100 .bar:after, +.c100.p100 .fill { + -webkit-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -o-transform: rotate(180deg); + transform: rotate(180deg); +} +.c100 { + position: relative; + font-size: 120px; + width: 1em; + height: 1em; + border-radius: 50%; + float: none; + margin: 0 0.1em 0.1em 0; + background-color: #cccccc; +} +.c100 *, +.c100 *:before, +.c100 *:after { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +.c100.center { + float: none; + margin: 0 auto; +} +.c100.big { + font-size: 180px; +} +.c100.small { + font-size: 60px; +} +.c100 > span { + position: absolute; + width: 100%; + z-index: 1; + left: 0; + top: 0; + width: 5em; + line-height: 5em; + font-size: 0.2em; + color: #cccccc; + display: block; + text-align: center; + white-space: nowrap; + -webkit-transition-property: all; + -moz-transition-property: all; + -o-transition-property: all; + transition-property: all; + -webkit-transition-duration: 0.2s; + -moz-transition-duration: 0.2s; + -o-transition-duration: 0.2s; + transition-duration: 0.2s; + -webkit-transition-timing-function: ease-out; + -moz-transition-timing-function: ease-out; + -o-transition-timing-function: ease-out; + transition-timing-function: ease-out; +} +.c100:after { + position: absolute; + top: 0.08em; + left: 0.08em; + display: block; + content: " "; + border-radius: 50%; + background-color: #f5f5f5; + width: 0.84em; + height: 0.84em; + -webkit-transition-property: all; + -moz-transition-property: all; + -o-transition-property: all; + transition-property: all; + -webkit-transition-duration: 0.2s; + -moz-transition-duration: 0.2s; + -o-transition-duration: 0.2s; + transition-duration: 0.2s; + -webkit-transition-timing-function: ease-in; + -moz-transition-timing-function: ease-in; + -o-transition-timing-function: ease-in; + transition-timing-function: ease-in; +} +.c100 .slice { + position: absolute; + width: 1em; + height: 1em; + clip: rect(0em, 1em, 1em, 0.5em); +} +.c100.p1 .bar { + -webkit-transform: rotate(3.6deg); + -moz-transform: rotate(3.6deg); + -ms-transform: rotate(3.6deg); + -o-transform: rotate(3.6deg); + transform: rotate(3.6deg); +} +.c100.p2 .bar { + -webkit-transform: rotate(7.2deg); + -moz-transform: rotate(7.2deg); + -ms-transform: rotate(7.2deg); + -o-transform: rotate(7.2deg); + transform: rotate(7.2deg); +} +.c100.p3 .bar { + -webkit-transform: rotate(10.8deg); + -moz-transform: rotate(10.8deg); + -ms-transform: rotate(10.8deg); + -o-transform: rotate(10.8deg); + transform: rotate(10.8deg); +} +.c100.p4 .bar { + -webkit-transform: rotate(14.4deg); + -moz-transform: rotate(14.4deg); + -ms-transform: rotate(14.4deg); + -o-transform: rotate(14.4deg); + transform: rotate(14.4deg); +} +.c100.p5 .bar { + -webkit-transform: rotate(18deg); + -moz-transform: rotate(18deg); + -ms-transform: rotate(18deg); + -o-transform: rotate(18deg); + transform: rotate(18deg); +} +.c100.p6 .bar { + -webkit-transform: rotate(21.6deg); + -moz-transform: rotate(21.6deg); + -ms-transform: rotate(21.6deg); + -o-transform: rotate(21.6deg); + transform: rotate(21.6deg); +} +.c100.p7 .bar { + -webkit-transform: rotate(25.2deg); + -moz-transform: rotate(25.2deg); + -ms-transform: rotate(25.2deg); + -o-transform: rotate(25.2deg); + transform: rotate(25.2deg); +} +.c100.p8 .bar { + -webkit-transform: rotate(28.8deg); + -moz-transform: rotate(28.8deg); + -ms-transform: rotate(28.8deg); + -o-transform: rotate(28.8deg); + transform: rotate(28.8deg); +} +.c100.p9 .bar { + -webkit-transform: rotate(32.4deg); + -moz-transform: rotate(32.4deg); + -ms-transform: rotate(32.4deg); + -o-transform: rotate(32.4deg); + transform: rotate(32.4deg); +} +.c100.p10 .bar { + -webkit-transform: rotate(36deg); + -moz-transform: rotate(36deg); + -ms-transform: rotate(36deg); + -o-transform: rotate(36deg); + transform: rotate(36deg); +} +.c100.p11 .bar { + -webkit-transform: rotate(39.6deg); + -moz-transform: rotate(39.6deg); + -ms-transform: rotate(39.6deg); + -o-transform: rotate(39.6deg); + transform: rotate(39.6deg); +} +.c100.p12 .bar { + -webkit-transform: rotate(43.2deg); + -moz-transform: rotate(43.2deg); + -ms-transform: rotate(43.2deg); + -o-transform: rotate(43.2deg); + transform: rotate(43.2deg); +} +.c100.p13 .bar { + -webkit-transform: rotate(46.800000000000004deg); + -moz-transform: rotate(46.800000000000004deg); + -ms-transform: rotate(46.800000000000004deg); + -o-transform: rotate(46.800000000000004deg); + transform: rotate(46.800000000000004deg); +} +.c100.p14 .bar { + -webkit-transform: rotate(50.4deg); + -moz-transform: rotate(50.4deg); + -ms-transform: rotate(50.4deg); + -o-transform: rotate(50.4deg); + transform: rotate(50.4deg); +} +.c100.p15 .bar { + -webkit-transform: rotate(54deg); + -moz-transform: rotate(54deg); + -ms-transform: rotate(54deg); + -o-transform: rotate(54deg); + transform: rotate(54deg); +} +.c100.p16 .bar { + -webkit-transform: rotate(57.6deg); + -moz-transform: rotate(57.6deg); + -ms-transform: rotate(57.6deg); + -o-transform: rotate(57.6deg); + transform: rotate(57.6deg); +} +.c100.p17 .bar { + -webkit-transform: rotate(61.2deg); + -moz-transform: rotate(61.2deg); + -ms-transform: rotate(61.2deg); + -o-transform: rotate(61.2deg); + transform: rotate(61.2deg); +} +.c100.p18 .bar { + -webkit-transform: rotate(64.8deg); + -moz-transform: rotate(64.8deg); + -ms-transform: rotate(64.8deg); + -o-transform: rotate(64.8deg); + transform: rotate(64.8deg); +} +.c100.p19 .bar { + -webkit-transform: rotate(68.4deg); + -moz-transform: rotate(68.4deg); + -ms-transform: rotate(68.4deg); + -o-transform: rotate(68.4deg); + transform: rotate(68.4deg); +} +.c100.p20 .bar { + -webkit-transform: rotate(72deg); + -moz-transform: rotate(72deg); + -ms-transform: rotate(72deg); + -o-transform: rotate(72deg); + transform: rotate(72deg); +} +.c100.p21 .bar { + -webkit-transform: rotate(75.60000000000001deg); + -moz-transform: rotate(75.60000000000001deg); + -ms-transform: rotate(75.60000000000001deg); + -o-transform: rotate(75.60000000000001deg); + transform: rotate(75.60000000000001deg); +} +.c100.p22 .bar { + -webkit-transform: rotate(79.2deg); + -moz-transform: rotate(79.2deg); + -ms-transform: rotate(79.2deg); + -o-transform: rotate(79.2deg); + transform: rotate(79.2deg); +} +.c100.p23 .bar { + -webkit-transform: rotate(82.8deg); + -moz-transform: rotate(82.8deg); + -ms-transform: rotate(82.8deg); + -o-transform: rotate(82.8deg); + transform: rotate(82.8deg); +} +.c100.p24 .bar { + -webkit-transform: rotate(86.4deg); + -moz-transform: rotate(86.4deg); + -ms-transform: rotate(86.4deg); + -o-transform: rotate(86.4deg); + transform: rotate(86.4deg); +} +.c100.p25 .bar { + -webkit-transform: rotate(90deg); + -moz-transform: rotate(90deg); + -ms-transform: rotate(90deg); + -o-transform: rotate(90deg); + transform: rotate(90deg); +} +.c100.p26 .bar { + -webkit-transform: rotate(93.60000000000001deg); + -moz-transform: rotate(93.60000000000001deg); + -ms-transform: rotate(93.60000000000001deg); + -o-transform: rotate(93.60000000000001deg); + transform: rotate(93.60000000000001deg); +} +.c100.p27 .bar { + -webkit-transform: rotate(97.2deg); + -moz-transform: rotate(97.2deg); + -ms-transform: rotate(97.2deg); + -o-transform: rotate(97.2deg); + transform: rotate(97.2deg); +} +.c100.p28 .bar { + -webkit-transform: rotate(100.8deg); + -moz-transform: rotate(100.8deg); + -ms-transform: rotate(100.8deg); + -o-transform: rotate(100.8deg); + transform: rotate(100.8deg); +} +.c100.p29 .bar { + -webkit-transform: rotate(104.4deg); + -moz-transform: rotate(104.4deg); + -ms-transform: rotate(104.4deg); + -o-transform: rotate(104.4deg); + transform: rotate(104.4deg); +} +.c100.p30 .bar { + -webkit-transform: rotate(108deg); + -moz-transform: rotate(108deg); + -ms-transform: rotate(108deg); + -o-transform: rotate(108deg); + transform: rotate(108deg); +} +.c100.p31 .bar { + -webkit-transform: rotate(111.60000000000001deg); + -moz-transform: rotate(111.60000000000001deg); + -ms-transform: rotate(111.60000000000001deg); + -o-transform: rotate(111.60000000000001deg); + transform: rotate(111.60000000000001deg); +} +.c100.p32 .bar { + -webkit-transform: rotate(115.2deg); + -moz-transform: rotate(115.2deg); + -ms-transform: rotate(115.2deg); + -o-transform: rotate(115.2deg); + transform: rotate(115.2deg); +} +.c100.p33 .bar { + -webkit-transform: rotate(118.8deg); + -moz-transform: rotate(118.8deg); + -ms-transform: rotate(118.8deg); + -o-transform: rotate(118.8deg); + transform: rotate(118.8deg); +} +.c100.p34 .bar { + -webkit-transform: rotate(122.4deg); + -moz-transform: rotate(122.4deg); + -ms-transform: rotate(122.4deg); + -o-transform: rotate(122.4deg); + transform: rotate(122.4deg); +} +.c100.p35 .bar { + -webkit-transform: rotate(126deg); + -moz-transform: rotate(126deg); + -ms-transform: rotate(126deg); + -o-transform: rotate(126deg); + transform: rotate(126deg); +} +.c100.p36 .bar { + -webkit-transform: rotate(129.6deg); + -moz-transform: rotate(129.6deg); + -ms-transform: rotate(129.6deg); + -o-transform: rotate(129.6deg); + transform: rotate(129.6deg); +} +.c100.p37 .bar { + -webkit-transform: rotate(133.20000000000002deg); + -moz-transform: rotate(133.20000000000002deg); + -ms-transform: rotate(133.20000000000002deg); + -o-transform: rotate(133.20000000000002deg); + transform: rotate(133.20000000000002deg); +} +.c100.p38 .bar { + -webkit-transform: rotate(136.8deg); + -moz-transform: rotate(136.8deg); + -ms-transform: rotate(136.8deg); + -o-transform: rotate(136.8deg); + transform: rotate(136.8deg); +} +.c100.p39 .bar { + -webkit-transform: rotate(140.4deg); + -moz-transform: rotate(140.4deg); + -ms-transform: rotate(140.4deg); + -o-transform: rotate(140.4deg); + transform: rotate(140.4deg); +} +.c100.p40 .bar { + -webkit-transform: rotate(144deg); + -moz-transform: rotate(144deg); + -ms-transform: rotate(144deg); + -o-transform: rotate(144deg); + transform: rotate(144deg); +} +.c100.p41 .bar { + -webkit-transform: rotate(147.6deg); + -moz-transform: rotate(147.6deg); + -ms-transform: rotate(147.6deg); + -o-transform: rotate(147.6deg); + transform: rotate(147.6deg); +} +.c100.p42 .bar { + -webkit-transform: rotate(151.20000000000002deg); + -moz-transform: rotate(151.20000000000002deg); + -ms-transform: rotate(151.20000000000002deg); + -o-transform: rotate(151.20000000000002deg); + transform: rotate(151.20000000000002deg); +} +.c100.p43 .bar { + -webkit-transform: rotate(154.8deg); + -moz-transform: rotate(154.8deg); + -ms-transform: rotate(154.8deg); + -o-transform: rotate(154.8deg); + transform: rotate(154.8deg); +} +.c100.p44 .bar { + -webkit-transform: rotate(158.4deg); + -moz-transform: rotate(158.4deg); + -ms-transform: rotate(158.4deg); + -o-transform: rotate(158.4deg); + transform: rotate(158.4deg); +} +.c100.p45 .bar { + -webkit-transform: rotate(162deg); + -moz-transform: rotate(162deg); + -ms-transform: rotate(162deg); + -o-transform: rotate(162deg); + transform: rotate(162deg); +} +.c100.p46 .bar { + -webkit-transform: rotate(165.6deg); + -moz-transform: rotate(165.6deg); + -ms-transform: rotate(165.6deg); + -o-transform: rotate(165.6deg); + transform: rotate(165.6deg); +} +.c100.p47 .bar { + -webkit-transform: rotate(169.20000000000002deg); + -moz-transform: rotate(169.20000000000002deg); + -ms-transform: rotate(169.20000000000002deg); + -o-transform: rotate(169.20000000000002deg); + transform: rotate(169.20000000000002deg); +} +.c100.p48 .bar { + -webkit-transform: rotate(172.8deg); + -moz-transform: rotate(172.8deg); + -ms-transform: rotate(172.8deg); + -o-transform: rotate(172.8deg); + transform: rotate(172.8deg); +} +.c100.p49 .bar { + -webkit-transform: rotate(176.4deg); + -moz-transform: rotate(176.4deg); + -ms-transform: rotate(176.4deg); + -o-transform: rotate(176.4deg); + transform: rotate(176.4deg); +} +.c100.p50 .bar { + -webkit-transform: rotate(180deg); + -moz-transform: rotate(180deg); + -ms-transform: rotate(180deg); + -o-transform: rotate(180deg); + transform: rotate(180deg); +} +.c100.p51 .bar { + -webkit-transform: rotate(183.6deg); + -moz-transform: rotate(183.6deg); + -ms-transform: rotate(183.6deg); + -o-transform: rotate(183.6deg); + transform: rotate(183.6deg); +} +.c100.p52 .bar { + -webkit-transform: rotate(187.20000000000002deg); + -moz-transform: rotate(187.20000000000002deg); + -ms-transform: rotate(187.20000000000002deg); + -o-transform: rotate(187.20000000000002deg); + transform: rotate(187.20000000000002deg); +} +.c100.p53 .bar { + -webkit-transform: rotate(190.8deg); + -moz-transform: rotate(190.8deg); + -ms-transform: rotate(190.8deg); + -o-transform: rotate(190.8deg); + transform: rotate(190.8deg); +} +.c100.p54 .bar { + -webkit-transform: rotate(194.4deg); + -moz-transform: rotate(194.4deg); + -ms-transform: rotate(194.4deg); + -o-transform: rotate(194.4deg); + transform: rotate(194.4deg); +} +.c100.p55 .bar { + -webkit-transform: rotate(198deg); + -moz-transform: rotate(198deg); + -ms-transform: rotate(198deg); + -o-transform: rotate(198deg); + transform: rotate(198deg); +} +.c100.p56 .bar { + -webkit-transform: rotate(201.6deg); + -moz-transform: rotate(201.6deg); + -ms-transform: rotate(201.6deg); + -o-transform: rotate(201.6deg); + transform: rotate(201.6deg); +} +.c100.p57 .bar { + -webkit-transform: rotate(205.20000000000002deg); + -moz-transform: rotate(205.20000000000002deg); + -ms-transform: rotate(205.20000000000002deg); + -o-transform: rotate(205.20000000000002deg); + transform: rotate(205.20000000000002deg); +} +.c100.p58 .bar { + -webkit-transform: rotate(208.8deg); + -moz-transform: rotate(208.8deg); + -ms-transform: rotate(208.8deg); + -o-transform: rotate(208.8deg); + transform: rotate(208.8deg); +} +.c100.p59 .bar { + -webkit-transform: rotate(212.4deg); + -moz-transform: rotate(212.4deg); + -ms-transform: rotate(212.4deg); + -o-transform: rotate(212.4deg); + transform: rotate(212.4deg); +} +.c100.p60 .bar { + -webkit-transform: rotate(216deg); + -moz-transform: rotate(216deg); + -ms-transform: rotate(216deg); + -o-transform: rotate(216deg); + transform: rotate(216deg); +} +.c100.p61 .bar { + -webkit-transform: rotate(219.6deg); + -moz-transform: rotate(219.6deg); + -ms-transform: rotate(219.6deg); + -o-transform: rotate(219.6deg); + transform: rotate(219.6deg); +} +.c100.p62 .bar { + -webkit-transform: rotate(223.20000000000002deg); + -moz-transform: rotate(223.20000000000002deg); + -ms-transform: rotate(223.20000000000002deg); + -o-transform: rotate(223.20000000000002deg); + transform: rotate(223.20000000000002deg); +} +.c100.p63 .bar { + -webkit-transform: rotate(226.8deg); + -moz-transform: rotate(226.8deg); + -ms-transform: rotate(226.8deg); + -o-transform: rotate(226.8deg); + transform: rotate(226.8deg); +} +.c100.p64 .bar { + -webkit-transform: rotate(230.4deg); + -moz-transform: rotate(230.4deg); + -ms-transform: rotate(230.4deg); + -o-transform: rotate(230.4deg); + transform: rotate(230.4deg); +} +.c100.p65 .bar { + -webkit-transform: rotate(234deg); + -moz-transform: rotate(234deg); + -ms-transform: rotate(234deg); + -o-transform: rotate(234deg); + transform: rotate(234deg); +} +.c100.p66 .bar { + -webkit-transform: rotate(237.6deg); + -moz-transform: rotate(237.6deg); + -ms-transform: rotate(237.6deg); + -o-transform: rotate(237.6deg); + transform: rotate(237.6deg); +} +.c100.p67 .bar { + -webkit-transform: rotate(241.20000000000002deg); + -moz-transform: rotate(241.20000000000002deg); + -ms-transform: rotate(241.20000000000002deg); + -o-transform: rotate(241.20000000000002deg); + transform: rotate(241.20000000000002deg); +} +.c100.p68 .bar { + -webkit-transform: rotate(244.8deg); + -moz-transform: rotate(244.8deg); + -ms-transform: rotate(244.8deg); + -o-transform: rotate(244.8deg); + transform: rotate(244.8deg); +} +.c100.p69 .bar { + -webkit-transform: rotate(248.4deg); + -moz-transform: rotate(248.4deg); + -ms-transform: rotate(248.4deg); + -o-transform: rotate(248.4deg); + transform: rotate(248.4deg); +} +.c100.p70 .bar { + -webkit-transform: rotate(252deg); + -moz-transform: rotate(252deg); + -ms-transform: rotate(252deg); + -o-transform: rotate(252deg); + transform: rotate(252deg); +} +.c100.p71 .bar { + -webkit-transform: rotate(255.6deg); + -moz-transform: rotate(255.6deg); + -ms-transform: rotate(255.6deg); + -o-transform: rotate(255.6deg); + transform: rotate(255.6deg); +} +.c100.p72 .bar { + -webkit-transform: rotate(259.2deg); + -moz-transform: rotate(259.2deg); + -ms-transform: rotate(259.2deg); + -o-transform: rotate(259.2deg); + transform: rotate(259.2deg); +} +.c100.p73 .bar { + -webkit-transform: rotate(262.8deg); + -moz-transform: rotate(262.8deg); + -ms-transform: rotate(262.8deg); + -o-transform: rotate(262.8deg); + transform: rotate(262.8deg); +} +.c100.p74 .bar { + -webkit-transform: rotate(266.40000000000003deg); + -moz-transform: rotate(266.40000000000003deg); + -ms-transform: rotate(266.40000000000003deg); + -o-transform: rotate(266.40000000000003deg); + transform: rotate(266.40000000000003deg); +} +.c100.p75 .bar { + -webkit-transform: rotate(270deg); + -moz-transform: rotate(270deg); + -ms-transform: rotate(270deg); + -o-transform: rotate(270deg); + transform: rotate(270deg); +} +.c100.p76 .bar { + -webkit-transform: rotate(273.6deg); + -moz-transform: rotate(273.6deg); + -ms-transform: rotate(273.6deg); + -o-transform: rotate(273.6deg); + transform: rotate(273.6deg); +} +.c100.p77 .bar { + -webkit-transform: rotate(277.2deg); + -moz-transform: rotate(277.2deg); + -ms-transform: rotate(277.2deg); + -o-transform: rotate(277.2deg); + transform: rotate(277.2deg); +} +.c100.p78 .bar { + -webkit-transform: rotate(280.8deg); + -moz-transform: rotate(280.8deg); + -ms-transform: rotate(280.8deg); + -o-transform: rotate(280.8deg); + transform: rotate(280.8deg); +} +.c100.p79 .bar { + -webkit-transform: rotate(284.40000000000003deg); + -moz-transform: rotate(284.40000000000003deg); + -ms-transform: rotate(284.40000000000003deg); + -o-transform: rotate(284.40000000000003deg); + transform: rotate(284.40000000000003deg); +} +.c100.p80 .bar { + -webkit-transform: rotate(288deg); + -moz-transform: rotate(288deg); + -ms-transform: rotate(288deg); + -o-transform: rotate(288deg); + transform: rotate(288deg); +} +.c100.p81 .bar { + -webkit-transform: rotate(291.6deg); + -moz-transform: rotate(291.6deg); + -ms-transform: rotate(291.6deg); + -o-transform: rotate(291.6deg); + transform: rotate(291.6deg); +} +.c100.p82 .bar { + -webkit-transform: rotate(295.2deg); + -moz-transform: rotate(295.2deg); + -ms-transform: rotate(295.2deg); + -o-transform: rotate(295.2deg); + transform: rotate(295.2deg); +} +.c100.p83 .bar { + -webkit-transform: rotate(298.8deg); + -moz-transform: rotate(298.8deg); + -ms-transform: rotate(298.8deg); + -o-transform: rotate(298.8deg); + transform: rotate(298.8deg); +} +.c100.p84 .bar { + -webkit-transform: rotate(302.40000000000003deg); + -moz-transform: rotate(302.40000000000003deg); + -ms-transform: rotate(302.40000000000003deg); + -o-transform: rotate(302.40000000000003deg); + transform: rotate(302.40000000000003deg); +} +.c100.p85 .bar { + -webkit-transform: rotate(306deg); + -moz-transform: rotate(306deg); + -ms-transform: rotate(306deg); + -o-transform: rotate(306deg); + transform: rotate(306deg); +} +.c100.p86 .bar { + -webkit-transform: rotate(309.6deg); + -moz-transform: rotate(309.6deg); + -ms-transform: rotate(309.6deg); + -o-transform: rotate(309.6deg); + transform: rotate(309.6deg); +} +.c100.p87 .bar { + -webkit-transform: rotate(313.2deg); + -moz-transform: rotate(313.2deg); + -ms-transform: rotate(313.2deg); + -o-transform: rotate(313.2deg); + transform: rotate(313.2deg); +} +.c100.p88 .bar { + -webkit-transform: rotate(316.8deg); + -moz-transform: rotate(316.8deg); + -ms-transform: rotate(316.8deg); + -o-transform: rotate(316.8deg); + transform: rotate(316.8deg); +} +.c100.p89 .bar { + -webkit-transform: rotate(320.40000000000003deg); + -moz-transform: rotate(320.40000000000003deg); + -ms-transform: rotate(320.40000000000003deg); + -o-transform: rotate(320.40000000000003deg); + transform: rotate(320.40000000000003deg); +} +.c100.p90 .bar { + -webkit-transform: rotate(324deg); + -moz-transform: rotate(324deg); + -ms-transform: rotate(324deg); + -o-transform: rotate(324deg); + transform: rotate(324deg); +} +.c100.p91 .bar { + -webkit-transform: rotate(327.6deg); + -moz-transform: rotate(327.6deg); + -ms-transform: rotate(327.6deg); + -o-transform: rotate(327.6deg); + transform: rotate(327.6deg); +} +.c100.p92 .bar { + -webkit-transform: rotate(331.2deg); + -moz-transform: rotate(331.2deg); + -ms-transform: rotate(331.2deg); + -o-transform: rotate(331.2deg); + transform: rotate(331.2deg); +} +.c100.p93 .bar { + -webkit-transform: rotate(334.8deg); + -moz-transform: rotate(334.8deg); + -ms-transform: rotate(334.8deg); + -o-transform: rotate(334.8deg); + transform: rotate(334.8deg); +} +.c100.p94 .bar { + -webkit-transform: rotate(338.40000000000003deg); + -moz-transform: rotate(338.40000000000003deg); + -ms-transform: rotate(338.40000000000003deg); + -o-transform: rotate(338.40000000000003deg); + transform: rotate(338.40000000000003deg); +} +.c100.p95 .bar { + -webkit-transform: rotate(342deg); + -moz-transform: rotate(342deg); + -ms-transform: rotate(342deg); + -o-transform: rotate(342deg); + transform: rotate(342deg); +} +.c100.p96 .bar { + -webkit-transform: rotate(345.6deg); + -moz-transform: rotate(345.6deg); + -ms-transform: rotate(345.6deg); + -o-transform: rotate(345.6deg); + transform: rotate(345.6deg); +} +.c100.p97 .bar { + -webkit-transform: rotate(349.2deg); + -moz-transform: rotate(349.2deg); + -ms-transform: rotate(349.2deg); + -o-transform: rotate(349.2deg); + transform: rotate(349.2deg); +} +.c100.p98 .bar { + -webkit-transform: rotate(352.8deg); + -moz-transform: rotate(352.8deg); + -ms-transform: rotate(352.8deg); + -o-transform: rotate(352.8deg); + transform: rotate(352.8deg); +} +.c100.p99 .bar { + -webkit-transform: rotate(356.40000000000003deg); + -moz-transform: rotate(356.40000000000003deg); + -ms-transform: rotate(356.40000000000003deg); + -o-transform: rotate(356.40000000000003deg); + transform: rotate(356.40000000000003deg); +} +.c100.p100 .bar { + -webkit-transform: rotate(360deg); + -moz-transform: rotate(360deg); + -ms-transform: rotate(360deg); + -o-transform: rotate(360deg); + transform: rotate(360deg); +} +.c100:hover { + cursor: default; +} +.c100:hover > span { + width: 3.33em; + line-height: 3.33em; + font-size: 0.3em; + color: #307bbb; +} +.c100:hover:after { + top: 0.04em; + left: 0.04em; + width: 0.92em; + height: 0.92em; +} +.c100.dark { + background-color: #777777; +} +.c100.dark .bar, +.c100.dark .fill { + border-color: #c6ff00 !important; +} +.c100.dark > span { + color: #777777; +} +.c100.dark:after { + background-color: #666666; +} +.c100.dark:hover > span { + color: #c6ff00; +} +.c100.green .bar, +.c100.green .fill { + border-color: #4db53c !important; +} +.c100.green:hover > span { + color: #4db53c; +} +.c100.green.dark .bar, +.c100.green.dark .fill { + border-color: #5fd400 !important; +} +.c100.green.dark:hover > span { + color: #5fd400; +} +.c100.orange .bar, +.c100.orange .fill { + border-color: #dd9d22 !important; +} +.c100.orange:hover > span { + color: #dd9d22; +} +.c100.orange.dark .bar, +.c100.orange.dark .fill { + border-color: #e08833 !important; +} +.c100.orange.dark:hover > span { + color: #e08833; +} diff --git a/static/css/styles.css b/static/css/styles.css index 47d678a..e297beb 100644 --- a/static/css/styles.css +++ b/static/css/styles.css @@ -65,3 +65,8 @@ table, th, td { margin-bottom: 5px; margin-top: 5px; } + +.resource-usage { + width: 50%; + margin: 0 auto; +} diff --git a/static/js/script.js b/static/js/script.js new file mode 100644 index 0000000..6256314 --- /dev/null +++ b/static/js/script.js @@ -0,0 +1,238 @@ +$("#delete-vm").click(function(){ + const vmname = $(this).data('vmname') + swal({ + title: `Are you sure you want to delete ${vmname}?`, + icon: "warning", + buttons: { + cancel: true, + delete: { + text: "Delete", + closeModal: false, + className: "swal-button--danger", + } + }, + dangerMode: true, + }) + .then((willDelete) => { + if (willDelete) { + const vmid = $(this).data('vmid') + fetch(`/proxstar/vm/${vmid}/delete`, { + credentials: 'same-origin', + method: 'post' + }).then((response) => { + return swal(`${vmname} has been deleted!`, { + icon: "success", + }); + }).then(() => { + window.location = "/proxstar"; + }).catch(err => { + if (err) { + swal("Uh oh...", `Unable to delete ${vmname}. Please try again later.`, "error"); + } else { + swal.stopLoading(); + swal.close(); + } + }); + } + }); +}); + +$("#stop-vm").click(function(){ + const vmname = $(this).data('vmname') + swal({ + title: `Are you sure you want to stop ${vmname}?`, + icon: "warning", + buttons: { + cancel: true, + delete: { + text: "Stop", + closeModal: false, + className: "swal-button--danger", + } + }, + dangerMode: true, + }) + .then((willDelete) => { + if (willDelete) { + const vmid = $(this).data('vmid') + fetch(`/proxstar/vm/${vmid}/power/stop`, { + credentials: 'same-origin', + method: 'post' + }).then((response) => { + return swal(`${vmname} is now stopping!`, { + icon: "success", + }); + }).then(() => { + window.location = `/proxstar/vm/${vmid}`; + }).catch(err => { + if (err) { + swal("Uh oh...", `Unable to stop ${vmname}. Please try again later.`, "error"); + } else { + swal.stopLoading(); + swal.close(); + } + }); + } + }); +}); + +$("#reset-vm").click(function(){ + const vmname = $(this).data('vmname') + swal({ + title: `Are you sure you want to reset ${vmname}?`, + icon: "warning", + buttons: { + cancel: true, + delete: { + text: "Reset", + closeModal: false, + className: "swal-button--danger", + } + }, + dangerMode: true, + }) + .then((willDelete) => { + if (willDelete) { + const vmid = $(this).data('vmid') + fetch(`/proxstar/vm/${vmid}/power/reset`, { + credentials: 'same-origin', + method: 'post' + }).then((response) => { + return swal(`${vmname} is now resetting!`, { + icon: "success", + }); + }).then(() => { + window.location = `/proxstar/vm/${vmid}`; + }).catch(err => { + if (err) { + swal("Uh oh...", `Unable to reset ${vmname}. Please try again later.`, "error"); + } else { + swal.stopLoading(); + swal.close(); + } + }); + } + }); +}); + +$("#shutdown-vm").click(function(){ + const vmname = $(this).data('vmname') + swal({ + title: `Are you sure you want to shutdown ${vmname}?`, + icon: "warning", + buttons: { + cancel: true, + delete: { + text: "Shutdown", + closeModal: false, + className: "swal-button--danger", + } + }, + dangerMode: true, + }) + .then((willDelete) => { + if (willDelete) { + const vmid = $(this).data('vmid') + fetch(`/proxstar/vm/${vmid}/power/shutdown`, { + credentials: 'same-origin', + method: 'post' + }).then((response) => { + return swal(`${vmname} is now shutting down!`, { + icon: "success", + }); + }).then(() => { + window.location = `/proxstar/vm/${vmid}`; + }).catch(err => { + if (err) { + swal("Uh oh...", `Unable to shutdown ${vmname}. Please try again later.`, "error"); + } else { + swal.stopLoading(); + swal.close(); + } + }); + } + }); +}); + +$("#suspend-vm").click(function(){ + const vmname = $(this).data('vmname') + swal({ + title: `Are you sure you want to suspend ${vmname}?`, + icon: "warning", + buttons: { + cancel: true, + delete: { + text: "Suspend", + closeModal: false, + className: "swal-button--danger", + } + }, + dangerMode: true, + }) + .then((willDelete) => { + if (willDelete) { + const vmid = $(this).data('vmid') + fetch(`/proxstar/vm/${vmid}/power/suspend`, { + credentials: 'same-origin', + method: 'post' + }).then((response) => { + return swal(`${vmname} is now suspending!`, { + icon: "success", + }); + }).then(() => { + window.location = `/proxstar/vm/${vmid}`; + }).catch(err => { + if (err) { + swal("Uh oh...", `Unable to suspend ${vmname}. Please try again later.`, "error"); + } else { + swal.stopLoading(); + swal.close(); + } + }); + } + }); +}); + +$("#start-vm").click(function(){ + const vmname = $(this).data('vmname') + const vmid = $(this).data('vmid') + fetch(`/proxstar/vm/${vmid}/power/start`, { + credentials: 'same-origin', + method: 'post' + }).then((response) => { + return swal(`${vmname} is now starting!`, { + icon: "success", + }); + }).then(() => { + window.location = `/proxstar/vm/${vmid}`; + }).catch(err => { + if (err) { + swal("Uh oh...", `Unable to start ${vmname}. Please try again later.`, "error"); + } else { + swal.stopLoading(); + swal.close(); + } + }); +}); + +$("#resume-vm").click(function(){ + const vmname = $(this).data('vmname') + const vmid = $(this).data('vmid') + fetch(`/proxstar/vm/${vmid}/power/resume`, { + credentials: 'same-origin', + method: 'post' + }).then((response) => { + return swal(`${vmname} is now resuming!`, { + icon: "success", + }); + }).then(() => { + window.location = `/proxstar/vm/${vmid}`; + }).catch(err => { + if (err) { + swal("Uh oh...", `Unable to resume ${vmname}. Please try again later.`, "error"); + } else { + swal.stopLoading(); + swal.close(); + } + }); +}); diff --git a/templates/base.html b/templates/base.html index 6797f74..a34d936 100644 --- a/templates/base.html +++ b/templates/base.html @@ -7,9 +7,8 @@ + - - {% block nav %} @@ -34,7 +33,7 @@
  • - + Create VM @@ -90,6 +89,10 @@ Proxstar ({{config["GIT_REVISION"]}}) + + + + diff --git a/templates/confirm_delete.html b/templates/confirm_delete.html deleted file mode 100644 index 3c13c8a..0000000 --- a/templates/confirm_delete.html +++ /dev/null @@ -1,10 +0,0 @@ -{% extends "base.html" %} -{% block body %} - -Are you sure you want to delete "{{ vmname }}"? - -
    - -
    - -{% endblock %} diff --git a/templates/create.html b/templates/create.html index 81a4736..720483d 100644 --- a/templates/create.html +++ b/templates/create.html @@ -11,11 +11,9 @@
    {% if full_limits %}

    You have reached your limit for the following resources:

    -
      {% for limit in full_limits %} -
    • {{ limit }}
    • +

      {{ limit }}

      {% endfor %} -

    Before you can create any more VMs, you must first either power off (CPU/Memory) or delete (Disk) existing VMs until you have enough resources available.

    {% else %}
    @@ -55,9 +53,56 @@

    Current Usage

    -

    CPU: {{ usage['cpu'] }}/{{ limits['cpu'] }} Cores

    -

    Memory: {{ usage['mem'] }}/{{ limits['mem'] }} GB

    -

    Disk: {{ usage['disk'] }}/{{ limits['disk'] }} GB

    +
    +
    + CPU Cores + {% if percents['cpu'] <= 50 %} +
    + {% elif percents['cpu'] <= 75 %} +
    + {% else %} +
    + {% endif %} + {{ usage['cpu'] }}/{{ limits['cpu'] }} +
    +
    +
    +
    +
    +
    +
    + Memory (GB) + {% if percents['mem'] <= 50 %} +
    + {% elif percents['mem'] <= 75 %} +
    + {% else %} +
    + {% endif %} + {{ usage['mem'] }}/{{ limits['mem'] }} +
    +
    +
    +
    +
    +
    +
    + Disk (GB) + {% if percents['disk'] <= 50 %} +
    + {% elif percents['disk'] <= 75 %} +
    + {% else %} +
    + {% endif %} + {{ usage['disk'] }}/{{ limits['disk'] }} +
    +
    +
    +
    +
    +
    +
    diff --git a/templates/list_vms.html b/templates/list_vms.html index 2483c3c..799fc6d 100644 --- a/templates/list_vms.html +++ b/templates/list_vms.html @@ -3,18 +3,28 @@
    - {% for vm in vms %} -
    -
    -
    - -

    {{ vm['name'] }}

    -
    -

    Status: {{ vm['status'] }}

    -
    + {% if not vms %} +
    +
    +
    +

    It looks like you don't have any VMs! If you want to create a VM, click here.

    - {% endfor %} +
    + {% else %} + {% for vm in vms %} +
    +
    +
    + +

    {{ vm['name'] }}

    +
    +

    Status: {{ vm['status'] }}

    +
    +
    +
    + {% endfor %} + {% endif %}
    diff --git a/templates/vm_details.html b/templates/vm_details.html index 06284ef..e05030c 100644 --- a/templates/vm_details.html +++ b/templates/vm_details.html @@ -10,34 +10,20 @@
    {% if vm['qmpstatus'] == 'stopped' %} - - - + + {% endif %} {% if vm['qmpstatus'] == 'paused' %} -
    - -
    + {% endif %} {% if vm['qmpstatus'] == 'running' or vm['qmpstatus'] == 'paused' %} -
    - -
    + {% if vm['qmpstatus'] == 'running' %} -
    - -
    + {% endif %} -
    - -
    -
    - -
    + + {% endif %} -
    - -