mirror of
https://github.com/ComputerScienceHouse/proxstar.git
synced 2025-02-12 13:01:51 +00:00
renew starrs during renewal, add ability to change vm cores
This commit is contained in:
parent
f3d69381c1
commit
9fa6bf051d
5 changed files with 133 additions and 15 deletions
37
app.py
37
app.py
|
@ -71,9 +71,11 @@ def vm_details(vmid):
|
||||||
vm['iso'] = get_vm_iso(proxmox, vmid, config=vm['config'])
|
vm['iso'] = get_vm_iso(proxmox, vmid, config=vm['config'])
|
||||||
vm['interfaces'] = []
|
vm['interfaces'] = []
|
||||||
for interface in get_vm_interfaces(proxmox, vm['vmid'], config=vm['config']):
|
for interface in get_vm_interfaces(proxmox, vm['vmid'], config=vm['config']):
|
||||||
vm['interfaces'].append([interface[0], get_ip_for_mac(starrs, interface[1])[0][3]])
|
vm['interfaces'].append([interface[0], get_ip_for_mac(starrs, interface[1])])
|
||||||
vm['expire'] = get_vm_expire(vmid, app.config['VM_EXPIRE_MONTHS']).strftime('%m/%d/%Y')
|
vm['expire'] = get_vm_expire(vmid, app.config['VM_EXPIRE_MONTHS']).strftime('%m/%d/%Y')
|
||||||
return render_template('vm_details.html', username='com6056', vm=vm)
|
usage = get_user_usage(proxmox, 'proxstar')
|
||||||
|
limits = get_user_usage_limits(user)
|
||||||
|
return render_template('vm_details.html', username='com6056', vm=vm, usage=usage, limits=limits)
|
||||||
else:
|
else:
|
||||||
return '', 403
|
return '', 403
|
||||||
|
|
||||||
|
@ -90,13 +92,39 @@ def vm_power(vmid, action):
|
||||||
return '', 403
|
return '', 403
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/vm/<string:vmid>/cpu/<int:cores>", methods=['POST'])
|
||||||
|
def vm_cpu(vmid, cores):
|
||||||
|
proxmox = connect_proxmox(app.config['PROXMOX_HOST'],
|
||||||
|
app.config['PROXMOX_USER'],
|
||||||
|
app.config['PROXMOX_PASS'])
|
||||||
|
if int(vmid) in get_user_allowed_vms(proxmox, user):
|
||||||
|
cur_cores = get_vm_config(proxmox, vmid)['cores']
|
||||||
|
status = get_vm(proxmox, vmid)['qmpstatus']
|
||||||
|
if cores >= cur_cores:
|
||||||
|
if status == 'running' or status == 'paused':
|
||||||
|
usage_check = check_user_usage(proxmox, user, cores - cur_cores, 0, 0)
|
||||||
|
else:
|
||||||
|
usage_check = check_user_usage(proxmox, user, cores, 0, 0)
|
||||||
|
if usage_check:
|
||||||
|
return usage_check
|
||||||
|
change_vm_cpu(proxmox, vmid, cores)
|
||||||
|
return '', 200
|
||||||
|
else:
|
||||||
|
return '', 403
|
||||||
|
|
||||||
|
|
||||||
@app.route("/vm/<string:vmid>/renew", methods=['POST'])
|
@app.route("/vm/<string:vmid>/renew", methods=['POST'])
|
||||||
def vm_renew(vmid):
|
def vm_renew(vmid):
|
||||||
proxmox = connect_proxmox(app.config['PROXMOX_HOST'],
|
proxmox = connect_proxmox(app.config['PROXMOX_HOST'],
|
||||||
app.config['PROXMOX_USER'],
|
app.config['PROXMOX_USER'],
|
||||||
app.config['PROXMOX_PASS'])
|
app.config['PROXMOX_PASS'])
|
||||||
|
starrs = connect_starrs(
|
||||||
|
app.config['STARRS_DB_NAME'], app.config['STARRS_DB_USER'],
|
||||||
|
app.config['STARRS_DB_HOST'], app.config['STARRS_DB_PASS'])
|
||||||
if int(vmid) in get_user_allowed_vms(proxmox, user):
|
if int(vmid) in get_user_allowed_vms(proxmox, user):
|
||||||
renew_vm_expire(vmid, app.config['VM_EXPIRE_MONTHS'])
|
renew_vm_expire(vmid, app.config['VM_EXPIRE_MONTHS'])
|
||||||
|
for interface in get_vm_interfaces(proxmox, vmid):
|
||||||
|
renew_ip(starrs, get_ip_for_mac(starrs, interface[1]))
|
||||||
return '', 200
|
return '', 200
|
||||||
else:
|
else:
|
||||||
return '', 403
|
return '', 403
|
||||||
|
@ -179,10 +207,11 @@ def create():
|
||||||
if usage_check:
|
if usage_check:
|
||||||
return usage_check
|
return usage_check
|
||||||
else:
|
else:
|
||||||
if not check_hostname(starrs, name):
|
valid, available = check_hostname(starrs, name)
|
||||||
|
if valid and available:
|
||||||
vmid, mac = create_vm(proxmox, starrs, user, name, cores, memory,
|
vmid, mac = create_vm(proxmox, starrs, user, name, cores, memory,
|
||||||
disk, iso)
|
disk, iso)
|
||||||
register_starrs(starrs, name, user, mac,
|
register_starrs(starrs, name, app.config['STARRS_USER'], mac,
|
||||||
get_next_ip(starrs,
|
get_next_ip(starrs,
|
||||||
app.config['STARRS_IP_RANGE'])[0][0])
|
app.config['STARRS_IP_RANGE'])[0][0])
|
||||||
get_vm_expire(vmid, app.config['VM_EXPIRE_MONTHS'])
|
get_vm_expire(vmid, app.config['VM_EXPIRE_MONTHS'])
|
||||||
|
|
11
proxmox.py
11
proxmox.py
|
@ -163,11 +163,11 @@ def check_user_usage(proxmox, user, vm_cpu, vm_mem, vm_disk):
|
||||||
limits = get_user_usage_limits(user)
|
limits = get_user_usage_limits(user)
|
||||||
cur_usage = get_user_usage(proxmox, user)
|
cur_usage = get_user_usage(proxmox, user)
|
||||||
if int(cur_usage['cpu']) + int(vm_cpu) > int(limits['cpu']):
|
if int(cur_usage['cpu']) + int(vm_cpu) > int(limits['cpu']):
|
||||||
return 'Exceeds CPU limit!'
|
return 'exceeds_cpu_limit'
|
||||||
elif int(cur_usage['mem']) + (int(vm_mem) / 1024) > int(limits['mem']):
|
elif int(cur_usage['mem']) + (int(vm_mem) / 1024) > int(limits['mem']):
|
||||||
return 'Exceeds memory limit!'
|
return 'exceeds_memory_limit'
|
||||||
elif int(cur_usage['disk']) + int(vm_disk) > int(limits['disk']):
|
elif int(cur_usage['disk']) + int(vm_disk) > int(limits['disk']):
|
||||||
return 'Exceeds disk limit!'
|
return 'exceeds_disk_limit'
|
||||||
|
|
||||||
|
|
||||||
def get_user_usage_percent(proxmox, usage=None, limits=None):
|
def get_user_usage_percent(proxmox, usage=None, limits=None):
|
||||||
|
@ -222,6 +222,11 @@ def change_vm_power(proxmox, vmid, action):
|
||||||
node.qemu(vmid).status.resume.post()
|
node.qemu(vmid).status.resume.post()
|
||||||
|
|
||||||
|
|
||||||
|
def change_vm_cpu(proxmox, vmid, cores):
|
||||||
|
node = proxmox.nodes(get_vm_node(proxmox, vmid))
|
||||||
|
node.qemu(vmid).config.put(cores=cores)
|
||||||
|
|
||||||
|
|
||||||
def get_isos(proxmox, storage):
|
def get_isos(proxmox, storage):
|
||||||
isos = []
|
isos = []
|
||||||
for iso in proxmox.nodes('proxmox01').storage(storage).content.get():
|
for iso in proxmox.nodes('proxmox01').storage(storage).content.get():
|
||||||
|
|
27
starrs.py
27
starrs.py
|
@ -15,7 +15,7 @@ def get_next_ip(starrs, range_name):
|
||||||
c = starrs.cursor()
|
c = starrs.cursor()
|
||||||
try:
|
try:
|
||||||
c.execute("BEGIN")
|
c.execute("BEGIN")
|
||||||
c.callproc("api.initialize", ('root', ))
|
c.callproc("api.initialize", ('root',))
|
||||||
c.callproc("api.get_address_from_range", (range_name, ))
|
c.callproc("api.get_address_from_range", (range_name, ))
|
||||||
results = c.fetchall()
|
results = c.fetchall()
|
||||||
c.execute("COMMIT")
|
c.execute("COMMIT")
|
||||||
|
@ -28,8 +28,21 @@ def get_ip_for_mac(starrs, mac):
|
||||||
c = starrs.cursor()
|
c = starrs.cursor()
|
||||||
try:
|
try:
|
||||||
c.execute("BEGIN")
|
c.execute("BEGIN")
|
||||||
c.callproc("api.initialize", ('root', ))
|
c.callproc("api.initialize", ('root',))
|
||||||
c.callproc("api.get_system_interface_addresses", (mac.lower(), ))
|
c.callproc("api.get_system_interface_addresses", (mac.lower(),))
|
||||||
|
results = c.fetchall()
|
||||||
|
c.execute("COMMIT")
|
||||||
|
finally:
|
||||||
|
c.close()
|
||||||
|
return results[0][3]
|
||||||
|
|
||||||
|
|
||||||
|
def renew_ip(starrs, addr):
|
||||||
|
c = starrs.cursor()
|
||||||
|
try:
|
||||||
|
c.execute("BEGIN")
|
||||||
|
c.callproc("api.initialize", ('root',))
|
||||||
|
c.callproc("api.renew_interface_address", (addr,))
|
||||||
results = c.fetchall()
|
results = c.fetchall()
|
||||||
c.execute("COMMIT")
|
c.execute("COMMIT")
|
||||||
finally:
|
finally:
|
||||||
|
@ -41,14 +54,14 @@ def check_hostname(starrs, hostname):
|
||||||
c = starrs.cursor()
|
c = starrs.cursor()
|
||||||
try:
|
try:
|
||||||
c.execute("BEGIN")
|
c.execute("BEGIN")
|
||||||
c.callproc("api.initialize", ('root', ))
|
c.callproc("api.initialize", ('root',))
|
||||||
c.callproc("api.validate_name", (hostname,))
|
c.callproc("api.validate_name", (hostname,))
|
||||||
valid = False
|
valid = False
|
||||||
if hostname == c.fetchall()[0][0]:
|
if hostname == c.fetchall()[0][0]:
|
||||||
valid = True
|
valid = True
|
||||||
c.execute("COMMIT")
|
c.execute("COMMIT")
|
||||||
c.execute("BEGIN")
|
c.execute("BEGIN")
|
||||||
c.callproc("api.initialize", ('root', ))
|
c.callproc("api.initialize", ('root',))
|
||||||
c.callproc("api.check_dns_hostname", (hostname, 'csh.rit.edu'))
|
c.callproc("api.check_dns_hostname", (hostname, 'csh.rit.edu'))
|
||||||
available = False
|
available = False
|
||||||
if not c.fetchall()[0][0]:
|
if not c.fetchall()[0][0]:
|
||||||
|
@ -66,7 +79,7 @@ def register_starrs(starrs, name, owner, mac, addr):
|
||||||
c = starrs.cursor()
|
c = starrs.cursor()
|
||||||
try:
|
try:
|
||||||
c.execute("BEGIN")
|
c.execute("BEGIN")
|
||||||
c.callproc("api.initialize", ('root', ))
|
c.callproc("api.initialize", ('root',))
|
||||||
c.callproc(
|
c.callproc(
|
||||||
"api.create_system_quick",
|
"api.create_system_quick",
|
||||||
(name, owner, 'members', mac, addr, 'csh.rit.edu', 'dhcp', True))
|
(name, owner, 'members', mac, addr, 'csh.rit.edu', 'dhcp', True))
|
||||||
|
@ -81,7 +94,7 @@ def delete_starrs(starrs, name):
|
||||||
c = starrs.cursor()
|
c = starrs.cursor()
|
||||||
try:
|
try:
|
||||||
c.execute("BEGIN")
|
c.execute("BEGIN")
|
||||||
c.callproc("api.initialize", ('root', ))
|
c.callproc("api.initialize", ('root',))
|
||||||
c.callproc("api.remove_system", (name, ))
|
c.callproc("api.remove_system", (name, ))
|
||||||
results = c.fetchall()
|
results = c.fetchall()
|
||||||
c.execute("COMMIT")
|
c.execute("COMMIT")
|
||||||
|
|
|
@ -452,3 +452,61 @@ $("#create-vm").click(function(){
|
||||||
swal("Uh oh...", `You must enter a disk size for your VM!`, "error");
|
swal("Uh oh...", `You must enter a disk size for your VM!`, "error");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#change-cores").click(function(){
|
||||||
|
const vmid = $(this).data('vmid')
|
||||||
|
const cur_cores = $(this).data('cores')
|
||||||
|
const usage = $(this).data('usage')
|
||||||
|
const limit = $(this).data('limit')
|
||||||
|
var core_list = document.createElement('select');
|
||||||
|
core_list.setAttribute('style', 'width: 25px');
|
||||||
|
for (i = 1; i < limit - usage + 1; i++) {
|
||||||
|
core_list.appendChild(new Option(i, i));
|
||||||
|
}
|
||||||
|
swal({
|
||||||
|
title: 'Select how many cores you would like to allocate to this VM:',
|
||||||
|
content: core_list,
|
||||||
|
buttons: {
|
||||||
|
cancel: {
|
||||||
|
text: "Cancel",
|
||||||
|
visible: true,
|
||||||
|
closeModal: true,
|
||||||
|
className: "",
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
text: "Select",
|
||||||
|
closeModal: false,
|
||||||
|
className: "swal-button",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((willChange) => {
|
||||||
|
if (willChange) {
|
||||||
|
const cores = $(core_list).val()
|
||||||
|
fetch(`/proxstar/vm/${vmid}/cpu/${cores}`, {
|
||||||
|
credentials: 'same-origin',
|
||||||
|
method: 'post'
|
||||||
|
}).then((response) => {
|
||||||
|
return swal(`Now applying the change to the number of cores!`, {
|
||||||
|
icon: "success",
|
||||||
|
buttons: {
|
||||||
|
ok: {
|
||||||
|
text: "OK",
|
||||||
|
closeModal: true,
|
||||||
|
className: "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).then(() => {
|
||||||
|
window.location = `/proxstar/vm/${vmid}`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
if (err) {
|
||||||
|
swal("Uh oh...", `Unable to change the number of cores. Please try again later.`, "error");
|
||||||
|
} else {
|
||||||
|
swal.stopLoading();
|
||||||
|
swal.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -72,7 +72,20 @@
|
||||||
<dt>Status</dt>
|
<dt>Status</dt>
|
||||||
<dd>{{ vm['qmpstatus'] }}</dd>
|
<dd>{{ vm['qmpstatus'] }}</dd>
|
||||||
<dt>Cores</dt>
|
<dt>Cores</dt>
|
||||||
<dd>{{ vm['config']['cores'] * vm['config'].get('sockets', 1) }}</dd>
|
<dd>
|
||||||
|
{{ vm['config']['cores'] * vm['config'].get('sockets', 1) }}
|
||||||
|
{% if limits['cpu'] - usage['cpu'] > 0 %}
|
||||||
|
{% if vm['qmpstatus'] == 'running' or vm['qmpstatus'] == 'paused' %}
|
||||||
|
<button class="btn btn-default proxstar-changebtn" id="change-cores" data-vmid="{{ vm['vmid'] }}" data-cores="{{ vm['config']['cores'] * vm['config'].get('sockets', 1) }}" data-usage="{{ usage['cpu'] - (vm['config']['cores'] * vm['config'].get('sockets', 1)) }}" data-limit="{{ limits['cpu'] }}">
|
||||||
|
<span class="glyphicon glyphicon-cog"></span>
|
||||||
|
</button>
|
||||||
|
{% else %}
|
||||||
|
<button class="btn btn-default proxstar-changebtn" id="change-cores" data-vmid="{{ vm['vmid'] }}" data-cores="{{ vm['config']['cores'] * vm['config'].get('sockets', 1) }}" data-usage="{{ usage['cpu'] }}" data-limit="{{ limits['cpu'] }}">
|
||||||
|
<span class="glyphicon glyphicon-cog"></span>
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
</dd>
|
||||||
<dt>Memory</dt>
|
<dt>Memory</dt>
|
||||||
<dd>{{ vm['config']['memory'] // 1024}} GB</dd>
|
<dd>{{ vm['config']['memory'] // 1024}} GB</dd>
|
||||||
<dt>Expiration</dt>
|
<dt>Expiration</dt>
|
||||||
|
|
Loading…
Reference in a new issue