mirror of
https://github.com/ComputerScienceHouse/proxstar.git
synced 2025-03-09 15:40:09 +00:00
added ability for user to eject and change iso
This commit is contained in:
parent
ba36af7dd5
commit
dd98c600e2
5 changed files with 171 additions and 17 deletions
27
app.py
27
app.py
|
@ -35,6 +35,12 @@ def list_vms():
|
||||||
return render_template('list_vms.html', username='com6056', vms=vms)
|
return render_template('list_vms.html', username='com6056', vms=vms)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/isos")
|
||||||
|
def isos():
|
||||||
|
isos = get_isos(proxmox, app.config['PROXMOX_ISO_STORAGE'])
|
||||||
|
return ','.join(isos)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/vm/<string:vmid>")
|
@app.route("/vm/<string:vmid>")
|
||||||
def vm_details(vmid):
|
def vm_details(vmid):
|
||||||
if int(vmid) in get_user_allowed_vms(proxmox, user):
|
if int(vmid) in get_user_allowed_vms(proxmox, user):
|
||||||
|
@ -42,7 +48,7 @@ def vm_details(vmid):
|
||||||
vm['vmid'] = vmid
|
vm['vmid'] = vmid
|
||||||
vm['config'] = get_vm_config(proxmox, vmid)
|
vm['config'] = get_vm_config(proxmox, vmid)
|
||||||
vm['disks'] = get_vm_disks(proxmox, vmid, config=vm['config'])
|
vm['disks'] = get_vm_disks(proxmox, vmid, config=vm['config'])
|
||||||
vm['isos'] = get_vm_isos(proxmox, vmid, config=vm['config'])
|
vm['iso'] = get_vm_iso(proxmox, vmid, config=vm['config'])
|
||||||
vm['interfaces'] = get_vm_interfaces(
|
vm['interfaces'] = get_vm_interfaces(
|
||||||
proxmox, vm['vmid'], config=vm['config'])
|
proxmox, vm['vmid'], config=vm['config'])
|
||||||
return render_template('vm_details.html', username='com6056', vm=vm)
|
return render_template('vm_details.html', username='com6056', vm=vm)
|
||||||
|
@ -59,6 +65,25 @@ def vm_power(vmid, action):
|
||||||
return '', 403
|
return '', 403
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/vm/<string:vmid>/eject", methods=['POST'])
|
||||||
|
def iso_eject(vmid):
|
||||||
|
if int(vmid) in get_user_allowed_vms(proxmox, user):
|
||||||
|
eject_vm_iso(proxmox, vmid)
|
||||||
|
return '', 200
|
||||||
|
else:
|
||||||
|
return '', 403
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/vm/<string:vmid>/mount/<string:iso>", methods=['POST'])
|
||||||
|
def iso_mount(vmid, iso):
|
||||||
|
if int(vmid) in get_user_allowed_vms(proxmox, user):
|
||||||
|
iso = "{}:iso/{}".format(app.config['PROXMOX_ISO_STORAGE'], iso)
|
||||||
|
mount_vm_iso(proxmox, vmid, iso)
|
||||||
|
return '', 200
|
||||||
|
else:
|
||||||
|
return '', 403
|
||||||
|
|
||||||
|
|
||||||
@app.route("/vm/<string:vmid>/delete", methods=['POST'])
|
@app.route("/vm/<string:vmid>/delete", methods=['POST'])
|
||||||
def delete(vmid):
|
def delete(vmid):
|
||||||
if int(vmid) in get_user_allowed_vms(proxmox, user):
|
if int(vmid) in get_user_allowed_vms(proxmox, user):
|
||||||
|
|
32
proxmox.py
32
proxmox.py
|
@ -106,21 +106,17 @@ def get_vm_disks(proxmox, vmid, config=None):
|
||||||
return disks
|
return disks
|
||||||
|
|
||||||
|
|
||||||
def get_vm_isos(proxmox, vmid, config=None):
|
def get_vm_iso(proxmox, vmid, config=None):
|
||||||
if not config:
|
if not config:
|
||||||
config = get_vm_config(proxmox, vmid)
|
config = get_vm_config(proxmox, vmid)
|
||||||
drives = []
|
if config.get('ide2'):
|
||||||
for key, val in config.items():
|
if config['ide2'].split(',')[0] == 'none':
|
||||||
valid_drive_types = ['ide', 'sata', 'scsi']
|
iso = 'None'
|
||||||
if any(drive_type in key for drive_type in valid_drive_types):
|
else:
|
||||||
if 'cdrom' in val:
|
iso = config['ide2'].split(',')[0].split('/')[1]
|
||||||
if val.split(',')[0] == 'none':
|
else:
|
||||||
iso = 'None'
|
iso = 'None'
|
||||||
else:
|
return iso
|
||||||
iso = val.split(',')[0].split('/')[1]
|
|
||||||
drives.append([key, iso])
|
|
||||||
drives = sorted(drives, key=lambda x: x[0])
|
|
||||||
return drives
|
|
||||||
|
|
||||||
|
|
||||||
def get_user_usage_limits(user):
|
def get_user_usage_limits(user):
|
||||||
|
@ -230,3 +226,13 @@ def get_isos(proxmox, storage):
|
||||||
for iso in proxmox.nodes('proxmox01').storage(storage).content.get():
|
for iso in proxmox.nodes('proxmox01').storage(storage).content.get():
|
||||||
isos.append(iso['volid'].split('/')[1])
|
isos.append(iso['volid'].split('/')[1])
|
||||||
return isos
|
return isos
|
||||||
|
|
||||||
|
|
||||||
|
def eject_vm_iso(proxmox, vmid):
|
||||||
|
node = proxmox.nodes(get_vm_node(proxmox, vmid))
|
||||||
|
node.qemu(vmid).config.post(ide2='none,media=cdrom')
|
||||||
|
|
||||||
|
|
||||||
|
def mount_vm_iso(proxmox, vmid, iso):
|
||||||
|
node = proxmox.nodes(get_vm_node(proxmox, vmid))
|
||||||
|
node.qemu(vmid).config.post(ide2="{},media=cdrom".format(iso))
|
||||||
|
|
|
@ -65,6 +65,22 @@ table, th, td {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.proxstar-ejectbtn {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0px 1px 0px 0px;
|
||||||
|
border-radius: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proxstar-changebtn {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0px 0px 0px 1px;
|
||||||
|
border-radius: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
.resource-usage {
|
.resource-usage {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
|
@ -236,3 +236,102 @@ $("#resume-vm").click(function(){
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#eject-iso").click(function(){
|
||||||
|
const vmid = $(this).data('vmid')
|
||||||
|
const iso = $(this).data('iso')
|
||||||
|
swal({
|
||||||
|
title: `Are you sure you want to eject ${iso}?`,
|
||||||
|
icon: "warning",
|
||||||
|
buttons: {
|
||||||
|
cancel: true,
|
||||||
|
delete: {
|
||||||
|
text: "Eject",
|
||||||
|
closeModal: false,
|
||||||
|
className: "swal-button--danger",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dangerMode: true,
|
||||||
|
})
|
||||||
|
.then((willDelete) => {
|
||||||
|
if (willDelete) {
|
||||||
|
const vmid = $(this).data('vmid')
|
||||||
|
fetch(`/proxstar/vm/${vmid}/eject`, {
|
||||||
|
credentials: 'same-origin',
|
||||||
|
method: 'post'
|
||||||
|
}).then((response) => {
|
||||||
|
return swal(`${iso} is now ejecting!`, {
|
||||||
|
icon: "success",
|
||||||
|
});
|
||||||
|
}).then(() => {
|
||||||
|
window.location = `/proxstar/vm/${vmid}`;
|
||||||
|
}).catch(err => {
|
||||||
|
if (err) {
|
||||||
|
swal("Uh oh...", `Unable to eject ${iso}. Please try again later.`, "error");
|
||||||
|
} else {
|
||||||
|
swal.stopLoading();
|
||||||
|
swal.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$("#change-iso").click(function(){
|
||||||
|
const vmid = $(this).data('vmid')
|
||||||
|
fetch(`/proxstar/isos`, {
|
||||||
|
credentials: 'same-origin',
|
||||||
|
}).then((response) => {
|
||||||
|
return response.text()
|
||||||
|
}).then((text) => {
|
||||||
|
var isos = text.split(',');
|
||||||
|
var iso_list = document.createElement('select');
|
||||||
|
for (i = 0; i < isos.length; i++) {
|
||||||
|
iso_list.appendChild(new Option(isos[i], isos[i]));
|
||||||
|
}
|
||||||
|
swal({
|
||||||
|
title: 'Choose an ISO to mount:',
|
||||||
|
content: iso_list,
|
||||||
|
buttons: {
|
||||||
|
cancel: true,
|
||||||
|
select: {
|
||||||
|
text: "Select",
|
||||||
|
closeModal: false,
|
||||||
|
className: "swal-button",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dangerMode: true,
|
||||||
|
})
|
||||||
|
.then((willDelete) => {
|
||||||
|
if (willDelete) {
|
||||||
|
const vmid = $(this).data('vmid')
|
||||||
|
const iso = $(iso_list).val()
|
||||||
|
fetch(`/proxstar/vm/${vmid}/mount/${iso}`, {
|
||||||
|
credentials: 'same-origin',
|
||||||
|
method: 'post'
|
||||||
|
}).then((response) => {
|
||||||
|
return swal(`${iso} is now being mounted!`, {
|
||||||
|
icon: "success",
|
||||||
|
});
|
||||||
|
}).then(() => {
|
||||||
|
window.location = `/proxstar/vm/${vmid}`;
|
||||||
|
}).catch(err => {
|
||||||
|
if (err) {
|
||||||
|
swal("Uh oh...", `Unable to mount ${iso}. Please try again later.`, "error");
|
||||||
|
} else {
|
||||||
|
swal.stopLoading();
|
||||||
|
swal.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).catch(err => {
|
||||||
|
if (err) {
|
||||||
|
swal("Uh oh...", `Unable to retrieve available ISOs. Please try again later.`, "error");
|
||||||
|
} else {
|
||||||
|
swal.stopLoading();
|
||||||
|
swal.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -43,9 +43,17 @@
|
||||||
<li>{{ disk[0] }}: {{ disk[1] }}</li>
|
<li>{{ disk[0] }}: {{ disk[1] }}</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<li class="nav-header">ISO</li>
|
<li class="nav-header">ISO</li>
|
||||||
{% for iso in vm['isos'] %}
|
<li>
|
||||||
<li>{{ iso[1] }}</li>
|
{{ vm['iso'] }}
|
||||||
{% endfor %}
|
{% if vm['iso'] != 'None' %}
|
||||||
|
<button class="btn btn-danger proxstar-ejectbtn" id="eject-iso" name="eject" data-vmid="{{ vm['vmid'] }}" data-iso="{{ vm['iso'] }}">
|
||||||
|
<span class="glyphicon glyphicon-eject"></span>
|
||||||
|
</button>
|
||||||
|
{% endif %}
|
||||||
|
<button class="btn btn-default proxstar-changebtn" id="change-iso" name="change" data-vmid="{{ vm['vmid'] }}" data-iso="{{ vm['iso'] }}">
|
||||||
|
<span class="glyphicon glyphicon-cog"></span>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue