#!/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='

'+item+' had been deleted !

' else: resultats='

'+item+' could not been deleted !

' 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='

'+cont+''+lang_console2+'

' else: item=request.form['restore'] item=item.split('_')[2] out=ct.snapshot_restore(item) if out: resultats='

'+item+' had been restored !

' else: resultats='

'+item+' could not been restored !

' 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='

'+item+' had been deleted !

' else: resultats='

'+item+' 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', '
') 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 = """

""" 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='

ISO mounted !

' 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='

ISO had been ejected !

' return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all='
Containers
'+get_lxc_state()+'
Virtual Servers
'+get_vm_state()+"
",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='' ##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+"' pool_html=pool_html+'

Pool: "+pool.name()+"
UUID: "+pool.UUIDString()+"
Autostart: "+str(pool.autostart())+"
Is active: "+str(pool.isActive())+"
Is persistent: "+str(pool.isPersistent())+"
Num volumes: "+str(pool.numOfVolumes())+"
Pool state: "+str(info[0])+"
Capacity: "+str(convert_size(info[1]))+"
Allocation: "+str(convert_size(info[2]))+"
Available: "+str(convert_size(info[3]))+'
' 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='' ##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+"" volume_html=volume_html+"
PoolVolume NameCapacityAllocationDeleteChart
"+pools+""+volume+""+str(convert_size(info[1]))+""+ str(convert_size(info[2]))+"" volume_html=volume_html+"
" 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)+"%
User: "+str(cpu_usage.user)+"%
Idle: "+str(cpu_usage.idle)+"%
IO wait: "+str(cpu_usage.iowait)+"%
" 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))+"
Free: "+str(convert_size(memory_usage['free']*1024))+"
Buffers: "+str(convert_size(memory_usage['buffers']*1024))+"
Cached: "+str(convert_size(memory_usage['cached']*1024))+"
".format(**memory_usage) return memory_usage_html, mem_percent_used, mem_percent_free def vm_monit(): vm_monit_html='' 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+"" vm_monit_html=vm_monit_html+"
NomState
"+dom.name()+""+str(state)+"
Max memory : "+ str(convert_size(maxmem*1024))+"
Memory : "+ str(convert_size(mem*1024)) vm_monit_html=vm_monit_html+"
CPU number : "+str(cpus)+"
CPU time : "+str(cput)+"
" return vm_monit_html def lxc_monit(): ct_monit_html='' 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+"" ct_monit_html=ct_monit_html+"
NomState
"+lxc_name+""+ct.state+"
Memory : "+ct_meme+"%" ct_monit_html=ct_monit_html+"
CPU : "+ct_cpu+"%
" 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='

'+ct_state.state+'

' else: color_ct_state='

'+ct_state.state+'

' out=out+''+ct_name+'' out=out+color_ct_state+'
' out=out+str(ct_state.get_ips()).replace('(', '').replace(')', '').replace(',', '').replace('\'', '')+'' out=''+out+'
NameStateActionsIP
' 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='

' else: disk_color='

' color_vm_state='

RUNNING

' out=out+''+activ_vm+'' out=out+color_vm_state+'
' out=out+get_vm_ips(activ_vm)+''+disk_color+'' for inactiv_vm in list_inactiv_vm(): color_vm_state='

STOPPED

' out=out+''+inactiv_vm+'' out=out+color_vm_state+'
' out=out+'IP' out=''+out+'
NameStateActionsIPDisk
' 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='
Containers
'+get_lxc_state()+'
Virtual Servers
'+get_vm_state()+"
",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 = """ {snapshot_name} """ dom.snapshotCreateXML(SNAPSHOT_XML_TEMPLATE.format(snapshot_name=snapshot_name),libvirt.VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC) if dom.snapshotCurrent().getName()==snapshot_name: resultats='

'+nom+' '+lang_snapvm+'

' else: resultats='

'+nom+' '+lang_snapvm_failed+'

' 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='

'+nom+' '+lang_snapvm+'

' except: resultats='

'+nom+' Snapshot Failed !

' else: resultats='

'+nom+' Should be stopped first !

' 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='

'+f.filename+' '+lang_uploaded+'

' 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='

'+file+' '+lang_deleted+'

' 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='

'+nom+' '+lang_created+'

' else: if len(nom.split()) > 1: logging.warning('CREATION FAILED - Too many word in '+nom+', please use one word !') resultats='

Too many word in '+nom+', please use only one word !

' else: logging.warning('CREATION FAILED - Error on '+nom+' creation : '+os+' !') resultats='

An Error append for '+nom+' !

' 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='

'+nom+' '+lang_openconsole+'

' 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='

'+plx_console+' '+lang_console+'

' return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all='
Container
'+get_lxc_state()+'
Virtual Server
'+get_vm_state()+"
",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='

'+plx_console+' '+lang_openconsole+'

' return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all='
Container
'+get_lxc_state()+'
Virtual Server
'+get_vm_state()+"
",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='

'+vm_console+' '+lang_openconsole+'

' else: resultats='

'+vm_console+' '+lang_console+'

' return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all='
Containers
'+get_lxc_state()+'
Virtual Servers
'+get_vm_state()+"
",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='

'+nom+' '+lang_already_started+'

'; else: container.start() container.wait("RUNNING", 3) logging.info('START - Started '+nom+' !') resultats='

'+nom+' '+lang_started+'

'; return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all='
Containers
'+get_lxc_state()+'
Virtual Servers
'+get_vm_state()+"
",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='

'+nom+' '+lang_stopped+'

'; return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all='
Containers
'+get_lxc_state()+'
Virtual Servers
'+get_vm_state()+"
",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='

'+nom+' '+lang_already_started+'

'; 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='

'+nom+' '+lang_started+'

'; return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all='
Containers
'+get_lxc_state()+'
Virtual Servers
'+get_vm_state()+"
",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='

'+nom+' '+lang_stopped+'

'; 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='

'+nom+' '+lang_forced_stop+'

'; return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all=get_lxc_state()+"
"+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='

'+nom+' is running, stop it first !

'; 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='

'+nom+' Error on Destroy

'; else: alive=4 logging.info('DESTROY - Destroyed '+nom+' !') resultats='

'+nom+' '+lang_destroyed+'

'; return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all=get_lxc_state()+"
"+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='

'+nom+' '+lang_console2+'

'; else: dom.undefine() time.sleep(3) resultats='

'+nom+' '+lang_destroyed+'

'; logging.info('DESTROY VM - Destoryed'+nom+' !') return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all='
Containers
'+get_lxc_state()+'
Virtual Servers
'+get_vm_state()+"
",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='

Too many word in '+newname+', please use only one word !

' else: container=lxc.Container(nom) container.stop() container.wait("STOPPED", 3) container.rename(newname) logging.info('RENAME - '+nom+' is now known as '+newname+' !') resultats='

'+nom+' is known as '+newname+' !

' return render_template('state.html',loguser=session['username'],alertmessage=resultats,state_all=get_lxc_state()+"
"+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='

Invalid Username/Password !

' 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)