882 lines
43 KiB
Python
882 lines
43 KiB
Python
#!/usr/bin/python3
|
|
import os
|
|
import sys
|
|
import lxc
|
|
import time
|
|
import datetime
|
|
import math
|
|
import pygal
|
|
import psutil
|
|
import logging
|
|
import libvirt
|
|
import collections
|
|
collections.MutableSequence = collections.abc.MutableSequence
|
|
collections.Iterable = collections.abc.Iterable
|
|
from pygal.style import LightenStyle, LightColorizedStyle
|
|
from flask import Flask, render_template, Response, request, redirect, url_for, session, escape
|
|
from flask_fontawesome import FontAwesome
|
|
from simplepam import authenticate
|
|
from flask_navigation import Navigation
|
|
from flask_dropzone import Dropzone
|
|
from xml.dom import minidom
|
|
|
|
|
|
|
|
#Flask config
|
|
flask_port=5005
|
|
flask_host='0.0.0.0'
|
|
flask_thread=True
|
|
flask_debug=False
|
|
#Other
|
|
__version__ = "2.7"
|
|
|
|
#path base for service lauch
|
|
path = os.path.dirname(__file__)
|
|
|
|
#iso path
|
|
iso_path= path+'/storage/iso/'
|
|
|
|
#Language
|
|
lang_created='had been created !'
|
|
lang_stopped='had been stopped !'
|
|
lang_forced_stop='Error on Stop, stop had been forced !'
|
|
lang_started='had been started !'
|
|
lang_destroyed='had been destroyed !'
|
|
lang_console='is stopped, please start it first !'
|
|
lang_console2='is started, please stop it first !'
|
|
lang_uploaded='had been uploaded !'
|
|
lang_openconsole='console can be opened in a new tab'
|
|
lang_already_started='is already started !'
|
|
lang_deleted='had been deleted !'
|
|
lang_snapvm='have a new snapshot !'
|
|
lang_snapvm_failed='had met an error. Snapshot failed !'
|
|
|
|
#Init logs
|
|
logging.basicConfig(filename=path+'/log/Main-lxc.log', level=logging.DEBUG, format=f'%(asctime)s %(levelname)s %(name)s %(threadName)s : %(message)s')
|
|
logging.info('PROGRAM START')
|
|
#Init Libvirt
|
|
try:
|
|
conn = libvirt.open("qemu:///system")
|
|
except:
|
|
exit(1)
|
|
#Init Flask
|
|
app = Flask(__name__,static_url_path='',static_folder='web/static',template_folder='web/templates')
|
|
#Init FontAwsome
|
|
fa = FontAwesome(app)
|
|
#Init Nav
|
|
nav = Navigation(app)
|
|
#DropZone
|
|
app.config.update(
|
|
UPLOADED_PATH= iso_path,
|
|
DROPZONE_MAX_FILE_SIZE = 10240,
|
|
DROPZONE_TIMEOUT = 5*60*1000,
|
|
DROPZONE_ALLOWED_FILE_CUSTOM = True,
|
|
DROPZONE_ALLOWED_FILE_TYPE = '.iso')
|
|
dropzone = Dropzone(app)
|
|
#Menu
|
|
nav.Bar('top', [
|
|
nav.Item('Dash', 'index'),
|
|
nav.Item('State', 'state'),
|
|
nav.Item('Build', 'build'),
|
|
nav.Item('Storage','pool'),
|
|
nav.Item('Monitoring','monit'),
|
|
nav.Item('Backup','backup'),
|
|
nav.Item('Host','host'),
|
|
nav.Item('Logs','logs'),
|
|
])
|
|
|
|
#Graf Pantone
|
|
dark_lighten_style = LightenStyle('#336676', base_style=LightColorizedStyle, step=2,value_font_size=25)
|
|
dark_lighten_style.background = 'transparent'
|
|
|
|
#Global fonctions
|
|
def get_xml(VM):
|
|
dom=conn.lookupByName(VM)
|
|
raw_xml = dom.XMLDesc()
|
|
xml = minidom.parseString(raw_xml)
|
|
return xml
|
|
|
|
##
|
|
@app.route('/del_snap_lxc', methods = ['POST'])
|
|
def del_snap_lxc():
|
|
cont=request.form['cont']
|
|
conn=lxc.Container(cont)
|
|
item=request.form['delete']
|
|
item=item.split('_')[2]
|
|
out=conn.snapshot_destroy(item)
|
|
if out:
|
|
resultats='<p id="alert" style="color:green"><b>'+item+'</b> had been deleted !</p>'
|
|
else:
|
|
resultats='<p id="alert" style="color:red"><b>'+item+'</b> could not been deleted !</p>'
|
|
return render_template('backup.html',listlxc=get_lxc_list(),listvm=list_full_vm(),loguser=session['username'],alertmessage=resultats)
|
|
|
|
@app.route('/rest_snap_lxc', methods = ['POST'])
|
|
def rest_snap_lxc():
|
|
cont=request.form['cont']
|
|
ct=lxc.Container(cont)
|
|
if ct.state=='RUNNING':
|
|
resultats='<p id="alert" style="color:red"><b>'+cont+'</b>'+lang_console2+'</p>'
|
|
else:
|
|
item=request.form['restore']
|
|
item=item.split('_')[2]
|
|
out=ct.snapshot_restore(item)
|
|
if out:
|
|
resultats='<p id="alert" style="color:green"><b>'+item+'</b> had been restored !</p>'
|
|
else:
|
|
resultats='<p id="alert" style="color:red"><b>'+item+'</b> could not been restored !</p>'
|
|
return render_template('backup.html',listlxc=get_lxc_list(),listvm=list_full_vm(),loguser=session['username'],alertmessage=resultats)
|
|
|
|
@app.route('/del_snap_vm', methods = ['POST'])
|
|
def del_snap_vm():
|
|
item=request.form['delete']
|
|
cont=request.form['cont']
|
|
dom=conn.lookupByName(cont)
|
|
snap_2del=dom.snapshotLookupByName(item)
|
|
out=snap_2del.delete()
|
|
if out:
|
|
resultats='<p id="alert" style="color:green"><b>'+item+'</b> had been deleted !</p>'
|
|
else:
|
|
resultats='<p id="alert" style="color:red"><b>'+item+'</b> could not been deleted !</>'
|
|
return render_template('backup.html',listlxc=get_lxc_list(),listvm=list_full_vm(),loguser=session['username'],alertmessage=resultats)
|
|
|
|
@app.route('/logs')
|
|
def logs():
|
|
if 'username' in session:
|
|
resultats=''
|
|
return render_template('logs.html',loguser=session['username'],alertmessage=resultats,state_all=get_lxc_state(),listlxc=get_lxc_list(),listdistrib=list_distrib())
|
|
return render_template('login.html',title="Logs")
|
|
|
|
@app.route('/stream')
|
|
def stream():
|
|
def generate():
|
|
with open(path+'/log/Main-lxc.log') as f:
|
|
while True:
|
|
yield f.read()
|
|
time.sleep(1)
|
|
return app.response_class(generate(), mimetype='text/plain')
|
|
|
|
@app.route('/host')
|
|
def host():
|
|
split_dec=conn.getSysinfo()
|
|
split_dec=split_dec.replace('\n', '<br>')
|
|
return render_template('host.html',loguser=session['username'],hostname=conn.getHostname(),hostlist=split_dec,title="Host")
|
|
|
|
def host_disk():
|
|
KB = 1024
|
|
MB = 1024 * KB
|
|
GB = 1024 * MB
|
|
host_disk_total = round(psutil.disk_usage('/').total / GB)
|
|
host_disk_used = round(psutil.disk_usage('/').used / GB)
|
|
host_disk_percent = psutil.disk_usage('/').percent
|
|
host_disk_free = host_disk_total - host_disk_used
|
|
host_disk_free_percent = round(100 - host_disk_percent,1)
|
|
return host_disk_total, host_disk_used, host_disk_percent, host_disk_free, host_disk_free_percent
|
|
|
|
|
|
|
|
def convert_size(bytes_size):
|
|
if bytes_size == 0:
|
|
return "0B"
|
|
size_name = ("B", "KB", "MB", "GB", "TB", "PB")
|
|
i = int(math.floor(math.log(bytes_size, 1024)))
|
|
p = math.pow(1024, i)
|
|
s = round(bytes_size / p, 2)
|
|
return"%s %s" % (s,size_name[i])
|
|
|
|
def get_cdrom_attribut(VM):
|
|
xml = get_xml(VM)
|
|
diskTypes = xml.getElementsByTagName('disk')
|
|
for disk_xml in diskTypes:
|
|
if disk_xml.getAttribute('device') == 'cdrom':
|
|
target_tag = disk_xml.getElementsByTagName('target')
|
|
address_tag = disk_xml.getElementsByTagName('address')
|
|
target_dev = target_tag[0].getAttribute('dev')
|
|
target_bus = target_tag[0].getAttribute('bus')
|
|
address_type = address_tag[0].getAttribute('type')
|
|
address_controller = address_tag[0].getAttribute('controller')
|
|
address_bus = address_tag[0].getAttribute('bus')
|
|
address_target = address_tag[0].getAttribute('target')
|
|
address_unit = address_tag[0].getAttribute('unit')
|
|
return target_dev, target_bus, address_type, address_controller, address_bus, address_target, address_unit
|
|
|
|
def mount_iso(VM,ISO):
|
|
dom = conn.lookupByName(VM)
|
|
target_dev, target_bus, address_type, address_controller, address_bus, address_target, address_unit = get_cdrom_attribut(VM)
|
|
diskFile = ISO
|
|
diskXML = """ <disk type='file' device='cdrom'>
|
|
<driver name='qemu' type='raw'/>
|
|
<source file='""" + diskFile + """'/>
|
|
<target dev='""" + target_dev + """' bus='""" + target_bus + """'/>
|
|
<address type='""" + address_type + """' controller='""" + address_controller + """' bus='""" + address_bus + """' target='""" + address_target + """' unit='""" + address_unit + """'/>
|
|
</disk>"""
|
|
dom.updateDeviceFlags(diskXML, 0)
|
|
|
|
def check_iso_is_mounted(VM):
|
|
dom = conn.lookupByName(VM)
|
|
raw_xml = dom.XMLDesc()
|
|
xml = minidom.parseString(raw_xml)
|
|
diskTypes = xml.getElementsByTagName('disk')
|
|
for disk_xml in diskTypes:
|
|
disk = None
|
|
source = disk_xml.getElementsByTagName('source')
|
|
if disk_xml.getAttribute('device') == 'cdrom':
|
|
try:
|
|
gotdata= source[0].getAttribute('file')
|
|
if source[0].getAttribute('file'):
|
|
state = 1
|
|
else:
|
|
state = 0
|
|
except IndexError:
|
|
state = 0
|
|
#Return 1 if mounted or 0 if not mounted
|
|
return state
|
|
|
|
@app.route("/mountiso", methods=['POST'])
|
|
def mountiso():
|
|
VM=request.form['vm']
|
|
ISO=iso_path+request.form['iso']
|
|
mount_iso(VM,ISO)
|
|
resultats='<p id="alert" style="color:green">ISO mounted !</p>'
|
|
return render_template('build.html',listvm=list_activ_vm(),list_net=conn.listNetworks(),listvm_iso=get_iso_list(),list_profiles=get_os_profile_list(),list_iso=get_iso_list(),list_iso_mount=get_iso_list(),loguser=session['username'],alertmessage=resultats,state_all=get_vm_state(),title="Build",listlxc=get_lxc_list(),listdistrib=list_distrib())
|
|
|
|
@app.route('/ejectiso', methods = ['POST'])
|
|
def eject_iso():
|
|
VM=request.form['ejectisovm']
|
|
state = check_iso_is_mounted(VM)
|
|
while state != 0:
|
|
ISO='';
|
|
mount_iso(VM,ISO)
|
|
state = check_iso_is_mounted(VM)
|
|
resultats='<p id="alert" style="color:green">ISO had been ejected !</p>'
|
|
return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all='<div class="card"><div class="card-header">Containers</div><div class="card-body">'+get_lxc_state()+'</div></div><div class="card"><div class="card-header">Virtual Servers</div><div class="card-body">'+get_vm_state()+"</div></div>",title="State",listlxc=get_lxc_list(),listdistrib=list_distrib())
|
|
|
|
def get_vm_devices(VM):
|
|
xml = get_xml(VM)
|
|
diskTypes = xml.getElementsByTagName("disk")
|
|
full_list=[]
|
|
for diskType in diskTypes:
|
|
list_vm=[]
|
|
list_vm.append(diskType.getAttribute("device"))
|
|
diskNodes = diskType.childNodes
|
|
for diskNode in diskNodes:
|
|
if diskNode.nodeName[0:1] != "#":
|
|
if diskNode.nodeName=='source':
|
|
for attr in diskNode.attributes.keys():
|
|
list_vm.append(diskNode.attributes[attr].value)
|
|
full_list.append(list_vm)
|
|
full_list.reverse()
|
|
return full_list
|
|
|
|
@app.route('/devicelist', methods = ['POST'])
|
|
def get_devices():
|
|
list_devices=[]
|
|
full_vm_list=list_activ_vm()+list_inactiv_vm()
|
|
for vm_name in full_vm_list:
|
|
list_vm=get_vm_devices(vm_name)
|
|
list_vm.insert(0, vm_name)
|
|
list_devices.append(list_vm)
|
|
return list_devices
|
|
|
|
|
|
def storage_get_pool():
|
|
pool_html='<table class="table table-responsive table-condensed align-middle mb-0"><tr>'
|
|
##Cleaning Pool cache to avoid error due to deleted entries
|
|
for refresh_pool in conn.listAllStoragePools():
|
|
refresh_pool.refresh(0)
|
|
for pools in conn.listStoragePools():
|
|
pool = conn.storagePoolLookupByName(pools)
|
|
info = pool.info()
|
|
if info[1]==0:
|
|
pool_used=0
|
|
else:
|
|
pool_used=round((info[2]*100)/info[1],2)
|
|
pool_free=100-pool_used
|
|
graf_pool=pygal.Pie(value_font_size=25,half_pie = True,fill=True, interpolate='cubic', style=dark_lighten_style, legend_at_bottom=True,show_legend=False)
|
|
graf_pool.add("Used",pool_used)
|
|
graf_pool.add("Free",pool_free)
|
|
graf_pool=graf_pool.render_data_uri()
|
|
pool_html=pool_html+"<td><img src='"+graf_pool+"' style='width:200px'><br>Pool: <b>"+pool.name()+"</b><br>UUID: "+pool.UUIDString()+"<br>Autostart: "+str(pool.autostart())+"<br>Is active: "+str(pool.isActive())+"<br>Is persistent: "+str(pool.isPersistent())+"<br>Num volumes: "+str(pool.numOfVolumes())+"<br>Pool state: "+str(info[0])+"<br>Capacity: "+str(convert_size(info[1]))+"<br>Allocation: "+str(convert_size(info[2]))+"<br>Available: "+str(convert_size(info[3]))+'</td>'
|
|
pool_html=pool_html+'</tr></table>'
|
|
return pool_html
|
|
|
|
@app.route('/delvol', methods = ['POST'])
|
|
def dellvol():
|
|
pool_item=request.form['pool']
|
|
volume_item=request.form['volume']
|
|
pools=conn.storagePoolLookupByName(pool_item)
|
|
vlm=pools.storageVolLookupByName(volume_item)
|
|
vlm.delete()
|
|
return redirect(url_for('pool'))
|
|
|
|
def storage_get_volumes():
|
|
volume_html='<table class="table table-responsive table-hover table-condensed align-middle mb-0 bg-white"><tr><th>Pool</th><th>Volume Name</th><th>Capacity</th><th>Allocation</th><th>Delete</th><th>Chart</th></tr>'
|
|
##Cleaning Pool cache to avoid error due to deleted entries
|
|
for refresh_pool in conn.listAllStoragePools():
|
|
refresh_pool.refresh(0)
|
|
|
|
for pools in conn.listStoragePools():
|
|
pool=conn.storagePoolLookupByName(pools)
|
|
for volume in pool.listVolumes():
|
|
vol = pool.storageVolLookupByName(volume)
|
|
info = vol.info()
|
|
if info[1]==0:
|
|
vol_used=0
|
|
else:
|
|
vol_used=round((info[2]*100)/info[1],2)
|
|
vol_free=100-vol_used
|
|
vol_graf=pygal.Pie(value_font_size=25,half_pie = True,fill=True, interpolate='cubic', style=dark_lighten_style, show_legend=False)
|
|
vol_graf.add("Used",vol_used)
|
|
vol_graf.add("Free",vol_free)
|
|
vol_graf=vol_graf.render_data_uri()
|
|
volume_html=volume_html+"<tr><td>"+pools+"</td><td>"+volume+"</td><td>"+str(convert_size(info[1]))+"</td><td>"+ str(convert_size(info[2]))+"</td><td>"
|
|
volume_html=volume_html+"<form action=\"/delvol\" method=\"post\"><input type=\"hidden\" name=\"pool\" value=\""+pools+"\"><button type=\"submit\" name=\"volume\" value=\""+volume+"\"><span class=\"fas fa-trash\"></span></button></form></td><td><img src='"+vol_graf+"' style='width:40px'></tr>"
|
|
volume_html=volume_html+"</table>"
|
|
return volume_html
|
|
|
|
def global_cpu_monit():
|
|
cpu_percent_used=psutil.cpu_percent()
|
|
cpu_percent_free=100-cpu_percent_used
|
|
cpu_usage=psutil.cpu_times_percent()
|
|
cpu_usage_html="Kernel: "+str(cpu_usage.system)+"%<br>User: "+str(cpu_usage.user)+"%<br>Idle: "+str(cpu_usage.idle)+"%<br>IO wait: "+str(cpu_usage.iowait)+"%<br>"
|
|
return cpu_usage_html, cpu_percent_used, cpu_percent_free
|
|
|
|
def global_mem_monit():
|
|
mem_percent_used=psutil.virtual_memory().percent
|
|
mem_percent_free=100-mem_percent_used
|
|
memory_usage= conn.getMemoryStats(libvirt.VIR_NODE_MEMORY_STATS_ALL_CELLS)
|
|
memory_usage_html="Total: "+str(convert_size(memory_usage['total']*1024))+"<br>Free: "+str(convert_size(memory_usage['free']*1024))+"<br>Buffers: "+str(convert_size(memory_usage['buffers']*1024))+"<br>Cached: "+str(convert_size(memory_usage['cached']*1024))+"<br>".format(**memory_usage)
|
|
return memory_usage_html, mem_percent_used, mem_percent_free
|
|
|
|
def vm_monit():
|
|
vm_monit_html='<table class="table table-responsive table-hover table-condensed align-middle mb-0"><tr><th>Nom</th><th>State</th></tr>'
|
|
full_vm_list=list_activ_vm()+list_inactiv_vm()
|
|
for vm_name in full_vm_list:
|
|
dom=conn.lookupByName(vm_name)
|
|
state, maxmem, mem, cpus, cput = dom.info()
|
|
if state==1:
|
|
state="RUNNING"
|
|
else:
|
|
state="STOPPED"
|
|
vm_monit_html=vm_monit_html+"<tr><td>"+dom.name()+"<td>"+str(state)+"<br>Max memory : "+ str(convert_size(maxmem*1024))+"<br>Memory : "+ str(convert_size(mem*1024))
|
|
vm_monit_html=vm_monit_html+"<br>CPU number : "+str(cpus)+"<br>CPU time : "+str(cput)+"</td></tr>"
|
|
vm_monit_html=vm_monit_html+"</table>"
|
|
return vm_monit_html
|
|
|
|
def lxc_monit():
|
|
ct_monit_html='<table class="table table-responsive table-hover table-condensed align-middle mb-0"><tr><th>Nom</th><th>State</th></tr>'
|
|
for lxc_name in get_lxc_list():
|
|
ct=lxc.Container(lxc_name)
|
|
if ct.state=='RUNNING':
|
|
p=psutil.Process(ct.init_pid)
|
|
ct_cpu=str(round(p.cpu_percent(), 2))
|
|
ct_meme=str(round(p.memory_percent(), 2))
|
|
else:
|
|
ct_meme='0'
|
|
ct_cpu='0'
|
|
ct_monit_html=ct_monit_html+"<tr><td>"+lxc_name+"<td>"+ct.state+"<br>Memory : "+ct_meme+"%"
|
|
ct_monit_html=ct_monit_html+"<br>CPU : "+ct_cpu+"%</td></tr>"
|
|
ct_monit_html=ct_monit_html+"</table>"
|
|
return ct_monit_html
|
|
|
|
def list_activ_vm():
|
|
list_run_id=conn.listDomainsID()
|
|
list_run=[]
|
|
for id in list_run_id:
|
|
dom=conn.lookupByID(id)
|
|
list_run.append(dom.name())
|
|
return list_run
|
|
|
|
def list_inactiv_vm():
|
|
list_vm=conn.listDefinedDomains()
|
|
return list_vm
|
|
|
|
def list_full_vm():
|
|
full_vm_list=list_activ_vm()+list_inactiv_vm()
|
|
return full_vm_list
|
|
|
|
def list_distrib():
|
|
link_list = ['debian','ubuntu','centos','busybox','ubuntu-cloud','cirros','sabayon']
|
|
name_list = ['Debian','Ubuntu','Centos','Busybox','Ubuntu-cloud','Cirros','Sabayon']
|
|
listd = zip(name_list, link_list)
|
|
return listd
|
|
|
|
def get_iso_list():
|
|
list_iso_path= []
|
|
list_iso_size= []
|
|
for x in os.listdir(iso_path):
|
|
if x.endswith(".iso"):
|
|
size=os.path.getsize(iso_path+x)
|
|
size=convert_size(size)
|
|
list_iso_size.append(str(size))
|
|
list_iso_path.append(str(x))
|
|
list_iso=zip(list_iso_path, list_iso_size)
|
|
return list_iso
|
|
|
|
def get_os_profile_list():
|
|
list_profile=[]
|
|
for profile in os.popen("osinfo-query os | awk '{ print $1 }' | awk 'NR > 2 { print }'"):
|
|
list_profile.append(str(profile))
|
|
return list_profile
|
|
|
|
def get_lxc_list():
|
|
liste_ct=lxc.list_containers()
|
|
return liste_ct
|
|
|
|
def get_lxc_activ():
|
|
activ_ct = 0
|
|
inactiv_ct = 0
|
|
for ct_name in get_lxc_list():
|
|
ct_state=lxc.Container(ct_name)
|
|
if ( ct_state.state == "RUNNING"):
|
|
activ_ct +=1
|
|
else:
|
|
inactiv_ct +=1
|
|
return activ_ct,inactiv_ct
|
|
|
|
def get_lxc_state():
|
|
out=''
|
|
for ct_name in get_lxc_list():
|
|
ct_state=lxc.Container(ct_name)
|
|
if ( ct_state.state == "RUNNING"):
|
|
color_ct_state='<p style="background-color:PaleGreen">'+ct_state.state+'</p>'
|
|
else:
|
|
color_ct_state='<p style="background-color:lightcoral">'+ct_state.state+'</p>'
|
|
out=out+'<tr><td>'+ct_name+'</td><td>'
|
|
out=out+color_ct_state+'</td><td><div id="action"><center><table class="tacs"><tr><td><form action="/startct" method="post"><button type="submit" value="'+ct_name+'" name="start" onclick="loading();">'
|
|
out=out+'<span class="fas fa-play"></span></button></form></td><td><form class="flotte" action="/stopct" method="post"><button type="submit" value="'+ct_name+'" name="stop" onclick="loading();">'
|
|
out=out+'<span class="fas fa-stop"></span></button></form></td><td><form class="flotte" action="/destroyct" method="post"><button type="submit" value="'+ct_name+'" name="destroy" onclick="loading();">'
|
|
out=out+'<span class="fas fa-trash"></span></button></form></td><td><form class="flotte" action="/console" method="post"><button type="submit" value="'+ct_name+'" name="console" onclick="loading();">'
|
|
out=out+'<span class="fas fa-terminal"></span></button></form></td></tr></table></center></div></td><td>'
|
|
out=out+str(ct_state.get_ips()).replace('(', '').replace(')', '').replace(',', '').replace('\'', '')+'</td></tr>'
|
|
out='<table class="table table-responsive table-hover table-condensed align-middle mb-0 bg-white"><tr><th>Name</th><th>State</th><th>Actions</th><th>IP</th></tr>'+out+'</table>'
|
|
return out
|
|
|
|
def get_snap_list_lxc(cont):
|
|
dom=lxc.Container(cont)
|
|
list_snap_lxc = dom.snapshot_list()
|
|
out=[]
|
|
for snap in list_snap_lxc:
|
|
nom_snap=snap[0]
|
|
date_snap=datetime.datetime.strptime(snap[2], '%Y:%m:%d %H:%M:%S')
|
|
date_snap=date_snap.strftime("%d%m%Y%H%M")
|
|
concat_name=dom.name+"_"+date_snap+"_"+nom_snap
|
|
out.append(concat_name)
|
|
return out
|
|
|
|
def get_snap_list_vm(cont):
|
|
dom=conn.lookupByName(cont)
|
|
list_snap_vm=dom.snapshotListNames()
|
|
list_snap_vm.reverse()
|
|
out=[]
|
|
for snap in list_snap_vm:
|
|
out.append(snap)
|
|
return out
|
|
|
|
def get_vm_ips(vm):
|
|
dom=conn.lookupByName(vm)
|
|
if not dom:
|
|
raise SystemExit("Failed to connect to Dom")
|
|
try:
|
|
ifaces = dom.interfaceAddresses(libvirt.VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT)
|
|
except:
|
|
ifaces = None
|
|
result="--.--.--.--"
|
|
if ifaces is None:
|
|
result="--.--.--.--"
|
|
else:
|
|
for (name, val) in ifaces.items():
|
|
if val['addrs']:
|
|
for addr in val['addrs']:
|
|
if addr['addr']:
|
|
result=str(addr['addr'])+"/"+str(addr['prefix'])
|
|
break
|
|
else:
|
|
result="-"
|
|
return result
|
|
|
|
def get_vm_state():
|
|
out=''
|
|
for activ_vm in list_activ_vm():
|
|
disk_state=check_iso_is_mounted(activ_vm)
|
|
if disk_state == 1:
|
|
disk_color='<p style="color:black"><form class="flotte" action="/ejectiso" method="post"><span class="fas fa-compact-disc"></span></p></td><td><form class="flotte" action="/ejectiso" method="post"><button style="border:0" type="submit" value="'+activ_vm+'" name="ejectisovm" onclick="loading();"><span class="fas fa-eject"></span></button></form>'
|
|
else:
|
|
disk_color='<p style="color:LightGray"><span class="fas fa-compact-disc"></span></p></td><td>'
|
|
color_vm_state='<p style="background-color:PaleGreen">RUNNING</p>'
|
|
out=out+'<tr><td>'+activ_vm+'</td><td>'
|
|
out=out+color_vm_state+'</td><td><div id="action"><center><table class="tacs"><tr><td><form action="/startvm" method="post"><button type="submit" value="'+activ_vm+'" name="startvm" onclick="loading();">'
|
|
out=out+'<span class="fas fa-play"></span></button></form></td><td><form class="flotte" action="/stopvm" method="post"><button type="submit" value="'+activ_vm+'" name="stopvm" onclick="loading();">'
|
|
out=out+'<span class="fas fa-stop"></span></button></form></td><td><form class="flotte" action="/destroyvm" method="post"><button type="submit" value="'+activ_vm+'" name="destroyvm" onclick="loading();">'
|
|
out=out+'<span class="fas fa-trash"></span></button></form></td><td><form class="flotte" action="/consolevm" method="post"><button type="submit" value="'+activ_vm+'" name="consolevm" onclick="loading();">'
|
|
out=out+'<span class="fas fa-terminal"></span></button></form></td></tr></table></center></div></td><td>'
|
|
out=out+get_vm_ips(activ_vm)+'</td><td>'+disk_color+'</td></tr>'
|
|
for inactiv_vm in list_inactiv_vm():
|
|
color_vm_state='<p style="background-color:lightcoral">STOPPED</p>'
|
|
out=out+'<tr><td>'+inactiv_vm+'</td><td>'
|
|
out=out+color_vm_state+'</td><td><div id="action"><center><table class="tacs"><tr><td><form action="/startvm" method="post"><button type="submit" value="'+inactiv_vm+'" name="startvm" onclick="loading();">'
|
|
out=out+'<span class="fas fa-play"></span></button></form></td><td><form class="flotte" action="/stopvm" method="post"><button type="submit" value="'+inactiv_vm+'" name="stopvm" onclick="loading();">'
|
|
out=out+'<span class="fas fa-stop"></span></button></form></td><td><form class="flotte" action="/destroyvm" method="post"><button type="submit" value="'+inactiv_vm+'" name="destroyvm" onclick="loading();">'
|
|
out=out+'<span class="fas fa-trash"></span></button></form></td><td><form class="flotte" action="/consolevm" method="post"><button type="submit" value="'+inactiv_vm+'" name="consolevm" onclick="loading();">'
|
|
out=out+'<span class="fas fa-terminal"></span></button></form></td></tr></table></center></div></td><td>'
|
|
out=out+'IP</td><td></td></tr>'
|
|
out='<table class="table table-responsive table-hover table-condensed align-middle mb-0 bg-white"><tr><th>Name</th><th>State</th><th>Actions</th><th>IP</th><th>Disk</th></tr>'+out+'</table>'
|
|
return out
|
|
|
|
def mount_pts():
|
|
os.system('mount -o remount,rw /dev/pts')
|
|
|
|
@app.route('/state')
|
|
def state():
|
|
resultats=''
|
|
return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all='<div class="card"><div class="card-header">Containers</div><div class="card-body">'+get_lxc_state()+'</div></div><div class="card"><div class="card-header">Virtual Servers</div><div class="card-body">'+get_vm_state()+"</div></div>",title="State",listlxc=get_lxc_list(),listdistrib=list_distrib())
|
|
|
|
@app.route('/snap_vm', methods = ['POST'])
|
|
def create_snap():
|
|
nom = request.form['nom']
|
|
dom=conn.lookupByName(nom)
|
|
actual_date=datetime.datetime.now()
|
|
actual_date=actual_date.strftime("%d%m%Y%H%M")
|
|
snapshot_name= dom.name()+"_"+actual_date+"_snap"
|
|
SNAPSHOT_XML_TEMPLATE = """<domainsnapshot>
|
|
<name>{snapshot_name}</name>
|
|
</domainsnapshot>"""
|
|
dom.snapshotCreateXML(SNAPSHOT_XML_TEMPLATE.format(snapshot_name=snapshot_name),libvirt.VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC)
|
|
if dom.snapshotCurrent().getName()==snapshot_name:
|
|
resultats='<p id="alert" style="color:green"><b>'+nom+'</b> '+lang_snapvm+'</p>'
|
|
else:
|
|
resultats='<p id="alert" style="color:red"><b>'+nom+'</b> '+lang_snapvm_failed+'</p>'
|
|
return render_template('backup.html',listlxc=list_snap_lxc,listvm=list_snap_vm,loguser=session['username'],alertmessage=resultats)
|
|
|
|
@app.route('/snap_lxc', methods = ['POST'])
|
|
def create_snap_lxc():
|
|
nom = request.form['nom']
|
|
cont=lxc.Container(nom)
|
|
if ( cont.state == "STOPPED"):
|
|
try:
|
|
snap=cont.snapshot()
|
|
resultats='<p id="alert" style="color:green"><b>'+nom+'</b> '+lang_snapvm+'</p>'
|
|
except:
|
|
resultats='<p id="alert" style="color:red"><b>'+nom+'</b> Snapshot Failed !</p>'
|
|
else:
|
|
resultats='<p id="alert" style="color:red"><b>'+nom+'</b> Should be stopped first !</p>'
|
|
full_snap_lxc=[]
|
|
full_snap_vm=[]
|
|
for int in get_lxc_list():
|
|
if get_snap_list_lxc(int):
|
|
full_snap_lxc.append(get_snap_list_lxc(int))
|
|
else:
|
|
full_snap_lxc.append('')
|
|
for ant in list_full_vm():
|
|
if get_snap_list_vm(ant):
|
|
full_snap_vm.append(get_snap_list_vm(ant))
|
|
else:
|
|
full_snap_vm.append('')
|
|
list_snap_lxc = zip(get_lxc_list(), full_snap_lxc)
|
|
list_snap_vm = zip(list_full_vm(), full_snap_vm)
|
|
return render_template('backup.html',listlxc=list_snap_lxc,listvm=list_snap_vm,loguser=session['username'],alertmessage=resultats)
|
|
|
|
@app.route('/backup')
|
|
def backup():
|
|
resultats=''
|
|
full_snap_lxc=[]
|
|
full_snap_vm=[]
|
|
for int in get_lxc_list():
|
|
if get_snap_list_lxc(int):
|
|
full_snap_lxc.append(get_snap_list_lxc(int))
|
|
else:
|
|
full_snap_lxc.append('')
|
|
for ant in list_full_vm():
|
|
if get_snap_list_vm(ant):
|
|
full_snap_vm.append(get_snap_list_vm(ant))
|
|
else:
|
|
full_snap_vm.append('')
|
|
list_snap_lxc = zip(get_lxc_list(), full_snap_lxc)
|
|
list_snap_vm = zip(list_full_vm(), full_snap_vm)
|
|
return render_template('backup.html',listlxc=list_snap_lxc,listvm=list_snap_vm,loguser=session['username'],alertmessage=resultats,title="Backups")
|
|
|
|
@app.route('/',methods = ['GET', 'POST'])
|
|
def index():
|
|
app.logger.info('Info level log')
|
|
app.logger.warning('Warning level log')
|
|
if 'username' in session:
|
|
resultats=''
|
|
global_cpu, cpu_percent_used, cpu_percent_free=global_cpu_monit()
|
|
global_ram, mem_percent_used, mem_percent_free=global_mem_monit()
|
|
activ_ct, inactiv_ct = get_lxc_activ()
|
|
host_disk_total, host_disk_used, host_disk_percent, host_disk_free, host_disk_free_percent = host_disk()
|
|
memory_usage= conn.getMemoryStats(libvirt.VIR_NODE_MEMORY_STATS_ALL_CELLS)
|
|
memory_total=convert_size(memory_usage['total']*1024)
|
|
memory_free=convert_size(memory_usage['free']*1024)
|
|
memory_buffers=convert_size(memory_usage['buffers']*1024)
|
|
memory_cached=convert_size(memory_usage['cached']*1024)
|
|
|
|
return render_template('index.html',host_disk_total=host_disk_total, host_disk_used=host_disk_used, host_disk_percent=host_disk_percent, host_disk_free=host_disk_free, host_disk_free_percent=host_disk_free_percent,hostname=conn.getHostname(),activ_vm=len(list_activ_vm()),inactiv_vm=len(list_inactiv_vm()),activ_ct=activ_ct,inactiv_ct=inactiv_ct,cpu_percent_used=cpu_percent_used,cpu_percent_free=cpu_percent_free,mem_percent_used=mem_percent_used,mem_percent_free=mem_percent_free,memory_total=memory_total,memory_free=memory_free,memory_buffers=memory_buffers,memory_cached=memory_cached,loguser=session['username'],title="Dashboard")
|
|
return render_template('login.html',title="Welcome")
|
|
|
|
@app.route('/upload', methods = ['GET', 'POST'])
|
|
def upload():
|
|
resultats=''
|
|
if request.method == 'POST':
|
|
f = request.files.get('file')
|
|
f.save(os.path.join(app.config['UPLOADED_PATH'],f.filename))
|
|
resultats='<p id="alert" style="color:green"><b>'+f.filename+'</b> '+lang_uploaded+'</p>'
|
|
return render_template('build.html',listvm=list_activ_vm(),list_net=conn.listNetworks(),listvm_iso=get_iso_list(),list_profiles=get_os_profile_list(),list_iso=get_iso_list(),list_iso_mount=get_iso_list(),loguser=session['username'],alertmessage=resultats,state_all=get_vm_state(),title="Build",listlxc=get_lxc_list(),listdistrib=list_distrib())
|
|
|
|
@app.route('/deliso', methods = ['POST'])
|
|
def delete_iso():
|
|
file=request.form['fichier']
|
|
location = app.config['UPLOADED_PATH']
|
|
path=os.path.join(location, file)
|
|
os.remove(path)
|
|
resultats='<p id="alert" style="color:green"><b>'+file+'</b> '+lang_deleted+'</p>'
|
|
return render_template('build.html',listvm=list_activ_vm(),list_net=conn.listNetworks(),listvm_iso=get_iso_list(),list_profiles=get_os_profile_list(),list_iso=get_iso_list(),list_iso_mount=get_iso_list(),loguser=session['username'],alertmessage=resultats,state_all=get_vm_state(),title="Build",listlxc=get_lxc_list(),listdistrib=list_distrib())
|
|
|
|
@app.route('/build')
|
|
def build():
|
|
if 'username' in session:
|
|
resultats=''
|
|
return render_template('build.html',listvm=list_activ_vm(),list_net=conn.listNetworks(),listvm_iso=get_iso_list(),list_profiles=get_os_profile_list(),list_iso=get_iso_list(),list_iso_mount=get_iso_list(),loguser=session['username'],alertmessage=resultats,state_all=get_vm_state(),title="Build",listlxc=get_lxc_list(),listdistrib=list_distrib())
|
|
return render_template('login.html')
|
|
|
|
@app.route('/monit')
|
|
def monit():
|
|
resultats=''
|
|
global_cpu, cpu_percent_used, cpu_percent_free=global_cpu_monit()
|
|
global_ram, mem_percent_used, mem_percent_free=global_mem_monit()
|
|
return render_template('monit.html',lxc_monit=lxc_monit(),vm_monit=vm_monit(),global_cpu=global_cpu,global_memory=global_ram,cpu_percent_used=cpu_percent_used,cpu_percent_free=cpu_percent_free, mem_percent_used=mem_percent_used,mem_percent_free=mem_percent_free,loguser=session['username'],alertmessage=resultats,title="Monitoring")
|
|
|
|
@app.route('/pool')
|
|
def pool():
|
|
resultats=''
|
|
return render_template('pool.html',volumes_det=storage_get_volumes(),pool_det=storage_get_pool(),loguser=session['username'],alertmessage=resultats,title="Pools")
|
|
|
|
@app.route("/creation", methods=['POST'])
|
|
def create_CT():
|
|
mount_pts()
|
|
nom = request.form['nom']
|
|
os = request.form['os']
|
|
ip = request.form['ip']
|
|
container=lxc.Container(nom)
|
|
resultats=container.create(os)
|
|
if request.form['ip']:
|
|
file_object = open('/var/lib/lxc/'+nom+'/config', 'a')
|
|
file_object.write('lxc.net.0.ipv4.address = '+ip+'\n')
|
|
file_object.write('lxc.net.0.ipv4.gateway = auto')
|
|
file_object.close()
|
|
if ( resultats == True ):
|
|
logging.info('CREATION - New contanier : '+nom+' - '+os+' ! ')
|
|
resultats='<p id="alert" style="color:green"><b>'+nom+'</b> '+lang_created+'</p>'
|
|
else:
|
|
if len(nom.split()) > 1:
|
|
logging.warning('CREATION FAILED - Too many word in <b>'+nom+'</b>, please use one word !')
|
|
resultats='<p id="alert" style="color:red">Too many word in <b>'+nom+'</b>, please use only one word !</p>'
|
|
else:
|
|
logging.warning('CREATION FAILED - Error on <b>'+nom+'</b> creation : '+os+' !')
|
|
resultats='<p id="alert" style="color:red">An Error append for <b>'+nom+'</b> !</p>'
|
|
return render_template('build.html',listvm=list_activ_vm(),list_net=conn.listNetworks(),listvm_iso=get_iso_list(),list_profiles=get_os_profile_list(),list_iso=get_iso_list(),list_iso_mount=get_iso_list(),loguser=session['username'],alertmessage=resultats,state_all=get_vm_state(),title="Build",listlxc=get_lxc_list(),listdistrib=list_distrib())
|
|
|
|
@app.route("/creationvm", methods=['POST'])
|
|
def create_VM():
|
|
nom = request.form['nom']
|
|
ram = request.form['ram']
|
|
cpu = request.form['cpu']
|
|
ose = request.form['os']
|
|
iso = request.form['iso']
|
|
iso = iso_path+iso
|
|
net = request.form['net']
|
|
disk = request.form['disk']
|
|
os.system('kill -9 $(ps -edf | grep pyxter | grep -v grep | awk \'{ print $2 }\')')
|
|
## VOIR TODO
|
|
##VERSION SERIE
|
|
# creationcmd='--name '+str(nom)+' --ram '+str(ram)+' --disk pool=default,size='+str(disk)+',bus=virtio,format=qcow2 --vcpus '+str(cpu)+' --os-type linux --os-variant '+str(ose)+' --network network:bridged --graphics none --console pty,target_type=serial --cdrom '+str(iso)+' --extra-args \'console=ttyS0,115200n8 serial\' --force --debug '
|
|
# os.system('/usr/bin/python3 -m pyxtermjs --command "virt-install" --host 0.0.0.0 --cmd-args "'+creationcmd+'" &')
|
|
##VERSION VNC
|
|
creationcmd='--name '+str(nom)+' --ram '+str(ram)+' --disk pool=default,size='+str(disk)+',bus=virtio,format=qcow2 --vcpus '+str(cpu)+' --os-type linux --os-variant '+str(ose)+' --network network:bridged --graphics vnc,listen=0.0.0.0 --noautoconsole --console pty,target_type=serial --cdrom '+str(iso)+' --force --debug '
|
|
os.system('virt-install'+creationcmd+'" &')
|
|
##
|
|
resultats='<p id="consolemessage" style="color:blue"><b>'+nom+'</b> '+lang_openconsole+'<button id="ModalBtn"><span class="fas fa-terminal"></span></button></p>'
|
|
return render_template('build.html',listvm=list_activ_vm(),list_net=conn.listNetworks(),listvm_iso=get_iso_list(),list_profiles=get_os_profile_list(),list_iso=get_iso_list(),list_iso_mount=get_iso_list(),loguser=session['username'],alertmessage=resultats,state_all=get_vm_state(),title="Build",listlxc=get_lxc_list(),listdistrib=list_distrib())
|
|
|
|
@app.route("/console",methods=['POST'])
|
|
def console():
|
|
mount_pts()
|
|
plx_console = request.form['console']
|
|
plx_console_state=lxc.Container(plx_console)
|
|
if ( plx_console_state.state == "STOPPED"):
|
|
resultats='<p id="alert" style="color:red"><b>'+plx_console+'</b> '+lang_console+' </p>'
|
|
return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all='<div class="card"><div class="card-header">Container</div><div class="card-body">'+get_lxc_state()+'</div></div><div class="card"><div class="card-header">Virtual Server</div><div class="card-body">'+get_vm_state()+"</div></div>",title="State",listlxc=get_lxc_list(),listdistrib=list_distrib())
|
|
os.system('kill -9 $(ps -edf | grep pyxter | grep -v grep | awk \'{ print $2 }\')')
|
|
os.system('/usr/bin/python3 -m pyxtermjs --command "lxc-attach" --cmd-args '+plx_console+' &')
|
|
time.sleep(2)
|
|
self_url=request.url_root
|
|
self_url=self_url.split(":")[1]
|
|
resultats='<p id="consolemessage" style="color:blue"><b>'+plx_console+'</b> '+lang_openconsole+'<button id="ModalBtn"><span class="fas fa-terminal"></span></button></p>'
|
|
return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all='<div class="card"><div class="card-header">Container</div><div class="card-body">'+get_lxc_state()+'</div></div><div class="card"><div class="card-header">Virtual Server</div><div class="card-body">'+get_vm_state()+"</div></div>",title="State",listlxc=get_lxc_list(),listdistrib=list_distrib())
|
|
|
|
@app.route("/consolevm",methods=['POST'])
|
|
def consolevm():
|
|
vm_console = request.form['consolevm']
|
|
dom=conn.lookupByName(vm_console)
|
|
if not conn:
|
|
raise SystemExit("Failed to open connection to Dom")
|
|
if dom.isActive():
|
|
os.system('kill -9 $(ps -edf | grep pyxter | grep -v grep | awk \'{ print $2 }\')')
|
|
os.system('/usr/bin/python3 -m pyxtermjs --command "virsh" --cmd-args "console '+vm_console+'" &')
|
|
time.sleep(2)
|
|
resultats='<p id="consolemessage" style="color:blue"><b>'+vm_console+'</b> '+lang_openconsole+'<button id="ModalBtn"><span class="fas fa-terminal"></span></button></p>'
|
|
|
|
else:
|
|
resultats='<p id="alert" style="color:red"><b>'+vm_console+'</b> '+lang_console+'</p>'
|
|
return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all='<div class="card"><div class="card-header">Containers</div><div class="card-body">'+get_lxc_state()+'</div></div><div class="card"><div class="card-header">Virtual Servers</div><div class="card-body">'+get_vm_state()+"</div></div>",title="State",listlxc=get_lxc_list(),listdistrib=list_distrib())
|
|
|
|
@app.route("/startct", methods=['POST'])
|
|
def start_ct():
|
|
mount_pts()
|
|
nom = request.form['start']
|
|
container=lxc.Container(nom)
|
|
if container.state=='RUNNING':
|
|
resultats='<p id="alert" style="color:blue"><b>'+nom+'</b> '+lang_already_started+'</p>';
|
|
else:
|
|
container.start()
|
|
container.wait("RUNNING", 3)
|
|
logging.info('START - Started '+nom+' !')
|
|
resultats='<p id="alert" style="color:blue"><b>'+nom+'</b> '+lang_started+'</p>';
|
|
return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all='<div class="card"><div class="card-header">Containers</div><div class="card-body">'+get_lxc_state()+'</div></div><div class="card"><div class="card-header">Virtual Servers</div><div class="card-body">'+get_vm_state()+"</div></div>",title="State",listlxc=get_lxc_list(),listdistrib=list_distrib())
|
|
|
|
@app.route("/stopct", methods=['POST'])
|
|
def stop_ct():
|
|
nom = request.form['stop']
|
|
container=lxc.Container(nom)
|
|
container.stop()
|
|
container.wait("STOPPED", 3)
|
|
logging.info('STOP - Stopped '+nom+' !')
|
|
resultats='<p id="alert" style="color:blue"><b>'+nom+'</b> '+lang_stopped+'</p>';
|
|
return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all='<div class="card"><div class="card-header">Containers</div><div class="card-body">'+get_lxc_state()+'</div></div><div class="card"><div class="card-header">Virtual Servers</div><div class="card-body">'+get_vm_state()+"</div></div>",title="State",listlxc=get_lxc_list(),listdistrib=list_distrib())
|
|
|
|
|
|
@app.route("/startvm", methods=['POST'])
|
|
def start_vm():
|
|
nom=request.form['startvm']
|
|
dom=conn.lookupByName(nom)
|
|
if dom.isActive():
|
|
resultats='<p id="alert" style="color:blue"><b>'+nom+'</b> '+lang_already_started+'</p>';
|
|
logging.info('START VM - Already tarted '+nom+' !')
|
|
else:
|
|
dom.create()
|
|
time.sleep(3)
|
|
alive=0
|
|
while alive < 3:
|
|
if dom.isActive():
|
|
alive=4
|
|
else:
|
|
logging.info('WAIT START VM - (TEST'+str(alive)+'/3)'+nom+' !')
|
|
time.sleep(3)
|
|
alive+=1
|
|
logging.info('START VM - Started '+nom+' !')
|
|
resultats='<p id="alert" style="color:blue"><b>'+nom+'</b> '+lang_started+'</p>';
|
|
return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all='<div class="card"><div class="card-header">Containers</div><div class="card-body">'+get_lxc_state()+'</div></div><div class="card"><div class="card-header">Virtual Servers</div><div class="card-body">'+get_vm_state()+"</div></div>",title="State",listlxc=get_lxc_list(),listdistrib=list_distrib())
|
|
|
|
@app.route("/stopvm", methods=['POST'])
|
|
def stop_vm():
|
|
nom=request.form['stopvm']
|
|
dom=conn.lookupByName(nom)
|
|
dom.shutdown()
|
|
time.sleep(3)
|
|
alive=0
|
|
while alive < 5:
|
|
if dom.isActive():
|
|
logging.info('WAIT STOP VM - (TEST'+str(alive)+'/5)'+nom+' !')
|
|
time.sleep(3)
|
|
alive+=1
|
|
else:
|
|
alive=6
|
|
resultats='<p id="alert" style="color:blue"><b>'+nom+'</b> '+lang_stopped+'</p>';
|
|
logging.info('STOP VM - Stopped'+nom+' !')
|
|
if dom.isActive():
|
|
#If not shutdown after 5 attempt, force stop (freeze VM, or OS not installed for example)
|
|
dom.destroy()
|
|
logging.info('ERROR STOP VM - Forced stopped'+nom+' !')
|
|
resultats='<p id="alert" style="color:red"><b>'+nom+'</b> '+lang_forced_stop+' </p>';
|
|
return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all=get_lxc_state()+"<br>"+get_vm_state(),title="State",listlxc=get_lxc_list(),listdistrib=list_distrib())
|
|
|
|
|
|
@app.route("/destroyct", methods=['POST'])
|
|
def destroy_ct():
|
|
nom = request.form['destroy']
|
|
container=lxc.Container(nom)
|
|
if ( container.state == "RUNNING"):
|
|
resultats='<p id="alert" style="color:red"><b>'+nom+'</b> is running, stop it first !</p>';
|
|
else:
|
|
container.stop()
|
|
container.wait("STOPPED", 3)
|
|
container.destroy()
|
|
alive=0
|
|
while alive < 3:
|
|
if (nom in get_lxc_list()):
|
|
logging.info('WAIT DESTROY CT - (TEST'+str(alive)+'/3)'+nom+' !')
|
|
time.sleep(3)
|
|
alive+=1
|
|
logging.info('ERROR DESTROY CT - '+nom+' !')
|
|
resultats='<p id="alert" style="color:red"><b>'+nom+'</b> Error on Destroy </p>';
|
|
else:
|
|
alive=4
|
|
logging.info('DESTROY - Destroyed '+nom+' !')
|
|
resultats='<p id="alert" style="color:blue"><b>'+nom+'</b> '+lang_destroyed+'</p>';
|
|
return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all=get_lxc_state()+"<br>"+get_vm_state(),title="State",listlxc=get_lxc_list(),listdistrib=list_distrib())
|
|
|
|
@app.route("/destroyvm", methods=['POST'])
|
|
def destroy_vm():
|
|
nom=request.form['destroyvm']
|
|
dom=conn.lookupByName(nom)
|
|
if dom.isActive()==True:
|
|
resultats='<p id="alert" style="color:red"><b>'+nom+'</b> '+lang_console2+'</p>';
|
|
else:
|
|
dom.undefine()
|
|
time.sleep(3)
|
|
resultats='<p id="alert" style="color:blue"><b>'+nom+'</b> '+lang_destroyed+'</p>';
|
|
logging.info('DESTROY VM - Destoryed'+nom+' !')
|
|
return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all='<div class="card"><div class="card-header">Containers</div><div class="card-body">'+get_lxc_state()+'</div></div><div class="card"><div class="card-header">Virtual Servers</div><div class="card-body">'+get_vm_state()+"</div></div>",title="State",listlxc=get_lxc_list(),listdistrib=list_distrib())
|
|
|
|
@app.route("/renamect", methods=['POST'])
|
|
def rename_ct():
|
|
mount_pts()
|
|
nom=request.form['nom']
|
|
newname=request.form['newname']
|
|
if len(newname.split()) > 1:
|
|
logging.warning('RENAME FAILED - Too many word in '+nom+', please use one word !')
|
|
resultats='<p id="alert" style="color:red">Too many word in <b>'+newname+'</b>, please use only one word !</p>'
|
|
else:
|
|
container=lxc.Container(nom)
|
|
container.stop()
|
|
container.wait("STOPPED", 3)
|
|
container.rename(newname)
|
|
logging.info('RENAME - '+nom+' is now known as '+newname+' !')
|
|
resultats='<p id="alert" style="color:blue"><b>'+nom+'</b> is known as <b>'+newname+'</b> ! </p>'
|
|
return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all=get_lxc_state()+"<br>"+get_vm_state(),title="State",listlxc=get_lxc_list(),listdistrib=list_distrib())
|
|
|
|
@app.route('/login', methods=['GET', 'POST'])
|
|
def login():
|
|
if request.method == 'POST':
|
|
username = request.form['username']
|
|
password = request.form['password']
|
|
if authenticate(str(username), str(password)):
|
|
session['username'] = request.form['username']
|
|
logging.info('AUTH LOG - New auth from '+username+' !')
|
|
return redirect(url_for('index'))
|
|
else:
|
|
resultats='<p id="alert" style="color:red">Invalid Username/Password ! </p>'
|
|
return render_template('login.html', alertmessage=resultats)
|
|
|
|
@app.route('/logout')
|
|
def logout():
|
|
session.pop('username', None)
|
|
return redirect(url_for('index'))
|
|
|
|
# set the secret key. keep this really secret:
|
|
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
|
|
|
|
|
|
if __name__ == '__main__':
|
|
app.run(host=flask_host, port=flask_port, threaded=flask_thread, debug=flask_debug)
|
|
|