Adding Network and Small corrections
This commit is contained in:
		
							parent
							
								
									a3b7ef628e
								
							
						
					
					
						commit
						843555a9d5
					
				
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								functions/__pycache__/fnet.cpython-311.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								functions/__pycache__/fnet.cpython-311.pyc
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -67,8 +67,10 @@ def create_attached_disk(vm_name,disk_name,disk_size,disk_id): | ||||
|   pool.createXML(xml_desc, 0) | ||||
| 
 | ||||
|   dom = conn.lookupByName(vm_name) | ||||
|   if not dom.isActive(): | ||||
|     dom.create() | ||||
|   try: | ||||
|     dom.resume | ||||
|   except: | ||||
|     pass | ||||
|   disk_full = disk_path+disk_name+".qcow2" | ||||
|   flags = (libvirt.VIR_DOMAIN_AFFECT_CONFIG | | ||||
|            libvirt.VIR_DOMAIN_AFFECT_LIVE | | ||||
|  | ||||
							
								
								
									
										99
									
								
								functions/fedit.py.ori
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								functions/fedit.py.ori
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,99 @@ | ||||
| from config import * | ||||
| import base64 | ||||
| import time | ||||
| import lxc | ||||
| 
 | ||||
| def get_version(): | ||||
|   vlxc = lxc.version | ||||
|   vlibvirt = str(libvirt.getVersion()/1000000) #1000000 * major + 1000 * minor + release | ||||
|   vhype = hype_version | ||||
|   return vlxc, vlibvirt, vhype | ||||
| 
 | ||||
| 
 | ||||
| def set_memory(vm_name,memory_new): | ||||
|   dom = conn.lookupByName(vm_name) | ||||
|   dom.shutdown() | ||||
|   time.sleep(3) | ||||
|   alive=0 | ||||
|   while alive < 5: | ||||
|       if dom.isActive(): | ||||
|           time.sleep(3) | ||||
|           alive+=1 | ||||
|       else: | ||||
|           alive=6 | ||||
|   if dom.isActive(): | ||||
|       dom.destroy() | ||||
|   dom.setMaxMemory(memory_new) | ||||
|   dom.setMemoryFlags(memory_new) | ||||
|   dom.create() | ||||
|   time.sleep(3) | ||||
|   alive=0 | ||||
|   while alive < 3: | ||||
|       if dom.isActive(): | ||||
|           alive=4 | ||||
|       else: | ||||
|           time.sleep(3) | ||||
|           alive+=1 | ||||
| 
 | ||||
| def set_vcpu(vm_name,vcpu_new): | ||||
|   dom = conn.lookupByName(vm_name) | ||||
|   dom.shutdown() | ||||
|   time.sleep(3) | ||||
|   alive=0 | ||||
|   while alive < 5: | ||||
|       if dom.isActive(): | ||||
|           time.sleep(3) | ||||
|           alive+=1 | ||||
|       else: | ||||
|           alive=6 | ||||
|   if dom.isActive(): | ||||
|       dom.destroy() | ||||
|   dom.setVcpusFlags(vcpu_new,libvirt.VIR_DOMAIN_AFFECT_CONFIG | libvirt.VIR_DOMAIN_VCPU_MAXIMUM) | ||||
|   dom.setVcpusFlags(vcpu_new,libvirt.VIR_DOMAIN_AFFECT_CONFIG | libvirt.VIR_DOMAIN_VCPU_CURRENT) | ||||
|   dom.create() | ||||
|   time.sleep(3) | ||||
|   alive=0 | ||||
|   while alive < 3: | ||||
|       if dom.isActive(): | ||||
|           alive=4 | ||||
|       else: | ||||
|           time.sleep(3) | ||||
|           alive+=1 | ||||
| 
 | ||||
| def get_info_vm(vm_name): | ||||
|   dom = conn.lookupByName(vm_name) | ||||
|   state, maxmem, mem, cpus, cput = dom.info() | ||||
|   return state, maxmem, mem, cpus, cput | ||||
| 
 | ||||
| #Screenshot | ||||
| def get_screenshot(vm_name): | ||||
|   dom = conn.lookupByName(vm_name) | ||||
|   stream = conn.newStream() | ||||
|   imageType = dom.screenshot(stream,0) | ||||
|   file = "tmp_screen_" + dom.name() | ||||
|   fileHandler = open(file, 'wb') | ||||
|   streamBytes = stream.recv(262120) | ||||
|   while streamBytes != b'': | ||||
|     fileHandler.write(streamBytes) | ||||
|     streamBytes = stream.recv(262120) | ||||
|   fileHandler.close() | ||||
|   stream.finish() | ||||
|   with open(file, "rb") as f: | ||||
|     data = base64.b64encode(f.read()) | ||||
|   os.remove(file) | ||||
|   return data | ||||
| 
 | ||||
| #Autostart | ||||
| 
 | ||||
| def get_autostart(vm_name): | ||||
|   dom = conn.lookupByName(vm_name) | ||||
|   return dom.autostart() | ||||
| 
 | ||||
| def set_autostart(vm_name): | ||||
|   dom = conn.lookupByName(vm_name) | ||||
|   dom.setAutostart(1) | ||||
| 
 | ||||
| def unset_autostart(vm_name): | ||||
|   dom = conn.lookupByName(vm_name) | ||||
|   dom.setAutostart(0) | ||||
| 
 | ||||
| @ -61,3 +61,21 @@ def destroy_lxc(lxc_name): | ||||
|     container=lxc.Container(lxc_name) | ||||
|     container.destroy() | ||||
| 
 | ||||
| ## RESSOURCES | ||||
| 
 | ||||
| def get_lxc_ressources(lxc_name): | ||||
|     container=lxc.Container(lxc_name) | ||||
|     mem_max = container.get_config_item('lxc.cgroup2.memory.max') | ||||
|     mem = container.get_config_item('lxc.cgroup2.memory.high') | ||||
|     swap_max = container.get_config_item('lxc.cgroup2.memory.swap.max') | ||||
|     vcpu = container.get_config_item('lxc.cgroup2.cpuset.cpus') | ||||
|     return vcpu, mem, mem_max, swap_max | ||||
| 
 | ||||
| def set_lxc_ressources(lxc_name,lxc_item,val): | ||||
|     container=lxc.Container(lxc_name) | ||||
|     container.set_config_item(lxc_item,val) | ||||
|     container.save_config() | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										70
									
								
								functions/fnet.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								functions/fnet.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,70 @@ | ||||
| from app import * | ||||
| import ipaddress | ||||
| from xml.dom import minidom | ||||
| 
 | ||||
| def diff_net(min_dhcp,max_dhcp): | ||||
|     ip1 = ipaddress.IPv4Address(min_dhcp) | ||||
|     ip2 = ipaddress.IPv4Address(max_dhcp) | ||||
|     nb_ip = int(ip2) - int(ip1) + 1 | ||||
|     return nb_ip | ||||
| 
 | ||||
| def get_int(net_name): | ||||
|   network = conn.networkLookupByName(net_name) | ||||
|   net_int = network.bridgeName() | ||||
|   return net_int | ||||
| 
 | ||||
| def create_vswitch_int(net_int): | ||||
|   cmd="ovs-vsctl add-br "+net_int | ||||
|   subprocess.call(cmd, shell=True) | ||||
| 
 | ||||
| def delete_network(net_name,net_int): | ||||
|    cmd = "ovs-vsctl del-br "+net_int | ||||
|    subprocess.call(cmd, shell=True) | ||||
|    network = conn.networkLookupByName(net_name)  #Lapin | ||||
|    network.destroy() | ||||
|    network.undefine() | ||||
|    cmd2="kill $(cat /run/dhypecp_"+net_int+".pid)" | ||||
|    subprocess.call(cmd2, shell=True) | ||||
|    cmd3="rm -f /run/dhypecp_"+net_int+".pid" | ||||
|    subprocess.call(cmd3, shell=True) | ||||
| 
 | ||||
| def create_network(net_name,net_int): | ||||
|     create_vswitch_int(net_int) | ||||
|     xml = f""" | ||||
|      <network> | ||||
|        <name>{ net_name }</name> | ||||
|        <forward mode='bridge'/> | ||||
|        <bridge name='{ net_int }'/> | ||||
|        <virtualport type='openvswitch'/> | ||||
|      </network> | ||||
|     """ | ||||
|     conn.networkDefineXML(xml) | ||||
|     net_use = conn.networkLookupByName(net_name) | ||||
|     net_use.create() | ||||
|     net_use.setAutostart(True) | ||||
| 
 | ||||
| def list_network_VM(): | ||||
|    net_tree = [] | ||||
|    net_na = [] | ||||
| #Host Interfaces | ||||
|    net_hard_int = conn.listInterfaces() | ||||
| #Virtual Interfaces | ||||
|    net_list = conn.listAllNetworks() | ||||
|    for net_name in net_list: | ||||
|      if net_name.isActive(): | ||||
|        net_sub_tree=[] | ||||
|        net_sub_tree.append(net_name.name()) | ||||
|        net_use = conn.networkLookupByName(net_name.name()) | ||||
|        ports = net_use.listAllPorts() | ||||
|        net_ports = [] | ||||
|        for port in ports: | ||||
|          raw_xml = port.XMLDesc() | ||||
|          net_xml = minidom.parseString(raw_xml) | ||||
|          net_element = net_xml.documentElement | ||||
|          net_VM = net_element.getElementsByTagName("name")[0] | ||||
|          net_ports.append(net_VM.firstChild.data) | ||||
|        net_sub_tree.append(net_ports) | ||||
|        net_tree.append(net_sub_tree) | ||||
|      else: | ||||
|        net_na.append(net_name.name()) | ||||
|    return net_hard_int,net_tree,net_na | ||||
| @ -9,6 +9,14 @@ def get_vm_activ(): | ||||
|        activ_vm.append(dom.name()) | ||||
|     return activ_vm | ||||
| 
 | ||||
| #Set a VM as active | ||||
| def is_active(vm_name): | ||||
|   dom = conn.lookupByName(vm_name) | ||||
|   try: | ||||
|     dom.resume() | ||||
|   except: | ||||
|     pass | ||||
| 
 | ||||
| def get_vm_inactiv(): | ||||
|     inactiv_vm=conn.listDefinedDomains() | ||||
|     return inactiv_vm | ||||
|  | ||||
							
								
								
									
										36
									
								
								templates/createnet.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								templates/createnet.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| {% 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-solid fa-ethernet"></i> - Build Network | ||||
|                                 </div> | ||||
|                                 <div class="card-body"> | ||||
| 
 | ||||
| 		<form action="/createint" method="post"> | ||||
|                 <label for="net_name">Network name (no space)</label> | ||||
|                 <input type="text" id="net_name" name="net_name" class="form-control" placeholder="no_net" required><br> | ||||
|                 <label for="net_int">Interface name (no space)</label> | ||||
|                 <input type="text" id="net_int" name="net_int" class="form-control" placeholder="example veth0" required><br> | ||||
|                 <label for="ip_int">Interface IP</label> | ||||
|                 <input type="text" id="ip_int" name="ip_int" class="form-control" placeholder="example: 10.2.0.1" required><br> | ||||
|                 <label for="mask_int">Interface mask</label> | ||||
|                 <input type="text" id="mask_int" name="mask_int" class="form-control" placeholder="example: 255.255.255.0" required><br> | ||||
|                 <strong>DHCP Configuration</strong> | ||||
|                 <label for="min_dhcp">DHCP minimum IP</label> | ||||
|                 <input type="text" id="min_dhcp" name="min_dhcp" class="form-control" placeholder="example: 10.2.0.2" required><br> | ||||
|                 <label for="max_dhcp">DHCP maximum IP</label> | ||||
|                 <input type="text" id="max_dhcp" name="max_dhcp" class="form-control" placeholder="example: 10.2.0.254" required><br> | ||||
|                 <button name="creation" class="btn btn-outline-secondary  btn-hype" type="submit" onclick="loading();">Create</button> | ||||
|         	</form> | ||||
| 
 | ||||
|                                 </div> | ||||
|                         </div> | ||||
|                 </div> | ||||
|         </div> | ||||
| <br> | ||||
| 
 | ||||
| {% endblock %} | ||||
							
								
								
									
										36
									
								
								templates/edit_lxc.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								templates/edit_lxc.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| {% extends 'layout.html' %} | ||||
| {% block content %} | ||||
| {% include 'menu.html' %} | ||||
| <div class="container"> | ||||
|        <div class="card"> | ||||
|                 <div class="card-header"> | ||||
| 		Ressources of {{ lxc_name }} | ||||
|                 </div> | ||||
|         	<div class="card-body"> | ||||
| 			<div class="row"> | ||||
|     				<div class="col-sm"> | ||||
|       					<i class="fa-solid fa-microchip"></i> vCPU : {{ max_vCPU }}</br></br> | ||||
| 					<i class="fa-solid fa-memory"></i> Memory: {{ actual_ram }}</br></br> | ||||
| 					<i class="fa-solid fa-memory"></i> Max Memory: {{ max_Mermory }}</br></br> | ||||
| 					<i class="fa-solid fa-memory"></i> Swap: {{ max_swap }}</br></br> | ||||
|     				</div> | ||||
| 
 | ||||
|     				<div class="col-sm"> | ||||
| 				<form action="/editressourceslxc" method="post"> | ||||
|                                         <input type="hidden" name="lxc_name" value="{{ lxc_name }}"></input> | ||||
|       					<table><tr><td>CPU :</td><td><input type="text" name="new_cpu" class="form-control form-control-sm" placeholder="{{ max_vCPU }}" value="{{ max_vCPU }}" ></input></td></tr></table><br> | ||||
|       					<table><tr><td>Memory :</td><td><input type="text" name="new_mem" class="form-control form-control-sm" placeholder="{{ actual_ram }}" value="{{ actual_ram }}" ></input></td></tr></table><br> | ||||
|       					<table><tr><td>Max Memory :</td><td><input type="text" name="new_max_mem" class="form-control form-control-sm" placeholder="{{ max_Mermory }}" value="{{ max_Mermory }}" ></input></td></tr></table><br> | ||||
|       					<table><tr><td>Swap :</td><td><input type="text" name="new_max_swap" class="form-control form-control-sm" placeholder="{{ max_swap }}" value="{{ max_swap }}" ></input></td></tr></table><br>				 | ||||
| 					<br><br> | ||||
| 					<button type="submit" class="btn btn-outline-warning btn-hype"><i class="fa-solid fa-pencil"></i></button> | ||||
| 					</form>	 | ||||
| 				</div> | ||||
| 			</div> | ||||
| 			 | ||||
|         	</div> | ||||
| 	</div> | ||||
| <br> | ||||
| </div> | ||||
| 
 | ||||
| {% endblock %} | ||||
| @ -22,6 +22,9 @@ | ||||
|       <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> | ||||
|       <li class="nav-link"> | ||||
|         <a class="nav-link text-body text-decoration-none fw-light" href="/network"><i class="fa-solid fa-network-wired"></i> Network</a> | ||||
|       </li> | ||||
| 
 | ||||
|     </ul> | ||||
|   </div> | ||||
|  | ||||
							
								
								
									
										51
									
								
								templates/network.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								templates/network.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | ||||
| {% extends 'layout.html' %} | ||||
| {% block content %} | ||||
| {% include 'menu.html' %} | ||||
| <center> | ||||
| <a href="/createnet" class="btn btn-outline-danger"><i class="fa-solid fa-plus"></i> Add Network</a></br></br></br> | ||||
| <div class="container"> | ||||
| Physical Interfaces: | ||||
|         <div class="row justify-content-md-center"> | ||||
|             <div class="col-md-6"> | ||||
|                 <ul class="list-group"> | ||||
| 			<li class="list-group-item bg-primary text-dark"> | ||||
|                         {% for pint in net_hard_int %} | ||||
|                                 <strong><i class="fa-solid fa-ethernet"></i> {{ pint }}</strong><br> | ||||
|                         {% endfor %} | ||||
|                         </li> | ||||
| 		</ul> | ||||
|             </div> | ||||
| 	</div> | ||||
| </div></br> | ||||
| <div class="container"> | ||||
| Virtual Interfaces: | ||||
|         <div class="row justify-content-md-center"> | ||||
|             <div class="col-md-6"> | ||||
|                 <ul class="list-group"> | ||||
| 		    {% for noac in net_na %} | ||||
| 			<li class="list-group-item bg-secondary text-dark"> | ||||
| 			<strong><i class="fa-solid fa-ethernet"></i> {{ noac }} Not active</strong><br> | ||||
| 			</li> | ||||
|                     {% endfor %} | ||||
|                     {% for item in net_tree %} | ||||
|                         <li class="list-group-item bg-info text-dark"> | ||||
|                             <strong><i class="fa-solid fa-ethernet"></i> {{ item[0] }}</strong> | ||||
| 				<form action="/delnet" method="post"> | ||||
| 			                <input type="hidden" id="net_del" name="net_del" class="form-control" value="{{ item[0] }}"> | ||||
| 			                <button name="delete" class="btn btn-outline-secondary" type="submit" onclick="loading();">Delete</button> | ||||
| 				</form><br> | ||||
|                             <ul class="list-group"> | ||||
|                                 {% for sub_item in item[1] %} | ||||
|                                     <li class="list-group-item bg-warning text-dark"> | ||||
| 					<i class="fa-solid fa-desktop"></i> {{ sub_item }} | ||||
| 				    </li> | ||||
|                                 {% endfor %} | ||||
|                             </ul> | ||||
|                         </li> | ||||
|                     {% endfor %} | ||||
|                 </ul> | ||||
|             </div> | ||||
|         </div> | ||||
| </div> | ||||
| </center> | ||||
| {% endblock %} | ||||
							
								
								
									
										56
									
								
								templates/network.html.ori
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								templates/network.html.ori
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,56 @@ | ||||
| {% extends 'layout.html' %} | ||||
| {% block content %} | ||||
| {% include 'menu.html' %} | ||||
| <!-- | ||||
| <div class="container"> | ||||
|         <div class="row justify-content-md-center"> | ||||
|             <div class="col"> | ||||
|                 <ul class="list-group"> | ||||
| 			<li class="list-group-item bg-primary text-dark"> | ||||
| 			Physical interface | ||||
| 			<center> | ||||
| 			{% for pint in net_hard_int %} | ||||
| 				<strong><i class="fa-solid fa-ethernet"></i> {{ pint }}</strong><br> | ||||
| 			{% endfor %} | ||||
| 			</center></li> | ||||
|                     {% for item in net_tree %} | ||||
|                         <li class="list-group-item bg-info text-dark"> | ||||
|                             <center><strong><i class="fa-solid fa-ethernet"></i> {{ item[0] }}</strong></center><br> | ||||
|                             <ul class="list-group"> | ||||
|                                 {% for sub_item in item[1] %} | ||||
|                                     <li class="list-group-item bg-warning text-dark"> | ||||
| 					<center><i class="fa-solid fa-desktop"></i> {{ sub_item }}</center> | ||||
| 				    </li> | ||||
|                                 {% endfor %} | ||||
|                             </ul> | ||||
|                         </li> | ||||
|                     {% endfor %} | ||||
|                 </ul> | ||||
|             </div> | ||||
|         </div> | ||||
| </div> | ||||
| --> | ||||
|     <div class="container"> | ||||
| 	<div class="row justify-content-md-center"> | ||||
|             <div class="col"> | ||||
|             {% for pint in net_hard_int %} | ||||
|                 <strong><i class="fa-solid fa-ethernet"></i> {{ pint }}</strong><br> | ||||
|             {% endfor %} | ||||
| 	    </div> | ||||
| 	</div> | ||||
|         <div class="row justify-content-md-center"> | ||||
|             <div class="col"> | ||||
|                 <div class="mermaid"> | ||||
| graph TD | ||||
| {% for item in net_tree %} | ||||
| root[Root] --- {{ item[0] }}[{{ item[0] }}] | ||||
| {% for sub_item in item[1] %} | ||||
| {{ item[0] }}[{{ item[0] }}] --- {{ sub_item }}[{{ sub_item }}] | ||||
| {% endfor %} | ||||
| {% endfor %} | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
|     <script>mermaid.initialize({startOnLoad:true});</script> | ||||
| {% endblock %} | ||||
| @ -20,6 +20,8 @@ | ||||
| </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> | ||||
|         <form action="/editlxc" method="post"><button type="submit" class="btn btn-outline-warning btn-hype" value="{{ act_lxc[0] }}" name="edit"  onclick="loading();"><i class="fa-solid fa-wrench"></i></button></form> | ||||
| 
 | ||||
| </td><td> | ||||
| </td><td> | ||||
|         {{act_lxc[1]}} | ||||
| @ -42,6 +44,7 @@ | ||||
| </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> | ||||
|         <form action="/editlxc" method="post"><button type="submit" class="btn btn-outline-warning btn-hype" value="{{ inact_lxc }}" name="edit"  onclick="loading();"><i class="fa-solid fa-wrench"></i></button></form> | ||||
| </td><td> | ||||
| </td><td>        - | ||||
| </td></tr> | ||||
| @ -99,7 +102,8 @@ | ||||
| </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> | ||||
|          <form action="/editvm" method="post"><button type="submit" class="btn btn-outline-warning btn-hype disabled" value="{{ inact_vm[0] }}" name="edit"  onclick="loading();"><i class="fa-solid fa-wrench"></i></button></form> | ||||
|          <form action="/editvm" method="post"><button type="submit" class="btn btn-outline-warning btn-hype" value="{{ inact_vm[0] }}" name="edit"  onclick="loading();"><i class="fa-solid fa-wrench"></i></button></form> | ||||
| <!--         <form action="/editvm" method="post"><button type="submit" class="btn btn-outline-warning btn-hype disabled" value="{{ inact_vm[0] }}" name="edit"  onclick="loading();"><i class="fa-solid fa-wrench"></i></button></form> --> | ||||
| </td><td> | ||||
| {% if inact_vm[1] == 1 %} | ||||
| <table class="table table-borderless"><tr><th> | ||||
|  | ||||
| @ -1,8 +1,8 @@ | ||||
| {% extends 'layout.html' %} | ||||
| {% block content %} | ||||
| {% include 'menu.html' %} | ||||
| <a href="/ter" target="_blank"><i class="fa-solid fa-expand"></i></a></br> | ||||
| 
 | ||||
| <center><a href="/ter" target="_blank" class="btn btn-outline-info"> Full screen  <i class="fa-solid fa-expand"></i></a></br> | ||||
| <br> | ||||
| <iframe src="/ter" height=768px width=1024px class="embed-responsive-item" allowfullscreen></iframe> | ||||
| 
 | ||||
| {% endblock %} | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user