mirror of
https://github.com/ComputerScienceHouse/proxstar.git
synced 2025-02-14 14:01:51 +00:00
use javascript for vm creation, show warnings if fields arent filled, display IP instead of MAC for interfaces
This commit is contained in:
parent
5198780746
commit
6d589f7bf8
7 changed files with 173 additions and 66 deletions
34
app.py
34
app.py
|
@ -41,19 +41,32 @@ def isos():
|
|||
return ','.join(isos)
|
||||
|
||||
|
||||
@app.route("/hostname/<string:name>")
|
||||
def hostname(name):
|
||||
starrs = connect_starrs(
|
||||
app.config['STARRS_DB_NAME'], app.config['STARRS_DB_USER'],
|
||||
app.config['STARRS_DB_HOST'], app.config['STARRS_DB_PASS'])
|
||||
result = check_hostname(starrs, name)
|
||||
return str(result)
|
||||
|
||||
|
||||
@app.route("/vm/<string:vmid>")
|
||||
def vm_details(vmid):
|
||||
proxmox = connect_proxmox(app.config['PROXMOX_HOST'],
|
||||
app.config['PROXMOX_USER'],
|
||||
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):
|
||||
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['iso'] = get_vm_iso(proxmox, vmid, config=vm['config'])
|
||||
vm['interfaces'] = get_vm_interfaces(
|
||||
proxmox, vm['vmid'], config=vm['config'])
|
||||
vm['interfaces'] = []
|
||||
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['expire'] = get_vm_expire(vmid, app.config['VM_EXPIRE_MONTHS']).strftime('%m/%d/%Y')
|
||||
return render_template('vm_details.html', username='com6056', vm=vm)
|
||||
else:
|
||||
|
@ -152,7 +165,7 @@ def create():
|
|||
elif request.method == 'POST':
|
||||
name = request.form['name']
|
||||
cores = request.form['cores']
|
||||
memory = request.form['memory']
|
||||
memory = request.form['mem']
|
||||
disk = request.form['disk']
|
||||
iso = request.form['iso']
|
||||
if iso != 'none':
|
||||
|
@ -161,13 +174,14 @@ def create():
|
|||
if usage_check:
|
||||
return usage_check
|
||||
else:
|
||||
vmid, mac = create_vm(proxmox, starrs, user, name, cores, memory,
|
||||
disk, iso)
|
||||
register_starrs(starrs, name, user, mac,
|
||||
get_next_ip(starrs,
|
||||
app.config['STARRS_IP_RANGE'])[0][0])
|
||||
get_vm_expire(vmid, app.config['VM_EXPIRE_MONTHS'])
|
||||
return redirect("/proxstar/vm/{}".format(vmid))
|
||||
if not check_hostname(starrs, name):
|
||||
vmid, mac = create_vm(proxmox, starrs, user, name, cores, memory,
|
||||
disk, iso)
|
||||
register_starrs(starrs, name, user, mac,
|
||||
get_next_ip(starrs,
|
||||
app.config['STARRS_IP_RANGE'])[0][0])
|
||||
get_vm_expire(vmid, app.config['VM_EXPIRE_MONTHS'])
|
||||
return vmid
|
||||
|
||||
|
||||
@app.route('/novnc/<path:path>')
|
||||
|
|
|
@ -82,9 +82,9 @@ def get_vm_disk_size(proxmox, vmid, config=None, name='virtio0'):
|
|||
config = get_vm_config(proxmox, vmid)
|
||||
disk_size = config[name].split(',')
|
||||
if 'size' in disk_size[0]:
|
||||
disk_size = disk_size[0].split('=')[1]
|
||||
disk_size = disk_size[0].split('=')[1].rstrip('G')
|
||||
else:
|
||||
disk_size = disk_size[1].split('=')[1]
|
||||
disk_size = disk_size[1].split('=')[1].rstrip('G')
|
||||
return disk_size
|
||||
|
||||
|
||||
|
@ -98,9 +98,9 @@ def get_vm_disks(proxmox, vmid, config=None):
|
|||
if 'cdrom' not in val:
|
||||
disk_size = val.split(',')
|
||||
if 'size' in disk_size[0]:
|
||||
disk_size = disk_size[0].split('=')[1]
|
||||
disk_size = disk_size[0].split('=')[1].rstrip('G')
|
||||
else:
|
||||
disk_size = disk_size[1].split('=')[1]
|
||||
disk_size = disk_size[1].split('=')[1].rstrip('G')
|
||||
disks.append([key, disk_size])
|
||||
disks = sorted(disks, key=lambda x: x[0])
|
||||
return disks
|
||||
|
|
26
starrs.py
26
starrs.py
|
@ -25,6 +25,32 @@ def get_next_ip(starrs, range_name):
|
|||
return results
|
||||
|
||||
|
||||
def get_ip_for_mac(starrs, mac):
|
||||
c = starrs.cursor()
|
||||
try:
|
||||
c.execute("BEGIN")
|
||||
c.callproc("api.initialize", ('root', ))
|
||||
c.callproc("api.get_system_interface_addresses", (mac.lower(), ))
|
||||
results = c.fetchall()
|
||||
c.execute("COMMIT")
|
||||
finally:
|
||||
c.close()
|
||||
return results
|
||||
|
||||
|
||||
def check_hostname(starrs, hostname):
|
||||
c = starrs.cursor()
|
||||
try:
|
||||
c.execute("BEGIN")
|
||||
c.callproc("api.initialize", ('root', ))
|
||||
c.callproc("api.check_dns_hostname", (hostname, 'csh.rit.edu'))
|
||||
results = c.fetchall()
|
||||
c.execute("COMMIT")
|
||||
finally:
|
||||
c.close()
|
||||
return results[0][0]
|
||||
|
||||
|
||||
def register_starrs(starrs, name, owner, mac, addr):
|
||||
c = starrs.cursor()
|
||||
try:
|
||||
|
|
|
@ -91,6 +91,6 @@ table, th, td {
|
|||
}
|
||||
|
||||
.resource-usage {
|
||||
width: 50%;
|
||||
margin: 0 auto;
|
||||
width: 50%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
|
|
@ -52,8 +52,8 @@ $("#stop-vm").click(function(){
|
|||
},
|
||||
dangerMode: true,
|
||||
})
|
||||
.then((willDelete) => {
|
||||
if (willDelete) {
|
||||
.then((willStop) => {
|
||||
if (willStop) {
|
||||
const vmid = $(this).data('vmid')
|
||||
fetch(`/proxstar/vm/${vmid}/power/stop`, {
|
||||
credentials: 'same-origin',
|
||||
|
@ -91,8 +91,8 @@ $("#reset-vm").click(function(){
|
|||
},
|
||||
dangerMode: true,
|
||||
})
|
||||
.then((willDelete) => {
|
||||
if (willDelete) {
|
||||
.then((willReset) => {
|
||||
if (willReset) {
|
||||
const vmid = $(this).data('vmid')
|
||||
fetch(`/proxstar/vm/${vmid}/power/reset`, {
|
||||
credentials: 'same-origin',
|
||||
|
@ -130,8 +130,8 @@ $("#shutdown-vm").click(function(){
|
|||
},
|
||||
dangerMode: true,
|
||||
})
|
||||
.then((willDelete) => {
|
||||
if (willDelete) {
|
||||
.then((willShutdown) => {
|
||||
if (willShutdown) {
|
||||
const vmid = $(this).data('vmid')
|
||||
fetch(`/proxstar/vm/${vmid}/power/shutdown`, {
|
||||
credentials: 'same-origin',
|
||||
|
@ -169,8 +169,8 @@ $("#suspend-vm").click(function(){
|
|||
},
|
||||
dangerMode: true,
|
||||
})
|
||||
.then((willDelete) => {
|
||||
if (willDelete) {
|
||||
.then((willSuspend) => {
|
||||
if (willSuspend) {
|
||||
const vmid = $(this).data('vmid')
|
||||
fetch(`/proxstar/vm/${vmid}/power/suspend`, {
|
||||
credentials: 'same-origin',
|
||||
|
@ -258,8 +258,8 @@ $("#eject-iso").click(function(){
|
|||
},
|
||||
dangerMode: true,
|
||||
})
|
||||
.then((willDelete) => {
|
||||
if (willDelete) {
|
||||
.then((willEject) => {
|
||||
if (willEject) {
|
||||
const vmid = $(this).data('vmid')
|
||||
fetch(`/proxstar/vm/${vmid}/eject`, {
|
||||
credentials: 'same-origin',
|
||||
|
@ -320,8 +320,8 @@ $("#change-iso").click(function(){
|
|||
},
|
||||
dangerMode: true,
|
||||
})
|
||||
.then((willDelete) => {
|
||||
if (willDelete) {
|
||||
.then((willChange) => {
|
||||
if (willChange) {
|
||||
const vmid = $(this).data('vmid')
|
||||
const iso = $(iso_list).val()
|
||||
fetch(`/proxstar/vm/${vmid}/mount/${iso}`, {
|
||||
|
@ -381,3 +381,72 @@ $("#renew-vm").click(function(){
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("#create-vm").click(function(){
|
||||
const name = document.getElementById('name').value
|
||||
const cores = document.getElementById('cores').value
|
||||
const mem = document.getElementById('mem').value
|
||||
const disk = document.getElementById('disk').value
|
||||
const iso = document.getElementById('iso').value
|
||||
if (name && disk) {
|
||||
fetch(`/proxstar/hostname/${name}`, {
|
||||
credentials: 'same-origin',
|
||||
}).then((response) => {
|
||||
return response.text()
|
||||
}).then((text) => {
|
||||
if (text == "False") {
|
||||
var loader = document.createElement('div');
|
||||
loader.setAttribute('class', 'loader');
|
||||
var info = document.createElement('span');
|
||||
info.innerHTML = `Cores: ${cores}<br>Memory: ${mem/1024} GB<br>Disk: ${disk} GB<br>ISO: ${iso}`,
|
||||
swal({
|
||||
title: `Are you sure you want to create ${name}?`,
|
||||
content: info,
|
||||
icon: "info",
|
||||
buttons: {
|
||||
cancel: true,
|
||||
create: {
|
||||
text: "Create",
|
||||
closeModal: false,
|
||||
className: "swal-button",
|
||||
}
|
||||
}
|
||||
})
|
||||
.then((willCreate) => {
|
||||
if (willCreate) {
|
||||
var data = new FormData();
|
||||
data.append('name', name);
|
||||
data.append('cores', cores);
|
||||
data.append('mem', mem);
|
||||
data.append('disk', disk);
|
||||
data.append('iso', iso);
|
||||
fetch('/proxstar/vm/create', {
|
||||
credentials: 'same-origin',
|
||||
method: 'post',
|
||||
body: data
|
||||
}).then((response) => {
|
||||
return response.text()
|
||||
}).then((vmid) => {
|
||||
window.location = `/proxstar/vm/${vmid}`;
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
swal("Uh oh...", `That name is already taken! Please try another name.`, "error");
|
||||
}
|
||||
}).catch(err => {
|
||||
if (err) {
|
||||
swal("Uh oh...", `Unable to verify name. Please try again later.`, "error");
|
||||
} else {
|
||||
swal.stopLoading();
|
||||
swal.close();
|
||||
}
|
||||
});
|
||||
} else if (!name && !disk) {
|
||||
swal("Uh oh...", `You must enter a name and disk size for your VM!`, "error");
|
||||
} else if (!name) {
|
||||
swal("Uh oh...", `You must enter a name for your VM!`, "error");
|
||||
} else if (!disk) {
|
||||
swal("Uh oh...", `You must enter a disk size for your VM!`, "error");
|
||||
}
|
||||
});
|
||||
|
|
|
@ -16,42 +16,40 @@
|
|||
{% endfor %}
|
||||
<p>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.</p>
|
||||
{% else %}
|
||||
<form action="create" method="post">
|
||||
<div class="form-group">
|
||||
<label for="name">VM Name</label>
|
||||
<input type="text" name="name" class="form-control">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="cores">Cores</label>
|
||||
<select name="cores" class="form-control">
|
||||
{% for i in range(1, 4 - usage['cpu'] + 1) %}
|
||||
<option value="{{ i }}">{{ i }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="memory">Memory</label>
|
||||
<select name="memory" class="form-control">
|
||||
{% for i in range(1, 4 - usage['mem'] + 1) %}
|
||||
<option value="{{ i * 1024 }}">{{ i }}GB</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="disk">Disk</label>
|
||||
<input type="text" name="disk" class="form-control">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="iso">ISO</label>
|
||||
<select name="iso" class="form-control">
|
||||
<option value="none"></option>
|
||||
{% for iso in isos %}
|
||||
<option value="{{ iso }}">{{ iso }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<button class="btn btn-success" type="submit" value="Create">Create</button>
|
||||
</form>
|
||||
<div class="form-group">
|
||||
<label for="name">VM Name</label>
|
||||
<input type="text" name="name" id="name" class="form-control">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="cores">Cores</label>
|
||||
<select name="cores" id="cores" class="form-control">
|
||||
{% for i in range(1, limits['cpu'] - usage['cpu'] + 1) %}
|
||||
<option value="{{ i }}">{{ i }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="mem">Memory</label>
|
||||
<select name="mem" id="mem" class="form-control">
|
||||
{% for i in range(1, limits['mem'] - usage['mem'] + 1) %}
|
||||
<option value="{{ i * 1024 }}">{{ i }}GB</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="disk">Disk</label>
|
||||
<input type="text" name="disk" id="disk" class="form-control">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="iso">ISO</label>
|
||||
<select name="iso" id="iso" class="form-control">
|
||||
<option value="none"></option>
|
||||
{% for iso in isos %}
|
||||
<option value="{{ iso }}">{{ iso }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<button class="btn btn-success" id="create-vm" name="create">CREATE</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
{% endfor %}
|
||||
<li class="nav-header">Disks</li>
|
||||
{% for disk in vm['disks'] %}
|
||||
<li>{{ disk[0] }}: {{ disk[1] }}</li>
|
||||
<li>{{ disk[0] }}: {{ disk[1] }} GB</li>
|
||||
{% endfor %}
|
||||
<li class="nav-header">ISO</li>
|
||||
<li>
|
||||
|
@ -74,7 +74,7 @@
|
|||
<dt>Cores</dt>
|
||||
<dd>{{ vm['config']['cores'] * vm['config'].get('sockets', 1) }}</dd>
|
||||
<dt>Memory</dt>
|
||||
<dd>{{ vm['config']['memory'] }} MB</dd>
|
||||
<dd>{{ vm['config']['memory'] // 1024}} GB</dd>
|
||||
<dt>Expiration</dt>
|
||||
<dd>
|
||||
{{ vm['expire'] }}
|
||||
|
|
Loading…
Reference in a new issue