mirror of
https://github.com/ComputerScienceHouse/proxstar.git
synced 2025-02-14 14:01:51 +00:00
Shared Pools
This commit is contained in:
parent
50855e3712
commit
dff517d822
12 changed files with 349 additions and 16 deletions
12
HACKING/proxstar-postgres/schema/large.sql
generated
12
HACKING/proxstar-postgres/schema/large.sql
generated
|
@ -266,6 +266,18 @@ ALTER TABLE ONLY public.vm_expiration
|
||||||
ADD CONSTRAINT vm_expiration_pkey PRIMARY KEY (id);
|
ADD CONSTRAINT vm_expiration_pkey PRIMARY KEY (id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: allowed_users; Type: TABLE; Schema: public; Owner: proxstar
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE public.shared_pools (
|
||||||
|
name VARCHAR(32) PRIMARY KEY,
|
||||||
|
members VARCHAR(32)[]
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
ALTER TABLE public.shared_pools OWNER TO proxstar;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: DATABASE proxstar; Type: ACL; Schema: -; Owner: postgres
|
-- Name: DATABASE proxstar; Type: ACL; Schema: -; Owner: postgres
|
||||||
--
|
--
|
||||||
|
|
|
@ -44,6 +44,9 @@ from proxstar.db import (
|
||||||
delete_allowed_user,
|
delete_allowed_user,
|
||||||
get_template_disk,
|
get_template_disk,
|
||||||
set_template_info,
|
set_template_info,
|
||||||
|
add_shared_pool,
|
||||||
|
get_shared_pool,
|
||||||
|
get_shared_pools
|
||||||
)
|
)
|
||||||
from proxstar.vnc import (
|
from proxstar.vnc import (
|
||||||
add_vnc_target,
|
add_vnc_target,
|
||||||
|
@ -197,7 +200,25 @@ def list_vms(user_view=None):
|
||||||
vms.append(pending_vm)
|
vms.append(pending_vm)
|
||||||
else:
|
else:
|
||||||
vms = 'INACTIVE'
|
vms = 'INACTIVE'
|
||||||
return render_template('list_vms.html', user=user, user_view=user_view, vms=vms)
|
return render_template('list_vms.html', user=user, external_view=user_view, vms=vms)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/pool/shared/<string:name>')
|
||||||
|
@auth.oidc_auth
|
||||||
|
def list_shared_vms(name=None):
|
||||||
|
user = User(session['userinfo']['preferred_username'])
|
||||||
|
pool = get_shared_pool(db, name)
|
||||||
|
if pool:
|
||||||
|
if user.name in pool.members or user.rtp:
|
||||||
|
proxmox = connect_proxmox()
|
||||||
|
vms = proxmox.pools(pool.name).get()['members']
|
||||||
|
else:
|
||||||
|
return 'Not Member of Pool', 403
|
||||||
|
else:
|
||||||
|
return 'Pool does not exist', 400
|
||||||
|
if app.config['FORCE_STANDARD_USER']:
|
||||||
|
user.rtp = False
|
||||||
|
return render_template('list_vms.html', user=user, external_view=pool, vms=vms)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/pools')
|
@app.route('/pools')
|
||||||
|
@ -205,11 +226,10 @@ def list_pools():
|
||||||
user = User(session['userinfo']['preferred_username'])
|
user = User(session['userinfo']['preferred_username'])
|
||||||
if app.config['FORCE_STANDARD_USER']:
|
if app.config['FORCE_STANDARD_USER']:
|
||||||
user.rtp = False
|
user.rtp = False
|
||||||
if not user.rtp:
|
proxmox = connect_proxmox()
|
||||||
abort(403)
|
user_pools = get_pool_cache(db) if user.rtp else []
|
||||||
connect_proxmox()
|
shared_pools = map(lambda pool: {"name": pool.name, "members": pool.members, "vms": proxmox.pools(pool.name).get()['members']}, get_shared_pools(db, user.name, user.rtp))
|
||||||
vms = get_pool_cache(db)
|
return render_template('list_pools.html', user=user, user_pools=user_pools, shared_pools=shared_pools)
|
||||||
return render_template('list_pools.html', user=user, vms=vms)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/isos')
|
@app.route('/isos')
|
||||||
|
@ -463,9 +483,11 @@ def create():
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
stored_isos = get_isos(proxmox, app.config['PROXMOX_ISO_STORAGE'])
|
stored_isos = get_isos(proxmox, app.config['PROXMOX_ISO_STORAGE'])
|
||||||
pools = get_pools(proxmox, db)
|
pools = get_pools(proxmox, db)
|
||||||
|
for pool in get_shared_pools(db, user.name, True):
|
||||||
|
pools.append(pool.name)
|
||||||
templates = get_templates(db)
|
templates = get_templates(db)
|
||||||
return render_template(
|
return render_template(
|
||||||
'create.html',
|
'create_vm.html',
|
||||||
user=user,
|
user=user,
|
||||||
usage=user.usage,
|
usage=user.usage,
|
||||||
limits=user.limits,
|
limits=user.limits,
|
||||||
|
@ -585,6 +607,58 @@ def ignored_pools(pool):
|
||||||
else:
|
else:
|
||||||
return '', 403
|
return '', 403
|
||||||
|
|
||||||
|
@app.route('/pool/shared/create', methods=['GET', 'POST'])
|
||||||
|
@auth.oidc_auth
|
||||||
|
def create_shared_pool():
|
||||||
|
user = User(session['userinfo']['preferred_username'])
|
||||||
|
if request.method == 'GET':
|
||||||
|
return render_template('create_pool.html',user=user)
|
||||||
|
elif request.method == 'POST':
|
||||||
|
name = request.form['name']
|
||||||
|
members = request.form['members'].split(';')
|
||||||
|
description = request.form['description']
|
||||||
|
if 'rtp' in session['userinfo']['groups']:
|
||||||
|
try:
|
||||||
|
proxmox = connect_proxmox()
|
||||||
|
proxmox.pools.post(poolid=name, comment=description)
|
||||||
|
except:
|
||||||
|
return 'Error creating pool', 400
|
||||||
|
add_shared_pool(db, name, members)
|
||||||
|
return '', 200
|
||||||
|
else:
|
||||||
|
return '', 403
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/pool/shared/<string:name>/modify', methods=['POST'])
|
||||||
|
@auth.oidc_auth
|
||||||
|
def modify_shared_pool(name):
|
||||||
|
members = request.form['members'].split(',')
|
||||||
|
if 'rtp' in session['userinfo']['groups']:
|
||||||
|
pool = get_shared_pool(db, name)
|
||||||
|
if pool:
|
||||||
|
pool.members = members
|
||||||
|
db.commit()
|
||||||
|
return '', 200
|
||||||
|
return 'Pool not found', 400
|
||||||
|
else:
|
||||||
|
return '', 403
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/pool/shared/<string:name>/delete', methods=['POST'])
|
||||||
|
@auth.oidc_auth
|
||||||
|
def delete_shared_pool(name):
|
||||||
|
if 'rtp' in session['userinfo']['groups']:
|
||||||
|
pool = get_shared_pool(db, name)
|
||||||
|
if pool:
|
||||||
|
db.delete(pool)
|
||||||
|
db.commit()
|
||||||
|
proxmox = connect_proxmox()
|
||||||
|
proxmox.pools(name).delete()
|
||||||
|
return '', 200
|
||||||
|
return 'Pool not found', 400
|
||||||
|
else:
|
||||||
|
return '', 403
|
||||||
|
|
||||||
|
|
||||||
@app.route('/user/<string:user>/allow', methods=['POST', 'DELETE'])
|
@app.route('/user/<string:user>/allow', methods=['POST', 'DELETE'])
|
||||||
@auth.oidc_auth
|
@auth.oidc_auth
|
||||||
|
|
|
@ -14,6 +14,7 @@ from proxstar.models import (
|
||||||
Template,
|
Template,
|
||||||
Usage_Limit,
|
Usage_Limit,
|
||||||
VM_Expiration,
|
VM_Expiration,
|
||||||
|
Shared_Pools,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -212,3 +213,23 @@ def set_template_info(db, template_id, name, disk):
|
||||||
template.name = name
|
template.name = name
|
||||||
template.disk = disk
|
template.disk = disk
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def add_shared_pool(db, name, members):
|
||||||
|
if db.query(Shared_Pools).get(name):
|
||||||
|
return "Name Already in Use"
|
||||||
|
db.add(Shared_Pools(name=name, members=members))
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
|
||||||
|
def get_shared_pool(db, name):
|
||||||
|
return db.query(Shared_Pools).get(name)
|
||||||
|
|
||||||
|
|
||||||
|
def get_shared_pools(db, user, all_pools):
|
||||||
|
if all_pools:
|
||||||
|
return db.query(Shared_Pools).all()
|
||||||
|
pools = []
|
||||||
|
for pool in db.query(Shared_Pools).filter(Shared_Pools.members.contains(f"{{{user}}}")).all():
|
||||||
|
pools.append(pool)
|
||||||
|
return pools
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from sqlalchemy import Column, Date, Integer, String
|
from sqlalchemy import Column, Date, Integer, String
|
||||||
from sqlalchemy.dialects import postgresql
|
from sqlalchemy.dialects import postgresql
|
||||||
from sqlalchemy.ext.declarative import declarative_base
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
|
from sqlalchemy.ext.mutable import MutableList
|
||||||
from sqlalchemy.types import JSON, Text
|
from sqlalchemy.types import JSON, Text
|
||||||
|
|
||||||
from proxstar.util import default_repr
|
from proxstar.util import default_repr
|
||||||
|
@ -53,3 +54,9 @@ class Ignored_Pools(Base):
|
||||||
class Allowed_Users(Base):
|
class Allowed_Users(Base):
|
||||||
__tablename__ = 'allowed_users'
|
__tablename__ = 'allowed_users'
|
||||||
id = Column(String(32), primary_key=True)
|
id = Column(String(32), primary_key=True)
|
||||||
|
|
||||||
|
@default_repr
|
||||||
|
class Shared_Pools(Base):
|
||||||
|
__tablename__ = 'shared_pools'
|
||||||
|
name = Column(String(32), primary_key=True)
|
||||||
|
members = Column(MutableList.as_mutable(postgresql.ARRAY(String(32))))
|
||||||
|
|
|
@ -2,7 +2,7 @@ from flask import current_app as app
|
||||||
from proxmoxer import ProxmoxAPI
|
from proxmoxer import ProxmoxAPI
|
||||||
|
|
||||||
from proxstar import logging
|
from proxstar import logging
|
||||||
from proxstar.db import get_ignored_pools
|
from proxstar.db import get_ignored_pools, get_shared_pool
|
||||||
from proxstar.ldapdb import is_user
|
from proxstar.ldapdb import is_user
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -379,6 +379,54 @@ $("#create-vm").click(function(){
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#create-pool").click(function(){
|
||||||
|
console.log("bingus");
|
||||||
|
const name = document.getElementById('name').value.toLowerCase();
|
||||||
|
const description = document.getElementById('description').value;
|
||||||
|
const members = document.getElementById('members').value;
|
||||||
|
var info = document.createElement('span');
|
||||||
|
swal({
|
||||||
|
title: `Are you sure you want to create ${name}?`,
|
||||||
|
content: info,
|
||||||
|
icon: "info",
|
||||||
|
buttons: {
|
||||||
|
cancel: true,
|
||||||
|
confirm: {
|
||||||
|
text: "Create",
|
||||||
|
closeModal: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((willCreate) => {
|
||||||
|
if (willCreate) {
|
||||||
|
var data = new FormData();
|
||||||
|
data.append('name', name);
|
||||||
|
data.append('description', description);
|
||||||
|
data.append('members', members);
|
||||||
|
fetch('/pool/shared/create', {
|
||||||
|
credentials: 'same-origin',
|
||||||
|
method: 'POST',
|
||||||
|
body: data
|
||||||
|
}).then((response) => {
|
||||||
|
console.log(response);
|
||||||
|
var swal_text = `${name} is now being created. Check back soon and it should be good to go.`
|
||||||
|
return swal(`${swal_text}`, {
|
||||||
|
icon: "success",
|
||||||
|
buttons: {
|
||||||
|
ok: {
|
||||||
|
text: "OK",
|
||||||
|
closeModal: true,
|
||||||
|
className: "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).then(() => {
|
||||||
|
window.location = "/";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
$("#change-cores").click(function(){
|
$("#change-cores").click(function(){
|
||||||
const vmid = $(this).data('vmid');
|
const vmid = $(this).data('vmid');
|
||||||
const usage = $(this).data('usage');
|
const usage = $(this).data('usage');
|
||||||
|
@ -569,6 +617,67 @@ $(".edit-limit").click(function(){
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(".edit-shared-members").click(function(){
|
||||||
|
const pool = $(this).data('pool');
|
||||||
|
const currentMembers = $(this).data('members').slice(1,-1).split(', ');
|
||||||
|
var currentMembersString = "";
|
||||||
|
currentMembers.forEach(name => {
|
||||||
|
currentMembersString += name.slice(1,-1) + ',';
|
||||||
|
});
|
||||||
|
var options = document.createElement('div');
|
||||||
|
var members = document.createElement('input');
|
||||||
|
members.type = 'text';
|
||||||
|
members.defaultValue = currentMembersString.slice(0,-1);
|
||||||
|
options.append(members);
|
||||||
|
swal({
|
||||||
|
title: `Enter the new member list for ${pool}:`,
|
||||||
|
content: options,
|
||||||
|
buttons: {
|
||||||
|
cancel: {
|
||||||
|
text: "Cancel",
|
||||||
|
visible: true,
|
||||||
|
closeModal: true,
|
||||||
|
className: "",
|
||||||
|
},
|
||||||
|
confirm: {
|
||||||
|
text: "Submit",
|
||||||
|
closeModal: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((willChange) => {
|
||||||
|
if (willChange) {
|
||||||
|
var data = new FormData();
|
||||||
|
data.append('members', $(members).val());
|
||||||
|
fetch(`/pool/shared/${pool}/modify`, {
|
||||||
|
credentials: 'same-origin',
|
||||||
|
method: 'post',
|
||||||
|
body: data
|
||||||
|
}).then((response) => {
|
||||||
|
return swal(`Now applying new member list to ${pool}!`, {
|
||||||
|
icon: "success",
|
||||||
|
buttons: {
|
||||||
|
ok: {
|
||||||
|
text: "OK",
|
||||||
|
closeModal: true,
|
||||||
|
className: "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).then(() => {
|
||||||
|
window.location = "/";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
if (err) {
|
||||||
|
swal("Uh oh...", `Unable to change the members of ${pool}. Please try again later.`, "error");
|
||||||
|
} else {
|
||||||
|
swal.stopLoading();
|
||||||
|
swal.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
$(".delete-user").click(function(){
|
$(".delete-user").click(function(){
|
||||||
const user = $(this).data('user');
|
const user = $(this).data('user');
|
||||||
swal({
|
swal({
|
||||||
|
@ -607,6 +716,44 @@ $(".delete-user").click(function(){
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(".delete-pool").click(function(){
|
||||||
|
const pool = $(this).data('pool');
|
||||||
|
swal({
|
||||||
|
title: `Are you sure you want to delete the pool ${pool}?`,
|
||||||
|
icon: "warning",
|
||||||
|
buttons: {
|
||||||
|
cancel: true,
|
||||||
|
delete: {
|
||||||
|
text: "delete",
|
||||||
|
closeModal: false,
|
||||||
|
className: "swal-button--danger",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dangerMode: true,
|
||||||
|
})
|
||||||
|
.then((willDelete) => {
|
||||||
|
if (willDelete) {
|
||||||
|
fetch(`/pool/shared/${ pool }/delete`, {
|
||||||
|
credentials: 'same-origin',
|
||||||
|
method: 'post'
|
||||||
|
}).then((response) => {
|
||||||
|
return swal(`The pool ${pool} has been deleted!`, {
|
||||||
|
icon: "success",
|
||||||
|
});
|
||||||
|
}).then(() => {
|
||||||
|
window.location = "/";
|
||||||
|
}).catch(err => {
|
||||||
|
if (err) {
|
||||||
|
swal("Uh oh...", `Unable to delete the pool ${pool}. Please try again later.`, "error");
|
||||||
|
} else {
|
||||||
|
swal.stopLoading();
|
||||||
|
swal.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
$(".delete-ignored-pool").click(function(){
|
$(".delete-ignored-pool").click(function(){
|
||||||
const pool = $(this).data('pool');
|
const pool = $(this).data('pool');
|
||||||
fetch(`/pool/${pool}/ignore`, {
|
fetch(`/pool/${pool}/ignore`, {
|
||||||
|
|
|
@ -54,11 +54,17 @@
|
||||||
Create VM
|
Create VM
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% if user.rtp %}
|
|
||||||
<li class="nav-item navbar-user dropdown">
|
<li class="nav-item navbar-user dropdown">
|
||||||
<a class="nav-link" href="/pools">
|
<a class="nav-link" href="/pools">
|
||||||
<i class="fas fa-user"></i>
|
<i class="fas fa-user"></i>
|
||||||
User Pools
|
Pools
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% if user.rtp %}
|
||||||
|
<li class="nav-item navbar-user dropdown">
|
||||||
|
<a class="nav-link" href="/pool/shared/create">
|
||||||
|
<i class="fas fa-plus-circle"></i>
|
||||||
|
Create Shared Pool
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item navbar-user dropdown">
|
<li class="nav-item navbar-user dropdown">
|
||||||
|
|
37
proxstar/templates/create_pool.html
Normal file
37
proxstar/templates/create_pool.html
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% block body %}
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
{% if user['rtp'] %}
|
||||||
|
<div class="col-md-12 col-sm-12">
|
||||||
|
{% else %}
|
||||||
|
<div class="col-lg-9 col-md-8 col-sm-12">
|
||||||
|
{% endif %}
|
||||||
|
<div class="card bg-light mb-3">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title">Create Shared Pool</h3>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="name" class="pull-left">Pool Name</label>
|
||||||
|
<input type="text" name="name" id="name" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="description" class="pull-left">Description</label>
|
||||||
|
<input type="text" name="description" id="description" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="members" class="pull-left">Members</label>
|
||||||
|
<input type="text" name="members" id="members" class="form-control">
|
||||||
|
</div>
|
||||||
|
<div class="text-center">
|
||||||
|
<button class="btn btn-success" id="create-pool" name="create">CREATE</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -1,9 +1,8 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% for pool in vms %}
|
{% for pool in user_pools %}
|
||||||
<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12">
|
<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12">
|
||||||
<div class="card bg-light mb-3">
|
<div class="card bg-light mb-3">
|
||||||
<div class="card-header text-center">
|
<div class="card-header text-center">
|
||||||
|
@ -56,7 +55,30 @@
|
||||||
<button class="btn btn-info proxstar-poolbtn edit-limit" data-user="{{ pool['user'] }}" data-cpu="{{ pool['limits']['cpu'] }}" data-mem="{{ pool['limits']['mem'] }}" data-disk="{{ pool['limits']['disk'] }}">EDIT</button>
|
<button class="btn btn-info proxstar-poolbtn edit-limit" data-user="{{ pool['user'] }}" data-cpu="{{ pool['limits']['cpu'] }}" data-mem="{{ pool['limits']['mem'] }}" data-disk="{{ pool['limits']['disk'] }}">EDIT</button>
|
||||||
{% if not pool['vms'] %}
|
{% if not pool['vms'] %}
|
||||||
<button class="btn btn-danger proxstar-poolbtn delete-user" data-user="{{ pool['user'] }}">DELETE</button>
|
<button class="btn btn-danger proxstar-poolbtn delete-user" data-user="{{ pool['user'] }}">DELETE</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% for pool in shared_pools %}
|
||||||
|
<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12">
|
||||||
|
<div class="card bg-light mb-3">
|
||||||
|
<div class="card-header text-center">
|
||||||
|
<h5 class="card-title user-title">
|
||||||
|
<a href="/pool/{{ pool.name }}">
|
||||||
|
{{ pool.name }}
|
||||||
|
</a>
|
||||||
|
</h5>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="text-center">
|
||||||
|
<h6>{{ pool.members|length }} members</h5>
|
||||||
|
<button class="btn btn-info proxstar-poolbtn edit-shared-members" data-pool="{{ pool.name }}" data-members="{{ pool.members }}">EDIT</button>
|
||||||
|
{% if not pool['vms'] %}
|
||||||
|
<button class="btn btn-danger proxstar-poolbtn delete-pool" data-pool="{{ pool.name }}">DELETE</button>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% if user_view %}
|
{% if external_view %}
|
||||||
<div class="col-md-12 col-sm-12">
|
<div class="col-md-12 col-sm-12">
|
||||||
<div class="card bg-light mb-3">
|
<div class="card bg-light mb-3">
|
||||||
<div class="card-header text-center">
|
<div class="card-header text-center">
|
||||||
<h5 class="card-title">{{ user_view.name }}</h5>
|
<h5 class="card-title">{{ external_view.name }}</h5>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,7 +3,7 @@ from rq.registry import StartedJobRegistry
|
||||||
|
|
||||||
from proxstar.ldapdb import is_active, is_user, is_current_student
|
from proxstar.ldapdb import is_active, is_user, is_current_student
|
||||||
from proxstar import db, q, redis_conn
|
from proxstar import db, q, redis_conn
|
||||||
from proxstar.db import get_allowed_users, get_user_usage_limits, is_rtp
|
from proxstar.db import get_allowed_users, get_user_usage_limits, is_rtp, get_shared_pools
|
||||||
from proxstar.proxmox import connect_proxmox, get_pools
|
from proxstar.proxmox import connect_proxmox, get_pools
|
||||||
from proxstar.util import lazy_property, default_repr
|
from proxstar.util import lazy_property, default_repr
|
||||||
from proxstar.vm import VM
|
from proxstar.vm import VM
|
||||||
|
@ -39,6 +39,7 @@ class User:
|
||||||
if 'name' not in vm:
|
if 'name' not in vm:
|
||||||
vms.remove(vm)
|
vms.remove(vm)
|
||||||
vms = sorted(vms, key=lambda k: k['name'])
|
vms = sorted(vms, key=lambda k: k['name'])
|
||||||
|
|
||||||
return vms
|
return vms
|
||||||
|
|
||||||
@lazy_property
|
@lazy_property
|
||||||
|
@ -63,6 +64,12 @@ class User:
|
||||||
allowed_vms = []
|
allowed_vms = []
|
||||||
for vm in self.vms:
|
for vm in self.vms:
|
||||||
allowed_vms.append(vm['vmid'])
|
allowed_vms.append(vm['vmid'])
|
||||||
|
shared_pools = get_shared_pools(db, self.name, False)
|
||||||
|
proxmox = connect_proxmox()
|
||||||
|
for pool in shared_pools:
|
||||||
|
vms = proxmox.pools(pool.name).get()['members']
|
||||||
|
for vm in vms:
|
||||||
|
allowed_vms.append(vm['vmid'])
|
||||||
return allowed_vms
|
return allowed_vms
|
||||||
|
|
||||||
@lazy_property
|
@lazy_property
|
||||||
|
|
Loading…
Reference in a new issue