first commit

This commit is contained in:
root
2023-10-17 10:03:51 +02:00
commit 73bd0f460c
2265 changed files with 384897 additions and 0 deletions

36
templates/backup.html Normal file
View File

@@ -0,0 +1,36 @@
{% extends 'layout.html' %}
{% block content %}
{% include 'menu.html' %}
<div class="container">
<table class="table">
{% for lxc in list_snap_lxc %}
<tr><td>
<p class="fw-light">{{ lxc[0] }}</p>
</td><td>
{% for snap_lxc in lxc[1] %}
<table class="table"><tr><th>
{{ snap_lxc }}</th><th>
<form action="/rest_snap_lxc" method="post"><input type="hidden" name="lxc_name" value="{{ lxc[0] }}"><button type="submit" class="btn btn-outline-secondary btn-hype" name="item" value="{{ snap_lxc }}" onclick="loading();"><i class="fa-solid fa-rotate-left"></i></button></form>
</th><th>
<form action="/del_snap_lxc" method="post"><input type="hidden" name="lxc_name" value="{{ lxc[0] }}"><button type="submit" class="btn btn-outline-danger btn-hype" name="item" value="{{ snap_lxc }}" onclick="loading();"><i class="fas fa-trash"></i</button></form>
</th></tr></table>
{% endfor %}
</td></tr>
{% endfor %}
{% for vm in list_snap_vm %}
<tr><td>
<p class="fw-light">{{ vm[0] }}</p>
</td><td>
{% for snap_vm in vm[1] %}
<table class="table"><tr><th>
{{ snap_vm }}</th><th>
<button type="submit" class="btn btn-outline-secondary btn-hype" value="{{ snap }}" name="start" onclick="loading();"><i class="fa-solid fa-rotate-left"></i></button>
</th><th>
<button type="submit" class="btn btn-outline-danger btn-hype" value="{{ snap }}" name="start" onclick="loading();"><i class="fa-solid fa-trash"></i></button>
</th></tr></table>
{% endfor %}
</td></tr>
{% endfor %}
</table>
</div>
{% endblock %}

70
templates/build.html Normal file
View File

@@ -0,0 +1,70 @@
{% extends 'layout.html' %}
{% block content %}
{% include 'menu.html' %}
<div class="container">
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<i class="fa fa-cube"></i> - Build Container
</div>
<div class="card-body">
<form action="/creation" method="post">
<label for="cnom">Name</label>
<input type="text" id="cnom" name="nom" class="form-control" placeholder="Container" required><br>
<label for="cip">Optional static IP</label>
<input type="text" id="cip" name="ip" class="form-control" placeholder="192.168.XX.XX/YY"><br>
<label for="oslist">OS</label>
<select id="oslist" name="os" class="form-control">
{%for dist in list_lxc_os %}
<option value={{ dist[1] }}>{{ dist[0] }}</option>
{%endfor%}
</select><br>
<button name="creation" class="btn btn-outline-secondary btn-hype" type="submit" onclick="loading();">Create</button>
</form>
</div>
</div>
</div>
</div>
<br>
<div class="card">
<div class="card-header">
<i class="fa-solid fa-desktop"></i> - Create Virtual Server
</div>
<div class="card-body">
<form action="/creationvm" method="post">
<label for="nom">Name</label>
<input type="text" name="vm_name" class="form-control" placeholder="Server" required><br>
<label for="ram">Memory (in MiB)</label>
<input type="text" name="ram" class="form-control" placeholder="1024" required><br>
<label for="cpu">vCPU</label>
<input type="text" name="cpu" class="form-control" placeholder="1" required><br>
<label for="disk">Disk (in GB)</label>
<input type="text" class="form-control" name="disk" placeholder="10" required><br>
<label for="os">OS</label>
<select id="profilelist" class="form-control" name="os" placeholder="Profile" required>
{%for profile in list_profiles %}
<option value={{ profile }}>{{ profile }}</option>
{%endfor%}
</select><br>
<label for="iso">ISO</label>
<select id="isolist" class="form-control" name="iso" required>
{%for iso in list_iso %}
<option value={{ iso[0] }}>{{ iso[0] }}</option>
{%endfor%}
</select><br>
<label for="net">Network</label>
<select id="netlist" class="form-control" name="net" required>
{%for net in list_net %}
<option value={{ net }}>{{ net }}</option>
{%endfor%}
</select><br>
<button name="creation" class="btn btn-outline-secondary btn-hype" type="submit" onclick="loading();">Create</button>
</form>
</div>
</div>
</div>
{% endblock %}

239
templates/index.html Normal file
View File

@@ -0,0 +1,239 @@
{% extends 'layout.html' %}
{% block content %}
{% include 'menu.html' %}
<div class="container">
<div class="row">
<div class="col-4">
<div class="card">
<div class="card-header">
Hostname
</div>
<div class="card-body">
<h1 class="display-6">{{ host.hostname }}</h1>
Last boot : {{ host.boot_time }}
</div>
</div>
</div>
<div class="col-4">
<div class="card">
<div class="card-header">
LXC
</div>
<div class="card-body">
<h1 class="display-6" style="color:green">Up : {{ lxc_up }}</h1>
<p style="color:red" class="fw-light">Down : {{ lxc_down }}</p>
</div>
</div>
</div>
<div class="col-4">
<div class="card">
<div class="card-header">
VM
</div>
<div class="card-body">
<h1 class="display-6" style="color:green">Up : {{ vm_up }}</h1>
<p style="color:red" class="fw-light">Down : {{ vm_down }}</p>
</div>
</div>
</div>
</div>
<br>
<!-- Monit -->
<div class="row">
<div class="col-6">
<div class="card">
<div class="card-header">
Monitor
</div>
<div class="card-body">
<canvas id="canvas"></canvas>
</div>
</div>
</div>
<div class="col-6">
<div class="card">
<div class="card-header">
Usage
</div>
<div class="card-body">
<p class="fw-light">CPU</p>
<div class="progress">
<div id="cpubar" class="progress-bar progress-bar-striped" role="progressbar" style="width: {{ full['cpu']['percent'] }}%;" aria-valuenow={{ full['cpu']['percent'] }} aria-valuemin="0" aria-valuemax="100">{{ full['cpu']['percent'] }}%</div>
</div>
<small class="form-text text-muted" id="cpudetail">
user : {{ full['cpu']['time_user'] }} / nice : {{ full['cpu']['time_nice'] }} / system : {{ full['cpu']['time_system'] }} / idle : {{ full['cpu']['time_idle'] }} / iowait : {{ full['cpu']['time_iowait'] }} / irq : {{ full['cpu']['time_irq'] }} / softirq : {{ full['cpu']['time_softirq'] }} / steal : {{ full['cpu']['time_steal'] }} / guest : {{ full['cpu']['time_guest'] }} / guest nice : {{ full['cpu']['time_guest_nice'] }}
</small>
<br><br>
<p class="fw-light">MEM</p>
<div class="progress">
<div id="membar" class="progress-bar bg-warning progress-bar-striped" role="progressbar" style="width: {{ full['mem']['percent'] }}%;" aria-valuenow={{ full['mem']['percent'] }} aria-valuemin="0" aria-valuemax="100">{{ full['mem']['percent'] }}%</div>
</div>
<small class="form-text text-muted" id="memdetail">
total : {{ full['mem']['total'] }} / available : {{ full['mem']['available'] }} / used : {{ full['mem']['used'] }} / free : {{ full['mem']['free'] }} / active : {{ full['mem']['active'] }} / inactive : {{ full['mem']['inactive'] }} / buffers : {{ full['mem']['buffers'] }} / cached : {{ full['mem']['cached'] }} / shared : {{ full['mem']['shared'] }} / slab : {{ full['mem']['slab'] }}
</small>
<br><br>
<p class="fw-light">SWAP</p>
<div class="progress">
<div id="swapbar" class="progress-bar bg-danger progress-bar-striped" role="progressbar" style="width: {{ full['swap']['percent'] }}%;" aria-valuenow={{ full['swap']['percent'] }} aria-valuemin="0" aria-valuemax="100">{{ full['swap']['percent'] }}%</div>
</div>
<small class="form-text text-muted" id="swapdetail">
total : {{ full['swap']['total'] }} / used : {{ full['swap']['used'] }} / free : {{ full['swap']['free'] }} / sin : {{ full['swap']['sin'] }} / sout : {{ full['swap']['sout'] }}
</small>
</div>
</div>
</div>
</div>
<br>
<!-- Disk -->
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
Disks
</div>
<div class="card-body">
{% for key in full %}
{% if key.startswith('disk_') %}
<br>
<p class="fw-light">{{ full[key]['mountpoint'] }}</p>
<div class="progress">
<div class="progress-bar bg-info" role="progressbar" style="width: {{ full[key]['size_percent'] }}%;" aria-valuenow={{ full[key]['size_percent'] }} aria-valuemin="0" aria-valuemax="100">{{ full[key]['size_percent'] }}%</div>
</div>
<small class="form-text text-muted">
total : {{ full[key]['size_total'] }} / used : {{ full[key]['size_used'] }} / free : {{ full[key]['size_free'] }} / device : {{ full[key]['device'] }} / fstype : {{ full[key]['fstype'] }} / opt: {{ full[key]['opts'] }} / maxfile : {{ full[key]['maxfile'] }} / maxpath : {{ full[key]['maxpath'] }}
</small>
</br>
{% endif %}
{% endfor %}
</div>
</div>
</div>
</div>
<br>
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
Network
</div>
<div class="card-body">
<table class="table fw-light">
<tr><td>Name</td><td>IPv4</td><td>Netmask v4</td><td>IPv6</td><td>Netmask v6</td><td>Sent</td><td>Received</td></tr>
{% for key in full %}
{% if key.startswith('net_') %}
<tr><td>{{ full[key]['name'] }}</td><td>{{ full[key]['address_v4'] }}</td><td>{{ full[key]['netmask_v4'] }}</td><td>{{ full[key]['address_v6'] }}</td><td>{{ full[key]['netmask_v6'] }}</td><td>{{ full[key]['bytes_sent'] }}</td><td>{{ full[key]['bytes_recv'] }}</td><tr>
{% endif %}
{% endfor %}
</table>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
const config = {
type: 'line',
data: {
labels: Array(60).fill("0000-00-00 00:00:00"),
datasets: [{
label: "CPU %",
backgroundColor: 'rgb(0, 191, 255)',
borderColor: 'rgb(0, 191, 255)',
data: Array(60).fill(null),
fill: false,
pointRadius: 0,
},{
label: "Mem %",
backgroundColor: 'rgb(255,200,20)',
borderColor: 'rgb(255,200,20)',
data: Array(60).fill(null),
fill: false,
pointRadius: 0,
},{
label: "Swap %",
backgroundColor: 'rgb(255, 20, 100)',
borderColor: 'rgb(255, 20, 100)',
data: Array(60).fill(null),
fill: false,
pointRadius: 0,
}],
},
options: {
responsive: true,
title: {
display: false,
},
tooltips: {
mode: 'index',
intersect: false,
},
hover: {
mode: 'nearest',
intersect: true
},
scales: {
xAxes: [{
display: false,
scaleLabel: {
display: true,
labelString: 'Time'
}
}],
yAxes: [{
display: true,
scaleLabel: [{
display: true,
labelString: 'CPU'
},{
display: true,
labelString: 'Mem'
},{
display: true,
labelString: 'Swap'
}]
}]
}
}
};
const context = document.getElementById('canvas').getContext('2d');
const lineChart = new Chart(context, config);
const source = new EventSource("/chart-ressources/");
source.onmessage = function (event) {
const data = JSON.parse(event.data);
if (config.data.labels.length === 60) {
config.data.labels.shift();
config.data.datasets[0].data.shift();
config.data.datasets[1].data.shift();
config.data.datasets[2].data.shift();
}
config.data.labels.push(data.time);
config.data.datasets[0].data.push(data.cpu_percent);
config.data.datasets[1].data.push(data.mem_percent);
config.data.datasets[2].data.push(data.swap_percent);
lineChart.update();
$("#cpubar").html(data.cpu_percent+"%");
$("#membar").html(data.mem_percent+"%");
$("#swapbar").html(data.swap_percent+"%");
$("#cpudetail").html("user : "+data.cpu_time_user+" / nice : "+data.cpu_time_nice+" / system : "+data.cpu_time_system+" / idle : "+data.cpu_time_idle+" / iowait : "+data.cpu_time_iowait+" / irq : "+data.cpu_time_irq+" / softirq : "+data.cpu_time_softirq+" / steal : "+data.cpu_time_steal+" / guest : "+data.cpu_time_guest+" / guest nice : "+data.cpu_time_guest_nice);
$("#swapdetail").html("total : "+data.swap_total+" / used : "+data.swap_used+" / free : "+data.swap_free+" / sin : "+data.swap_sin+" / sout : "+data.swap_sout);
$("#memdetail").html("total : "+data.mem_total+" / available : "+data.mem_available+" / used : "+data.mem_used+" / free : "+data.mem_free+" / active : "+data.mem_active+" / inactive : "+data.mem_inactive+" / buffers : "+data.mem_buffers+" / cached : "+data.mem_cached+" / shared : "+data.mem_shared+" / slab : "+data.mem_slab);
var element_cpubar = document.getElementById("cpubar");
var element_membar = document.getElementById("membar");
var element_swapbar = document.getElementById("swapbar");
var element_cpudetail = document.getElementById("cpudetail");
element_cpubar.style.width = data.cpu_percent+"%"
element_membar.style.width = data.mem_percent+"%"
element_swapbar.style.width = data.swap_percent+"%"
}
});
</script>
{% endblock %}

63
templates/iso.html Normal file
View File

@@ -0,0 +1,63 @@
{% extends 'layout.html' %}
{% block content %}
{% include 'menu.html' %}
<div class="container">
<div class="card">
<div class="card-header">
DropZone
</div>
<div class="card-body">
<form action="{{ url_for('upload_files') }}" class="dropzone" id="file-dropzone">
</div>
</div>
<br>
<div class="card">
<div class="card-header">
ISO
</div>
<div class="card-body">
{%for iso in list_iso %}
<div class="row">
<div class="col-6">
{{ iso[0] }} ( {{ iso[1] }} )
</div>
<div class="col-1">
<form action="/deliso" method="post"><button type="submit" class="btn btn-outline-danger btn-hype" value="{{ iso[0] }}" name="fichier"><i class="fa fa-trash"></i></button></form>
</div>
<div class="col-5">
</div>
</div>
{%endfor%}
</div>
</div>
<br>
<div class="card">
<div class="card-header">
Mount ISO on Virtual Server
</div>
<div class="card-body">
<div class="row">
<div class="col-6">
<form action="/mountiso" method="post">
<select id="isolist" class="form-control" name="iso" required>
{%for iso in list_iso_mount %}
<option value={{ iso[0] }}>{{ iso[0] }}</option>
{%endfor%}
</select>
</div>
<div class="col-5">
<select id="vmlist" class="form-control" name="vm" required>
{%for vm in list_vm %}
<option value={{ vm }}>{{ vm }}</option>
{%endfor%}
</select>
</div>
<div class="col-1">
<button name="mountiso" type="submit" class="btn btn-outline-success btn-hype"><i class="fa fa-check"></i></button>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

158
templates/layout.html Normal file
View File

@@ -0,0 +1,158 @@
<!DOCTYPE html>
<html data-bs-theme="dark">
<head>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hype 2</title>
<link href="{{url_for('static', filename = 'bootstrap.min.css' )}}" rel="stylesheet">
<link href="{{url_for('static', filename = 'Chart.min.css' )}}" rel="stylesheet" >
<link href="{{url_for('static', filename = 'font-awesome/css/fontawesome.css')}}" rel="stylesheet">
<link href="{{url_for('static', filename = 'font-awesome/css/brands.css')}}" rel="stylesheet">
<link href="{{url_for('static', filename = 'font-awesome/css/solid.css')}}" rel="stylesheet">
<link href="{{url_for('static', filename = 'style.css')}}" rel="stylesheet">
<link href="{{url_for('static', filename = 'dropzone.min.css')}}" rel="stylesheet">
<script src="{{url_for('static', filename = 'popper.min.js')}}"></script>
<script src="{{url_for('static', filename = 'bootstrap.bundle.min.js')}}"></script>
<script src="{{url_for('static', filename = 'jquery.min.js')}}"></script>
<script src="{{url_for('static', filename = 'Chart.min.js')}}"></script>
<script src="{{url_for('static', filename = 'dropzone.min.js')}}"></script>
<script src="{{url_for('static', filename = '/core/rfb.js')}}"></script>
<script src="{{url_for('static', filename = '/core/util/strings.js')}}"></script>
<script src="{{url_for('static', filename = '/core/util/element.js')}}"></script>
<script src="{{url_for('static', filename = '/core/util/logging.js')}}"></script>
<script src="{{url_for('static', filename = '/core/util/browser.js')}}"></script>
<script src="{{url_for('static', filename = '/core/util/int.js')}}"></script>
<script src="{{url_for('static', filename = '/core/util/events.js')}}"></script>
<script src="{{url_for('static', filename = '/core/util/eventtarget.js')}}"></script>
<script src="{{url_for('static', filename = '/core/display.js')}}"></script>
<script src="{{url_for('static', filename = '/core/inflator.js')}}"></script>
<script src="{{url_for('static', filename = '/core/deflator.js')}}"></script>
<script src="{{url_for('static', filename = '/core/input/gesturehandler.js')}}"></script>
<script src="{{url_for('static', filename = '/core/input/keyboard.js')}}"></script>
<script src="{{url_for('static', filename = '/core/util/cursor.js')}}"></script>
<script src="{{url_for('static', filename = '/core/websock.js')}}"></script>
<script src="{{url_for('static', filename = '/core/des.js')}}"></script>
<script src="{{url_for('static', filename = '/core/input/keysym.js')}}"></script>
<script src="{{url_for('static', filename = '/core/input/xtscancodes.js')}}"></script>
<script src="{{url_for('static', filename = '/core/encodings.js')}}"></script>
<script src="{{url_for('static', filename = '/core/decoders/raw.js')}}"></script>
<script src="{{url_for('static', filename = '/core/decoders/copyrect.js')}}"></script>
<script src="{{url_for('static', filename = '/core/decoders/hextile.js')}}"></script>
<script src="{{url_for('static', filename = '/core/decoders/rre.js')}}"></script>
<script src="{{url_for('static', filename = '/core/decoders/tight.js')}}"></script>
<script src="{{url_for('static', filename = '/core/decoders/tightpng.js')}}"></script>
<script src="{{url_for('static', filename = '/core/base64.js')}}"></script>
<script src="{{url_for('static', filename = '/vendor/pako/lib/zlib/inflate.js')}}"></script>
<script src="{{url_for('static', filename = '/vendor/pako/lib/zlib/zstream.js')}}"></script>
<script src="{{url_for('static', filename = '/vendor/pako/lib/zlib/deflate.js')}}"></script>
<script src="{{url_for('static', filename = '/core/input/util.js')}}"></script>
<script src="{{url_for('static', filename = '/vendor/pako/lib/utils/common.js')}}"></script>
<script src="{{url_for('static', filename = '/vendor/pako/lib/zlib/inffast.js')}}"></script>
<script src="{{url_for('static', filename = '/vendor/pako/lib/zlib/adler32.js')}}"></script>
<script src="{{url_for('static', filename = '/vendor/pako/lib/zlib/crc32.js')}}"></script>
<script src="{{url_for('static', filename = '/vendor/pako/lib/zlib/inftrees.js')}}"></script>
<script src="{{url_for('static', filename = '/core/input/keysymdef.js')}}"></script>
<script src="{{url_for('static', filename = '/core/input/vkeys.js')}}"></script>
<script src="{{url_for('static', filename = '/core/input/fixedkeys.js')}}"></script>
<script src="{{url_for('static', filename = '/core/input/domkeytable.js')}}"></script>
<script src="{{url_for('static', filename = '/vendor/pako/lib/zlib/trees.js')}}"></script>
<script src="{{url_for('static', filename = '/vendor/pako/lib/zlib/messages.js')}}"></script>
</head>
<body>
<!-- Loading DIV -->
<div id="loading"><center><img src="{{url_for('static', filename = 'logo.gif')}}"></center></div>
{% block content %}{% endblock %}
<!-- Pour le fun -->
<div style="position:fixed;bottom:0;right:0">Version Beta 2.7</div>
<!-- Alerting -->
<script>
var opacity=0;
var intervalID=0;
function fadeout(){
setInterval(hide, 100);
}
setTimeout(function(){
fadeout();
}, 3000);
function hide(){
var body=document.getElementById("alert");
opacity = Number(window.getComputedStyle(body).getPropertyValue("opacity"))
if(opacity>0){
opacity=opacity-0.1;
body.style.opacity=opacity
}
else{
clearInterval(intervalID);
}
}
</script>
<!-- Menu JS-->
<script>
var menu_btn = document.querySelector("#menu-btn");
var sidebar = document.querySelector("#sidebar");
var container = document.querySelector(".my-container");
menu_btn.addEventListener("click", () => {
sidebar.classList.toggle("active-nav");
container.classList.toggle("active-cont");
});
</script>
<!-- Loading -->
<script type="text/javascript">// <![CDATA[
function loading(){
$("#loading").show();
$("#content").hide();
}
// ]]>
</script>
<!-- DropZone -->
<script>
var myDropzone = new Dropzone("#file-dropzone", {
maxFilesize: 10240, // 10Go in Mo
timeout: 0,
});
</script>
<!-- Alert JS -->
<script>
//Get the cookie related to theme
var cookieValue = document.cookie
.split("; ")
.find((row) => row.startsWith("theme="))
?.split("=")[1];
// Appli the theme related to the cookie
window.onload = function() {
if (cookieValue == 'dark'){
document.documentElement.setAttribute('data-bs-theme','dark')
}
else {
document.documentElement.setAttribute('data-bs-theme','light')
}
}
//Change the cookie and reload
document.getElementById('btnSwitch').addEventListener('click',()=>{
if (cookieValue == 'dark') {
document.cookie = "theme=light";
window.location.reload();
}
else {
document.cookie = "theme=dark";
window.location.reload();
}
})
</script>
</body>
</html>

26
templates/login.html Normal file
View File

@@ -0,0 +1,26 @@
{% extends 'layout.html' %}
{% block content %}
<div class="container mt-5">
<div class="row d-flex justify-content-center">
<div class="col-md-6">
<div class="card px-5 py-5" id="form1">
<h1 class="h1">Hype²</h1>
<form action="/login" method="POST" class="form-group">
<br><br>
<div class="form-group">
<input type="email" name="email" placeholder="Email" class="form-control">
</div><br>
<div class="form-group">
<input type="password" name="password" placeholder="Password" class="form-control">
</div><br>
<div class="form-group">
<button type="submit" class="btn btn-outline-info btn-hype">Login</button>
</div>
</form>
</div>
<div class="col-lg-3 col-md-3 col-sm-12"></div>
</div>
</div>
{% endblock %}

52
templates/menu.html Normal file
View File

@@ -0,0 +1,52 @@
<div class="side-navbar active-nav d-flex justify-content-between flex-wrap flex-column" id="sidebar">
<ul class="nav flex-column text-dark w-100 ">
<li class="nav-link">
<h1 class="display-6">Hype²</h1>
</li>
<hr class="text-body">
<li class="nav-link">
<a class="nav-link text-body text-decoration-none fw-light" href="/"><i class="fa fa-pie-chart"></i> Dashboard</a>
</li>
<li class="nav-link">
<a class="nav-link text-body text-decoration-none fw-light" href="/state"><i class="fa fa-cubes"></i> State</a>
</li>
<li class="nav-link">
<a class="nav-link text-body text-decoration-none fw-light" href="/build"><i class="fa fa-cogs"></i> Build</a>
</li>
<li class="nav-link">
<a class="nav-link text-body text-decoration-none fw-light" href="/backup"><i class="fa fa-archive"></i> Backup</a>
</li>
<li class="nav-link">
<a class="nav-link text-body text-decoration-none fw-light" href="/iso"><i class="fa-solid fa-compact-disc"></i> ISO</a>
</li>
<li class="nav-link">
<a class="nav-link text-body text-decoration-none fw-light" href="/pool"><i class="fa-solid fa-hard-drive"></i> Pools</a>
</li>
</ul>
</div>
<div class="p-1 my-container active-cont">
<nav class="navbar top-navbar px-5">
<a class="btn border-0 text-body" id="menu-btn"><i class="fa fa-bars"></i></a>
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button" data-bs-toggle="dropdown" aria-expanded="false">
<i class="fa fa-user"></i> {{ current_user.username }}
</a>
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdownMenuLink">
<li><a class="dropdown-item" href="/logout"><i class="fa fa-sign-out"></i> Logout</a></li>
<li><a class="dropdown-item" href="/signup"><i class="fa fa-user-plus"></i> Add user</a></li>
<li><a class="dropdown-item" href="/param"><i class="fa fa-gear"></i> Parameters</a></li>
<li><a class="dropdown-item" style="cursor:pointer" id="btnSwitch"><i class="fa-solid fa-circle-half-stroke"></i> Theme</a></li>
</ul>
</nav>
</br>
<!-- Safe pour que ce soit au format html, sinon, prit comme texte -->
<div class="container">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div id="alert" class="alert alert-{{ category }}">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
</div>
</br>

30
templates/param.html Normal file
View File

@@ -0,0 +1,30 @@
{% extends 'layout.html' %}
{% block content %}
{% include 'menu.html' %}
<div class="container fs-6"">
<div class="card">
<div class="card-header">
<i class="fa fa-cube"></i> List of users
</div>
<div class="card-body">
{% for user in users_list %}
<div class="row">
<div class="col-4">
<p class="fw-light">{{user[0]}}</p>
</div>
<div class="col-4">
<p class="fw-light">{{user[1]}}</p>
</div>
<div class="col-1">
<form action="/deluser" method="post"><input type="hidden" id="postId" name="username" value="{{user[0]}}" />
<button type="submit" class="btn btn-outline-danger btn-hype" value="{{user[1]}}" name="email">
<i class="fa-solid fa-trash"></i>
</button>
</form>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
{% endblock %}

39
templates/pool.html Normal file
View File

@@ -0,0 +1,39 @@
{% extends 'layout.html' %}
{% block content %}
{% include 'menu.html' %}
<div class="container">
{% for pool in list_pool_full %}
{{ pool[0] }}<hr>
<div class="progress">
<div id="cpubar" class="progress-bar progress-bar-striped" role="progressbar" style="width: {{ pool[6] }}%;" aria-valuenow={{ pool[6] }} aria-valuemin="0" aria-valuemax="100">{{ pool[6] }}%</div>
</div>
<small class="form-text text-muted">
UUID : {{ pool[1] }} / Active : {{ pool[2] }} / Total : {{ pool[3] }} / Used : {{ pool[4] }} / Free : {{ pool[5] }}
</small>
<table class="table">
<tr><th>Name</th><th>Total</th><th>Used</th><th></th><th></th>
{% for volume in pool[7] %}
<tr>
<td>{{ volume[0] }}</td>
<td>{{ volume[1] }}</td>
<td>{{ volume[2] }}</td>
<td>
<div class="progress">
<div id="cpubar" class="progress-bar progress-bar-striped" role="progressbar" style="width: {{ volume[3] }}%;" aria-valuenow={{ volume[3] }} aria-valuemin="0" aria-valuemax="100">{{ volume[3] }}%</div>
</div>
<td>{{ volume[3] }}%</td>
<td>
<form action="/del_volume" method="post">
<input type="hidden" name="pool_name" value="{{ pool[0] }}">
<button type="submit" class="btn btn-outline-danger btn-hype" name="volume_name" value="{{ volume[0] }}" onclick="loading();">
<i class="fa fa-trash" aria-hidden="true"></i></button></form>
</td>
</tr>
{% endfor %}
</table>
{% endfor %}
</div>
{% endblock %}

126
templates/pyxterm.html Normal file
View File

@@ -0,0 +1,126 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<style>
html {
font-family: arial;
}
</style>
<link
rel="stylesheet"
href="https://unpkg.com/xterm@4.11.0/css/xterm.css"
/>
</head>
<body>
<span style="font-size: small"
>status:
<span style="font-size: small" id="status">connecting...</span></span
>
<div style="width: 100%; height: calc(100% - 50px)" id="terminal"></div>
<!-- xterm -->
<script src="https://unpkg.com/xterm@4.11.0/lib/xterm.js"></script>
<script src="https://unpkg.com/xterm-addon-fit@0.5.0/lib/xterm-addon-fit.js"></script>
<script src="https://unpkg.com/xterm-addon-web-links@0.4.0/lib/xterm-addon-web-links.js"></script>
<script src="https://unpkg.com/xterm-addon-search@0.8.0/lib/xterm-addon-sear
ch.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.min.js"></script>
<script>
const term = new Terminal({
cursorBlink: true,
macOptionIsMeta: true,
scrollback: true,
});
term.attachCustomKeyEventHandler(customKeyEventHandler);
// https://github.com/xtermjs/xterm.js/issues/2941
const fit = new FitAddon.FitAddon();
term.loadAddon(fit);
term.loadAddon(new WebLinksAddon.WebLinksAddon());
term.loadAddon(new SearchAddon.SearchAddon());
term.open(document.getElementById("terminal"));
fit.fit();
term.resize(15, 50);
console.log(`size: ${term.cols} columns, ${term.rows} rows`);
fit.fit();
term.writeln("Copy: [ctrl]+[shift]+[x] Paste: [ctrl]+[shift]+[v]");
term.writeln('')
term.onData((data) => {
console.log("browser terminal received new data:", data);
socket.emit("pty-input", { input: data });
});
const socket = io.connect("/pty");
const status = document.getElementById("status");
socket.on("pty-output", function (data) {
console.log("new output received from server:", data.output);
term.write(data.output);
});
socket.on("connect", () => {
fitToscreen();
status.innerHTML =
'<span style="background-color: lightgreen;">connected</span>';
});
socket.on("disconnect", () => {
status.innerHTML =
'<span style="background-color: #ff8383;">disconnected</span>';
});
function fitToscreen() {
fit.fit();
const dims = { cols: term.cols, rows: term.rows };
console.log("sending new dimensions to server's pty", dims);
socket.emit("resize", dims);
}
function debounce(func, wait_ms) {
let timeout;
return function (...args) {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(context, args), wait_ms);
};
}
/**
* Handle copy and paste events
*/
function customKeyEventHandler(e) {
if (e.type !== "keydown") {
return true;
}
if (e.ctrlKey && e.shiftKey) {
const key = e.key.toLowerCase();
if (key === "v") {
// ctrl+shift+v: paste whatever is in the clipboard
navigator.clipboard.readText().then((toPaste) => {
term.writeText(toPaste);
});
return false;
} else if (key === "c" || key === "x") {
// ctrl+shift+x: copy whatever is highlighted to clipboard
// 'x' is used as an alternate to 'c' because ctrl+c is taken
// by the terminal (SIGINT) and ctrl+shift+c is taken by the browser
// (open devtools).
// I'm not aware of ctrl+shift+x being used by anything in the terminal
// or browser
const toCopy = term.getSelection();
navigator.clipboard.writeText(toCopy);
term.focus();
return false;
}
}
return true;
}
const wait_ms = 50;
window.onresize = debounce(fitToscreen, wait_ms);
</script>
</body>
</html>

29
templates/signup.html Normal file
View File

@@ -0,0 +1,29 @@
{% extends 'layout.html' %}
{% block content %}
{% include 'menu.html' %}
<div class="container mt-5">
<div class="row d-flex justify-content-center">
<div class="col-md-6">
<div class="card px-5 py-5" id="form1">
<h1 class="display-6">Add user</h1><br><br>
<form action="/signup" method="POST" class="form-group">
<div class="form-group">
<input type="text" name="username" placeholder="Username" class="form-control">
</div><br>
<div class="form-group">
<input type="email" name="email" placeholder="Email" class="form-control">
</div><br>
<div class="form-group">
<input type="password" name="password" placeholder="Password" class="form-control">
</div><br>
<div class="form-group">
<button type="submit" class="btn btn-outline-info btn-hype">Add</button>
</div>
</form>
</div>
<div class="col-lg-3 col-md-3 col-sm-12"></div>
</div>
</div>
{% endblock %}

113
templates/state.html Normal file
View File

@@ -0,0 +1,113 @@
{% extends 'layout.html' %}
{% block content %}
{% include 'menu.html' %}
<div class="container fs-6"">
<table class="table">
<!-- Active LXC -->
{% for act_lxc in activ_lxc %}
<tr><td>
<i class="fa fa-cube fa-lg"></i><i class="fa fa-check text-success"></i>
</td><td>
<p class="fw-light">{{act_lxc[0]}}</p>
</td><td>
<form action="/start_lxc" method="post"><button type="submit" class="btn btn-outline-success btn-hype disabled" value="{{ act_lxc[0] }}" name="start" onclick="loading();"><i class="fa fa-play" aria-hidden="true"></i></button></form>
</td><td>
<form action="/stop_lxc" method="post"><button type="submit" class="btn btn-outline-secondary btn-hype" value="{{ act_lxc[0] }}" name="stop" onclick="loading();"><i class="fa fa-stop" aria-hidden="true"></i></button></form>
</td><td>
<form action="/console_lxc" method="post" target=”_blank”><button type="submit" class="btn btn-outline-info btn-hype" value="{{ act_lxc[0] }}" name="lxc_name" onclick="loading();"><i class="fa fa-terminal"></i></button></form>
</td><td>
<form action="/destroy_lxc" method="post"><button type="submit" class="btn btn-outline-danger btn-hype disabled" value="{{ act_lxc[0] }}" name="destroy" onclick="loading();"><i class="fa fa-trash" aria-hidden="true"></i></button></form>
</td><td>
<form action="/snaplxc" method="post"><button type="submit" class="btn btn-outline-secondary btn-hype disabled" value="{{ act_lxc[0] }}" name="snap" onclick="loading();"><i class="fa-solid fa-box-archive"></i></button></form>
</td><td>
</td><td>
{{act_lxc[1]}}
</td></tr>
{% endfor %}
<!-- Inactive LXC -->
{% for inact_lxc in inactiv_lxc %}
<tr><td>
<i class="fa fa-cube fa-lg"></i><i class="fa fa-times text-danger"></i>
</td><td>
<p class="fw-light">{{inact_lxc}}</p>
</td><td>
<form action="/start_lxc" method="post"><button type="submit" class="btn btn-outline-success btn-hype" value="{{ inact_lxc }}" name="start" onclick="loading();"><i class="fa fa-play" aria-hidden="true"></i></button></form>
</td><td>
<form action="/stop_lxc" method="post"><button type="submit" class="btn btn-outline-secondary btn-hype disabled" value="{{ inact_lxc }}" name="stop" onclick="loading();"><i class="fa fa-stop" aria-hidden="true"></i></button></form>
</td><td>
<form action="/console_lxc" method="post"><button type="submit" class="btn btn-outline-info btn-hype disabled" value="{{ inact_lxc }}" name="lxc_name" onclick="loading();"><i class="fa fa-terminal" aria-hidden="true"></i></button></form>
</td><td>
<form action="/destroy_lxc" method="post"><button type="submit" class="btn btn-outline-danger btn-hype" value="{{ inact_lxc }}" name="destroy" onclick="loading();"><i class="fa fa-trash" aria-hidden="true"></i></button></form>
</td><td>
<form action="/snaplxc" method="post"><button type="submit" class="btn btn-outline-secondary btn-hype" value="{{ inact_lxc }}" name="snap" onclick="loading();"><i class="fa-solid fa-box-archive"></i></button></form>
</td><td>
</td><td>
-
</td></tr>
{% endfor %}
<!-- Activ VM -->
{% for act_vm in activ_vm %}
<tr><td>
<i class="fa fa-desktop fa-lg"></i><i class="fa fa-check text-success"></i>
</td><td>
<p class="fw-light">{{act_vm[0]}}</p>
</td><td>
<form action="/start_vm" method="post"><button type="submit" class="btn btn-outline-success btn-hype disabled" value="{{ act_vm[0] }}" name="start" onclick="loading();"><i class="fa fa-play" aria-hidden="true"></i></button></form>
</td><td>
<form action="/stop_vm" method="post"><button type="submit" class="btn btn-outline-secondary btn-hype" value="{{ act_vm[0] }}" name="stop" onclick="loading();"><i class="fa fa-stop" aria-hidden="true"></i></button></form>
</td><td>
<form action="/console_vm" method="post"><button type="submit" class="btn btn-outline-info btn-hype" value="{{ act_vm[0] }}" name="vm_name" onclick="loading();"><i class="fa fa-terminal" aria-hidden="true"></i></button></form>
</td><td>
<form action="/destroy_vm" method="post"><button type="submit" class="btn btn-outline-danger btn-hype disabled" value="{{ act_vm[0] }}" name="destroy" onclick="loading();"><i class="fa fa-trash" aria-hidden="true"></i></button></form>
</td><td>
<form action="/snapvm" method="post"><button type="submit" class="btn btn-outline-secondary btn-hype disabled" value="{{ act_vm[0] }}" name="snap" onclick="loading();"><i class="fa-solid fa-box-archive"></i></button></form>
</td><td>
{% if act_vm[1] == 1 %}
<table class="table table-borderless"><tr><th>
<i class="fa-solid fa-compact-disc"></i>
</th><th><form action="/mountiso" method="post"><input type="hidden" id="postId" name="iso" value="" />
<button type="submit" class="btn btn-outline-secondary btn-hype" value="{{act_vm[0]}}" name="vm" onclick="loading();">
<i class="fa-solid fa-eject"></i></button></form>
</th></tr></table>
{% else %}
<i class="fa-solid fa-compact-disc" style="color:grey"></i>
{% endif %}
</td><td>
{{act_vm[2]}}
</td></tr>
{% endfor %}
<!-- Inavtiv VM -->
{% for inact_vm in inactiv_vm %}
<tr><td>
<i class="fa fa-desktop fa-lg"></i><i class="fa fa-times text-danger"></i>
</td><td>
<p class="fw-light">{{inact_vm[0]}}</p>
</td><td>
<form action="/start_vm" method="post"><button type="submit" class="btn btn-outline-success btn-hype" value="{{ inact_vm[0] }}" name="start"><i class="fa fa-play" aria-hidden="true" onclick="loading();"></i></button></form>
</td><td>
<form action="/stop_vm" method="post"><button type="submit" class="btn btn-outline-secondary btn-hype disabled" value="{{ inact_vm[0] }}" name="stop" onclick="loading();"><i class="fa fa-stop" aria-hidden="true"></i></button></form>
</td><td>
<form action="/console_vm" method="post"><button type="submit" class="btn btn-outline-info btn-hype disabled"><i class="fa fa-terminal" aria-hidden="true" onclick="loading();"></i></button></form>
</td><td>
<form action="/destroy_vm" method="post"><button type="submit" class="btn btn-outline-danger btn-hype" value="{{ inact_vm[0] }}" name="destroy" onclick="loading();"><i class="fa fa-trash" aria-hidden="true"></i></button></form>
</td><td>
<form action="/snapvm" method="post"><button type="submit" class="btn btn-outline-secondary btn-hype" value="{{ inact_vm[0] }}" name="snap" onclick="loading();"><i class="fa-solid fa-box-archive"></i></button></form>
</td><td>
{% if inact_vm[1] == 1 %}
<table class="table table-borderless"><tr><th>
<i class="fa-solid fa-compact-disc"></i>
</th><th><form action="/mountiso" method="post"><input type="hidden" id="postId" name="iso" value="" />
<button type="submit" class="btn btn-outline-secondary btn-hype" value="{{act_vm[0]}}" name="vm" onclick="loading();">
<i class="fa-solid fa-eject"></i></button></form>
</th></tr></table>
{% else %}
<i class="fa-solid fa-compact-disc" style="color:grey"></i>
{% endif %}
</td><td>
-
</td></tr>
{% endfor %}
</table>
{% endblock %}

8
templates/terminal.html Normal file
View File

@@ -0,0 +1,8 @@
{% extends 'layout.html' %}
{% block content %}
{% include 'menu.html' %}
<a href="/ter" target="_blank"><i class="fa-solid fa-expand"></i></a></br>
<iframe src="/ter" height=768px width=1024px class="embed-responsive-item" allowfullscreen></iframe>
{% endblock %}

8
templates/vnc.html Normal file
View File

@@ -0,0 +1,8 @@
{% extends 'layout.html' %}
{% block content %}
{% include 'menu.html' %}
<a href="/vnc" target="_blank"><i class="fa-solid fa-expand"></i></a></br>
<iframe src="/vnc" height=768px width=1024px class="embed-responsive-item" allowfullscreen></iframe>
{% endblock %}