add ldap, check if active member, create user and give console perms, retry getting mac, better handling of rtp

This commit is contained in:
Jordan Rodgers 2018-01-19 03:01:10 -05:00
parent 8161d97f21
commit cc2033f2ca
11 changed files with 136 additions and 58 deletions

View file

@ -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
View file

@ -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'])

View file

@ -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
View file

@ -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
View 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))

View file

@ -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

View file

@ -4,3 +4,4 @@ proxmoxer
psycopg2
sqlalchemy
python-dateutil
csh_ldap

View file

@ -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">

View file

@ -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>

View file

@ -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">

View file

@ -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>