mirror of
https://github.com/ComputerScienceHouse/proxstar.git
synced 2025-02-14 14:01:51 +00:00
add ldap, check if active member, create user and give console perms, retry getting mac, better handling of rtp
This commit is contained in:
parent
8161d97f21
commit
cc2033f2ca
11 changed files with 136 additions and 58 deletions
5
agent.py
5
agent.py
|
@ -1,5 +0,0 @@
|
|||
from websockify.websocket import *
|
||||
from websockify.websocketproxy import *
|
||||
|
||||
server = WebSocketProxy(listen_port='10000', target_port='6000')
|
||||
server.start_server()
|
99
app.py
99
app.py
|
@ -4,6 +4,7 @@ import psycopg2
|
|||
import subprocess
|
||||
from db import *
|
||||
from starrs import *
|
||||
from ldapdb import *
|
||||
from proxmox import *
|
||||
from werkzeug.contrib.cache import SimpleCache
|
||||
from flask_pyoidc.flask_pyoidc import OIDCAuthentication
|
||||
|
@ -45,6 +46,10 @@ def list_vms(user=None):
|
|||
else:
|
||||
user = session['userinfo']['preferred_username']
|
||||
vms = get_vms_for_user(proxmox, user)
|
||||
if active:
|
||||
vms = get_vms_for_user(proxmox, user)
|
||||
else:
|
||||
vms = 'INACTIVE'
|
||||
return render_template(
|
||||
'list_vms.html',
|
||||
username=user,
|
||||
|
@ -80,10 +85,10 @@ def hostname(name):
|
|||
def vm_details(vmid):
|
||||
user = session['userinfo']['preferred_username']
|
||||
rtp = 'rtp' in session['userinfo']['groups']
|
||||
active = 'active' in session['userinfo']['groups']
|
||||
proxmox = connect_proxmox()
|
||||
starrs = connect_starrs()
|
||||
if int(vmid) in get_user_allowed_vms(
|
||||
proxmox, user) or 'rtp' in session['userinfo']['groups']:
|
||||
if 'rtp' in session['userinfo']['groups'] or int(vmid) in get_user_allowed_vms(proxmox, user):
|
||||
vm = get_vm(proxmox, vmid)
|
||||
vm['vmid'] = vmid
|
||||
vm['config'] = get_vm_config(proxmox, vmid)
|
||||
|
@ -97,7 +102,7 @@ def vm_details(vmid):
|
|||
get_ip_for_mac(starrs, interface[1])])
|
||||
vm['expire'] = get_vm_expire(
|
||||
vmid, app.config['VM_EXPIRE_MONTHS']).strftime('%m/%d/%Y')
|
||||
usage = get_user_usage(proxmox, 'proxstar')
|
||||
usage = get_user_usage(proxmox, user)
|
||||
limits = get_user_usage_limits(user)
|
||||
usage_check = check_user_usage(proxmox, user, vm['config']['cores'],
|
||||
vm['config']['memory'], 0)
|
||||
|
@ -105,6 +110,7 @@ def vm_details(vmid):
|
|||
'vm_details.html',
|
||||
username=user,
|
||||
rtp=rtp,
|
||||
active=active,
|
||||
vm=vm,
|
||||
usage=usage,
|
||||
limits=limits,
|
||||
|
@ -243,48 +249,55 @@ def delete(vmid):
|
|||
def create():
|
||||
user = session['userinfo']['preferred_username']
|
||||
rtp = 'rtp' in session['userinfo']['groups']
|
||||
active = 'active' in session['userinfo']['groups']
|
||||
proxmox = connect_proxmox()
|
||||
starrs = connect_starrs()
|
||||
if request.method == 'GET':
|
||||
usage = get_user_usage(proxmox, user)
|
||||
limits = get_user_usage_limits(user)
|
||||
percents = get_user_usage_percent(proxmox, user, usage, limits)
|
||||
isos = get_isos(proxmox, app.config['PROXMOX_ISO_STORAGE'])
|
||||
pools = get_pools(proxmox)
|
||||
return render_template(
|
||||
'create.html',
|
||||
username=user,
|
||||
rtp=rtp,
|
||||
usage=usage,
|
||||
limits=limits,
|
||||
percents=percents,
|
||||
isos=isos,
|
||||
pools=pools)
|
||||
elif request.method == 'POST':
|
||||
name = request.form['name']
|
||||
cores = request.form['cores']
|
||||
memory = request.form['mem']
|
||||
disk = request.form['disk']
|
||||
iso = request.form['iso']
|
||||
if iso != 'none':
|
||||
iso = "{}:iso/{}".format(app.config['PROXMOX_ISO_STORAGE'], iso)
|
||||
if not rtp:
|
||||
usage_check = check_user_usage(proxmox, user, 0, 0, disk)
|
||||
else:
|
||||
usage_check = None
|
||||
user = request.form['user']
|
||||
if usage_check:
|
||||
return usage_check
|
||||
else:
|
||||
valid, available = check_hostname(starrs, name)
|
||||
if valid and available:
|
||||
vmid, mac = create_vm(proxmox, starrs, user, name, cores,
|
||||
memory, disk, iso)
|
||||
register_starrs(
|
||||
starrs, name, app.config['STARRS_USER'], mac,
|
||||
get_next_ip(starrs, app.config['STARRS_IP_RANGE'])[0][0])
|
||||
get_vm_expire(vmid, app.config['VM_EXPIRE_MONTHS'])
|
||||
return vmid
|
||||
if active:
|
||||
if request.method == 'GET':
|
||||
usage = get_user_usage(proxmox, user)
|
||||
limits = get_user_usage_limits(user)
|
||||
percents = get_user_usage_percent(proxmox, user, usage, limits)
|
||||
isos = get_isos(proxmox, app.config['PROXMOX_ISO_STORAGE'])
|
||||
pools = get_pools(proxmox)
|
||||
return render_template(
|
||||
'create.html',
|
||||
username=user,
|
||||
rtp=rtp,
|
||||
active=active,
|
||||
usage=usage,
|
||||
limits=limits,
|
||||
percents=percents,
|
||||
isos=isos,
|
||||
pools=pools)
|
||||
elif request.method == 'POST':
|
||||
name = request.form['name']
|
||||
cores = request.form['cores']
|
||||
memory = request.form['mem']
|
||||
disk = request.form['disk']
|
||||
iso = request.form['iso']
|
||||
if iso != 'none':
|
||||
iso = "{}:iso/{}".format(app.config['PROXMOX_ISO_STORAGE'],
|
||||
iso)
|
||||
if not rtp:
|
||||
usage_check = check_user_usage(proxmox, user, 0, 0, disk)
|
||||
else:
|
||||
usage_check = None
|
||||
user = request.form['user']
|
||||
if usage_check:
|
||||
return usage_check
|
||||
else:
|
||||
valid, available = check_hostname(starrs, name)
|
||||
if valid and available:
|
||||
vmid, mac = create_vm(proxmox, starrs, user, name, cores,
|
||||
memory, disk, iso)
|
||||
register_starrs(
|
||||
starrs, name, app.config['STARRS_USER'], mac,
|
||||
get_next_ip(starrs,
|
||||
app.config['STARRS_IP_RANGE'])[0][0])
|
||||
get_vm_expire(vmid, app.config['VM_EXPIRE_MONTHS'])
|
||||
return vmid
|
||||
else:
|
||||
return '', 403
|
||||
|
||||
|
||||
@app.route('/limits/<string:user>', methods=['POST'])
|
||||
|
|
|
@ -29,3 +29,7 @@ STARRS_DB_USER = ''
|
|||
STARRS_DB_PASS = ''
|
||||
STARRS_USER = 'proxstar'
|
||||
STARRS_IP_RANGE = ''
|
||||
|
||||
# LDAP
|
||||
LDAP_BIND_DN = ''
|
||||
LDAP_BIND_PW = ''
|
||||
|
|
7
db.py
7
db.py
|
@ -1,6 +1,7 @@
|
|||
from sqlalchemy import create_engine, exists
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from ldapdb import *
|
||||
import datetime
|
||||
|
||||
from db_init import VM_Expiration, Usage_Limit, Base
|
||||
|
@ -58,7 +59,11 @@ def get_expired_vms():
|
|||
|
||||
def get_user_usage_limits(user):
|
||||
limits = dict()
|
||||
if session.query(exists().where(Usage_Limit.id == user)).scalar():
|
||||
if is_rtp(user):
|
||||
limits['cpu'] = 1000
|
||||
limits['mem'] = 1000
|
||||
limits['disk'] = 100000
|
||||
elif session.query(exists().where(Usage_Limit.id == user)).scalar():
|
||||
limits['cpu'] = session.query(Usage_Limit).filter(
|
||||
Usage_Limit.id == user).one().cpu
|
||||
limits['mem'] = session.query(Usage_Limit).filter(
|
||||
|
|
24
ldapdb.py
Normal file
24
ldapdb.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
from csh_ldap import CSHLDAP
|
||||
from flask import current_app as app
|
||||
|
||||
|
||||
def connect_ldap():
|
||||
try:
|
||||
ldap = CSHLDAP(app.config['LDAP_BIND_DN'],
|
||||
app.config['LDAP_BIND_PW'])
|
||||
except:
|
||||
print("Unable to connect to LDAP.")
|
||||
raise
|
||||
return ldap
|
||||
|
||||
|
||||
def is_rtp(user):
|
||||
ldap = connect_ldap()
|
||||
rtp_group = ldap.get_group('rtp')
|
||||
return rtp_group.check_member(ldap.get_member(user, uid=True))
|
||||
|
||||
|
||||
def is_active(ldap, user):
|
||||
ldap = connect_ldap()
|
||||
rtp_group = ldap.get_group('active')
|
||||
return rtp_group.check_member(ldap.get_member(user, uid=True))
|
25
proxmox.py
25
proxmox.py
|
@ -3,6 +3,7 @@ from functools import lru_cache
|
|||
from proxmoxer import ProxmoxAPI
|
||||
from flask import current_app as app
|
||||
from db import *
|
||||
from ldapdb import *
|
||||
|
||||
|
||||
def connect_proxmox():
|
||||
|
@ -18,10 +19,20 @@ def connect_proxmox():
|
|||
return proxmox
|
||||
|
||||
|
||||
def create_user(proxmox, user):
|
||||
if not is_rtp(user):
|
||||
proxmox.pools.post(poolid=user, comment='Managed by Proxstar')
|
||||
users = proxmox.access.users.get()
|
||||
username = "{}@csh.rit.edu".format(user)
|
||||
proxmox.access.users.post(userid=username)
|
||||
proxmox.access.acl.put(
|
||||
path="/pool/{}".format(user), roles='PVEVMConsole', users=username)
|
||||
|
||||
|
||||
def get_vms_for_user(proxmox, user):
|
||||
pools = get_pools(proxmox)
|
||||
if user not in pools:
|
||||
proxmox.pools.post(poolid=user, comment='Managed by Proxstar')
|
||||
create_user(proxmox, user)
|
||||
vms = proxmox.pools(user).get()['members']
|
||||
for vm in vms:
|
||||
if 'name' not in vm:
|
||||
|
@ -152,6 +163,8 @@ def get_user_usage(proxmox, user):
|
|||
usage['cpu'] = 0
|
||||
usage['mem'] = 0
|
||||
usage['disk'] = 0
|
||||
if is_rtp(user):
|
||||
return usage
|
||||
vms = get_vms_for_user(proxmox, user)
|
||||
for vm in vms:
|
||||
config = get_vm_config(proxmox, vm['vmid'])
|
||||
|
@ -204,8 +217,14 @@ def create_vm(proxmox, starrs, user, name, cores, memory, disk, iso):
|
|||
net0='virtio,bridge=vmbr0',
|
||||
pool=user,
|
||||
description='Managed by Proxstar')
|
||||
time.sleep(3)
|
||||
mac = get_vm_mac(proxmox, vmid)
|
||||
retry = 0
|
||||
while retry < 5:
|
||||
try:
|
||||
mac = get_vm_mac(proxmox, vmid)
|
||||
break
|
||||
except:
|
||||
retry += 1
|
||||
time.sleep(3)
|
||||
return vmid, mac
|
||||
|
||||
|
||||
|
|
|
@ -4,3 +4,4 @@ proxmoxer
|
|||
psycopg2
|
||||
sqlalchemy
|
||||
python-dateutil
|
||||
csh_ldap
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
{% if active %}
|
||||
<li>
|
||||
<a href="/">
|
||||
<span class="glyphicon glyphicon-th-list"></span>
|
||||
|
@ -39,6 +40,7 @@
|
|||
Create VM
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li class="dropdown navbar-user">
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
{% if rtp %}
|
||||
<div class="col-md-12 col-sm-12">
|
||||
{% else %}
|
||||
<div class="col-md-9 col-sm-12">
|
||||
{% endif %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Create VM</h3>
|
||||
|
@ -13,11 +17,11 @@
|
|||
<p>Before you can create any more VMs, you must first delete existing VMs until you have enough disk resources available.</p>
|
||||
{% else %}
|
||||
<div class="form-group">
|
||||
<label for="name">VM Name</label>
|
||||
<label for="name" class="pull-left">VM Name</label>
|
||||
<input type="text" name="name" id="name" class="form-control">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="cores">Cores</label>
|
||||
<label for="cores" class="pull-left">Cores</label>
|
||||
<select name="cores" id="cores" class="form-control">
|
||||
{% for i in range(1, limits['cpu'] + 1) %}
|
||||
<option value="{{ i }}">{{ i }}</option>
|
||||
|
@ -25,7 +29,7 @@
|
|||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="mem">Memory</label>
|
||||
<label for="mem" class="pull-left">Memory</label>
|
||||
<select name="mem" id="mem" class="form-control">
|
||||
<option value="512">512MB</option>
|
||||
{% for i in range(1, limits['mem'] + 1) %}
|
||||
|
@ -34,11 +38,11 @@
|
|||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="disk">Disk (GB)</label>
|
||||
<label for="disk" class="pull-left">Disk (GB)</label>
|
||||
<input type="number" name="disk" id="disk" class="form-control" min="1" max="{{ limits['disk'] - usage['disk'] }}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="iso">ISO</label>
|
||||
<label for="iso" class="pull-left">ISO</label>
|
||||
<select name="iso" id="iso" class="form-control">
|
||||
<option value="none"></option>
|
||||
{% for iso in isos %}
|
||||
|
@ -48,7 +52,7 @@
|
|||
</div>
|
||||
{% if rtp %}
|
||||
<div class="form-group">
|
||||
<label for="user">User</label>
|
||||
<label for="user" class="pull-left">User</label>
|
||||
<select name="user" id="user" class="form-control">
|
||||
{% for pool in pools %}
|
||||
<option value="{{ pool }}">{{ pool }}</option>
|
||||
|
@ -61,6 +65,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if not rtp %}
|
||||
<div class="col-md-3 col-sm-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
|
@ -120,6 +125,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -20,6 +20,14 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% elif vms == 'INACTIVE' %}
|
||||
<div class="col-md-12 col-sm-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<p>Only active members have access to create Proxmox VMs. If you believe this is an error, please contact an RTP.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% elif rtp_view != True %}
|
||||
{% for vm in vms %}
|
||||
<div class="col-md-3 col-sm-4 col-xs-6">
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
{% endif %}
|
||||
{% if vm['qmpstatus'] == 'running' or vm['qmpstatus'] == 'paused' %}
|
||||
{% if vm['qmpstatus'] == 'running' %}
|
||||
<a href="https://proxmox01.csh.rit.edu/#v1:0:=qemu%2F{{ vm['vmid'] }}:4::::8::" target="_blank">Open VM Console</a>
|
||||
<button class="btn btn-info proxstar-actionbtn" id="suspend-vm" name="suspend" data-vmid="{{ vm['vmid'] }}" data-vmname="{{ vm['name'] }}">SUSPEND</button>
|
||||
{% endif %}
|
||||
<button class="btn btn-info proxstar-actionbtn" id="shutdown-vm" name="shutdown" data-vmid="{{ vm['vmid'] }}" data-vmname="{{ vm['name'] }}">SHUTDOWN</button>
|
||||
|
|
Loading…
Reference in a new issue